Merge "AAPT2: Support building, linking, and merging static libraries" into nyc-dev
diff --git a/api/current.txt b/api/current.txt
index 73e7fab..799ad0f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5258,7 +5258,7 @@
   }
 
   public static class NotificationManager.Policy implements android.os.Parcelable {
-    ctor public deprecated NotificationManager.Policy(int, int, int);
+    ctor public NotificationManager.Policy(int, int, int);
     ctor public NotificationManager.Policy(int, int, int, int);
     method public int describeContents();
     method public static java.lang.String priorityCategoriesToString(int);
@@ -10466,7 +10466,6 @@
     method public boolean hasNext();
     method public java.util.Iterator<android.database.CursorJoiner.Result> iterator();
     method public android.database.CursorJoiner.Result next();
-    method public void remove();
   }
 
   public static final class CursorJoiner.Result extends java.lang.Enum {
@@ -19867,7 +19866,7 @@
 
   public static abstract class AudioManager.AudioRecordingCallback {
     ctor public AudioManager.AudioRecordingCallback();
-    method public void onRecordConfigChanged();
+    method public void onRecordConfigChanged(android.media.AudioRecordConfiguration[]);
   }
 
   public static abstract interface AudioManager.OnAudioFocusChangeListener {
@@ -31715,6 +31714,7 @@
 
   public static final class DocumentsContract.Root {
     field public static final java.lang.String COLUMN_AVAILABLE_BYTES = "available_bytes";
+    field public static final java.lang.String COLUMN_CAPACITY_BYTES = "capacity_bytes";
     field public static final java.lang.String COLUMN_DOCUMENT_ID = "document_id";
     field public static final java.lang.String COLUMN_FLAGS = "flags";
     field public static final java.lang.String COLUMN_ICON = "icon";
@@ -38478,7 +38478,6 @@
     method public boolean hasNext();
     method public java.util.Iterator<java.lang.String> iterator();
     method public java.lang.String next();
-    method public void remove();
     method public void setString(java.lang.String);
   }
 
@@ -57714,9 +57713,10 @@
   }
 
   public abstract interface Iterator {
+    method public default void forEachRemaining(java.util.function.Consumer<? super E>);
     method public abstract boolean hasNext();
     method public abstract E next();
-    method public abstract void remove();
+    method public default void remove();
   }
 
   public class LinkedHashMap extends java.util.HashMap implements java.util.Map {
@@ -58067,6 +58067,31 @@
     method public long orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
   }
 
+  public abstract interface PrimitiveIterator implements java.util.Iterator {
+    method public abstract void forEachRemaining(T_CONS);
+  }
+
+  public static abstract interface PrimitiveIterator.OfDouble implements java.util.PrimitiveIterator {
+    method public default void forEachRemaining(java.util.function.DoubleConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Double>);
+    method public default java.lang.Double next();
+    method public abstract double nextDouble();
+  }
+
+  public static abstract interface PrimitiveIterator.OfInt implements java.util.PrimitiveIterator {
+    method public default void forEachRemaining(java.util.function.IntConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Integer>);
+    method public default java.lang.Integer next();
+    method public abstract int nextInt();
+  }
+
+  public static abstract interface PrimitiveIterator.OfLong implements java.util.PrimitiveIterator {
+    method public default void forEachRemaining(java.util.function.LongConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Long>);
+    method public default java.lang.Long next();
+    method public abstract long nextLong();
+  }
+
   public class PriorityQueue extends java.util.AbstractQueue implements java.io.Serializable {
     ctor public PriorityQueue();
     ctor public PriorityQueue(int);
@@ -58238,7 +58263,6 @@
     method public short nextShort();
     method public short nextShort(int);
     method public int radix();
-    method public void remove();
     method public java.util.Scanner reset();
     method public java.util.Scanner skip(java.util.regex.Pattern);
     method public java.util.Scanner skip(java.lang.String);
diff --git a/api/system-current.txt b/api/system-current.txt
index e5ebe62..9a84d1a 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5390,7 +5390,7 @@
   }
 
   public static class NotificationManager.Policy implements android.os.Parcelable {
-    ctor public deprecated NotificationManager.Policy(int, int, int);
+    ctor public NotificationManager.Policy(int, int, int);
     ctor public NotificationManager.Policy(int, int, int, int);
     method public int describeContents();
     method public static java.lang.String priorityCategoriesToString(int);
@@ -10860,7 +10860,6 @@
     method public boolean hasNext();
     method public java.util.Iterator<android.database.CursorJoiner.Result> iterator();
     method public android.database.CursorJoiner.Result next();
-    method public void remove();
   }
 
   public static final class CursorJoiner.Result extends java.lang.Enum {
@@ -21356,7 +21355,7 @@
 
   public static abstract class AudioManager.AudioRecordingCallback {
     ctor public AudioManager.AudioRecordingCallback();
-    method public void onRecordConfigChanged();
+    method public void onRecordConfigChanged(android.media.AudioRecordConfiguration[]);
   }
 
   public static abstract interface AudioManager.OnAudioFocusChangeListener {
@@ -34100,6 +34099,7 @@
 
   public static final class DocumentsContract.Root {
     field public static final java.lang.String COLUMN_AVAILABLE_BYTES = "available_bytes";
+    field public static final java.lang.String COLUMN_CAPACITY_BYTES = "capacity_bytes";
     field public static final java.lang.String COLUMN_DOCUMENT_ID = "document_id";
     field public static final java.lang.String COLUMN_FLAGS = "flags";
     field public static final java.lang.String COLUMN_ICON = "icon";
@@ -41245,7 +41245,6 @@
     method public boolean hasNext();
     method public java.util.Iterator<java.lang.String> iterator();
     method public java.lang.String next();
-    method public void remove();
     method public void setString(java.lang.String);
   }
 
@@ -60818,9 +60817,10 @@
   }
 
   public abstract interface Iterator {
+    method public default void forEachRemaining(java.util.function.Consumer<? super E>);
     method public abstract boolean hasNext();
     method public abstract E next();
-    method public abstract void remove();
+    method public default void remove();
   }
 
   public class LinkedHashMap extends java.util.HashMap implements java.util.Map {
@@ -61171,6 +61171,31 @@
     method public long orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
   }
 
+  public abstract interface PrimitiveIterator implements java.util.Iterator {
+    method public abstract void forEachRemaining(T_CONS);
+  }
+
+  public static abstract interface PrimitiveIterator.OfDouble implements java.util.PrimitiveIterator {
+    method public default void forEachRemaining(java.util.function.DoubleConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Double>);
+    method public default java.lang.Double next();
+    method public abstract double nextDouble();
+  }
+
+  public static abstract interface PrimitiveIterator.OfInt implements java.util.PrimitiveIterator {
+    method public default void forEachRemaining(java.util.function.IntConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Integer>);
+    method public default java.lang.Integer next();
+    method public abstract int nextInt();
+  }
+
+  public static abstract interface PrimitiveIterator.OfLong implements java.util.PrimitiveIterator {
+    method public default void forEachRemaining(java.util.function.LongConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Long>);
+    method public default java.lang.Long next();
+    method public abstract long nextLong();
+  }
+
   public class PriorityQueue extends java.util.AbstractQueue implements java.io.Serializable {
     ctor public PriorityQueue();
     ctor public PriorityQueue(int);
@@ -61342,7 +61367,6 @@
     method public short nextShort();
     method public short nextShort(int);
     method public int radix();
-    method public void remove();
     method public java.util.Scanner reset();
     method public java.util.Scanner skip(java.util.regex.Pattern);
     method public java.util.Scanner skip(java.lang.String);
diff --git a/api/test-current.txt b/api/test-current.txt
index 3eae99d..f18f4e1 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5258,7 +5258,7 @@
   }
 
   public static class NotificationManager.Policy implements android.os.Parcelable {
-    ctor public deprecated NotificationManager.Policy(int, int, int);
+    ctor public NotificationManager.Policy(int, int, int);
     ctor public NotificationManager.Policy(int, int, int, int);
     method public int describeContents();
     method public static java.lang.String priorityCategoriesToString(int);
@@ -10476,7 +10476,6 @@
     method public boolean hasNext();
     method public java.util.Iterator<android.database.CursorJoiner.Result> iterator();
     method public android.database.CursorJoiner.Result next();
-    method public void remove();
   }
 
   public static final class CursorJoiner.Result extends java.lang.Enum {
@@ -19878,7 +19877,7 @@
 
   public static abstract class AudioManager.AudioRecordingCallback {
     ctor public AudioManager.AudioRecordingCallback();
-    method public void onRecordConfigChanged();
+    method public void onRecordConfigChanged(android.media.AudioRecordConfiguration[]);
   }
 
   public static abstract interface AudioManager.OnAudioFocusChangeListener {
@@ -31730,6 +31729,7 @@
 
   public static final class DocumentsContract.Root {
     field public static final java.lang.String COLUMN_AVAILABLE_BYTES = "available_bytes";
+    field public static final java.lang.String COLUMN_CAPACITY_BYTES = "capacity_bytes";
     field public static final java.lang.String COLUMN_DOCUMENT_ID = "document_id";
     field public static final java.lang.String COLUMN_FLAGS = "flags";
     field public static final java.lang.String COLUMN_ICON = "icon";
@@ -38497,7 +38497,6 @@
     method public boolean hasNext();
     method public java.util.Iterator<java.lang.String> iterator();
     method public java.lang.String next();
-    method public void remove();
     method public void setString(java.lang.String);
   }
 
@@ -57733,9 +57732,10 @@
   }
 
   public abstract interface Iterator {
+    method public default void forEachRemaining(java.util.function.Consumer<? super E>);
     method public abstract boolean hasNext();
     method public abstract E next();
-    method public abstract void remove();
+    method public default void remove();
   }
 
   public class LinkedHashMap extends java.util.HashMap implements java.util.Map {
@@ -58086,6 +58086,31 @@
     method public long orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
   }
 
+  public abstract interface PrimitiveIterator implements java.util.Iterator {
+    method public abstract void forEachRemaining(T_CONS);
+  }
+
+  public static abstract interface PrimitiveIterator.OfDouble implements java.util.PrimitiveIterator {
+    method public default void forEachRemaining(java.util.function.DoubleConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Double>);
+    method public default java.lang.Double next();
+    method public abstract double nextDouble();
+  }
+
+  public static abstract interface PrimitiveIterator.OfInt implements java.util.PrimitiveIterator {
+    method public default void forEachRemaining(java.util.function.IntConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Integer>);
+    method public default java.lang.Integer next();
+    method public abstract int nextInt();
+  }
+
+  public static abstract interface PrimitiveIterator.OfLong implements java.util.PrimitiveIterator {
+    method public default void forEachRemaining(java.util.function.LongConsumer);
+    method public default void forEachRemaining(java.util.function.Consumer<? super java.lang.Long>);
+    method public default java.lang.Long next();
+    method public abstract long nextLong();
+  }
+
   public class PriorityQueue extends java.util.AbstractQueue implements java.io.Serializable {
     ctor public PriorityQueue();
     ctor public PriorityQueue(int);
@@ -58257,7 +58282,6 @@
     method public short nextShort();
     method public short nextShort(int);
     method public int radix();
-    method public void remove();
     method public java.util.Scanner reset();
     method public java.util.Scanner skip(java.util.regex.Pattern);
     method public java.util.Scanner skip(java.lang.String);
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 057a4e9..16aee78 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -662,7 +662,7 @@
 
     /**
      * Notification policy configuration.  Represents user-preferences for notification
-     * filtering and prioritization.
+     * filtering.
      */
     public static class Policy implements android.os.Parcelable {
         /** Reminder notifications are prioritized. */
@@ -707,13 +707,13 @@
          */
         public static final int SUPPRESSED_EFFECTS_UNSET = -1;
         /**
-         * Whether notification suppressed by DND should not interruption visually when the screen
-         * is off.
+         * Whether notifications suppressed by DND should not interrupt visually (e.g. with
+         * notification lights or by turning the screen on) when the screen is off.
          */
         public static final int SUPPRESSED_EFFECT_SCREEN_OFF = 1 << 0;
         /**
-         * Whether notification suppressed by DND should not interruption visually when the screen
-         * is on.
+         * Whether notifications suppressed by DND should not interrupt visually when the screen
+         * is on (e.g. by peeking onto the screen).
          */
         public static final int SUPPRESSED_EFFECT_SCREEN_ON = 1 << 1;
 
@@ -728,13 +728,27 @@
          */
         public final int suppressedVisualEffects;
 
-
-        @Deprecated
+        /**
+         * Constructs a policy for Do Not Disturb priority mode behavior.
+         *
+         * @param priorityCategories bitmask of categories of notifications that can bypass DND.
+         * @param priorityCallSenders which callers can bypass DND.
+         * @param priorityMessageSenders which message senders can bypass DND.
+         */
         public Policy(int priorityCategories, int priorityCallSenders, int priorityMessageSenders) {
             this(priorityCategories, priorityCallSenders, priorityMessageSenders,
                     SUPPRESSED_EFFECTS_UNSET);
         }
 
+        /**
+         * Constructs a policy for Do Not Disturb priority mode behavior.
+         *
+         * @param priorityCategories bitmask of categories of notifications that can bypass DND.
+         * @param priorityCallSenders which callers can bypass DND.
+         * @param priorityMessageSenders which message senders can bypass DND.
+         * @param suppressedVisualEffects which visual interruptions should be suppressed from
+         *                                notifications that are filtered by DND.
+         */
         public Policy(int priorityCategories, int priorityCallSenders, int priorityMessageSenders,
                 int suppressedVisualEffects) {
             this.priorityCategories = priorityCategories;
@@ -865,7 +879,6 @@
                 return new Policy[size];
             }
         };
-
     }
 
     /**
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index a1ad590..c4037f8 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -344,6 +344,68 @@
             = "android.app.action.PROVISION_FINALIZATION";
 
     /**
+     * Action: Bugreport sharing with device owner has been accepted by the user.
+     *
+     * @hide
+     */
+    public static final String ACTION_BUGREPORT_SHARING_ACCEPTED =
+            "com.android.server.action.BUGREPORT_SHARING_ACCEPTED";
+
+    /**
+     * Action: Bugreport sharing with device owner has been declined by the user.
+     *
+     * @hide
+     */
+    public static final String ACTION_BUGREPORT_SHARING_DECLINED =
+            "com.android.server.action.BUGREPORT_SHARING_DECLINED";
+
+    /**
+     * Action: Bugreport has been collected and is dispatched to {@link DevicePolicyManagerService}.
+     *
+     * @hide
+     */
+    public static final String ACTION_REMOTE_BUGREPORT_DISPATCH =
+            "android.intent.action.REMOTE_BUGREPORT_DISPATCH";
+
+    /**
+     * Extra for shared bugreport's SHA-256 hash.
+     *
+     * @hide
+     */
+    public static final String EXTRA_REMOTE_BUGREPORT_HASH =
+            "android.intent.extra.REMOTE_BUGREPORT_HASH";
+
+    /**
+     * Extra for remote bugreport notification shown type.
+     *
+     * @hide
+     */
+    public static final String EXTRA_BUGREPORT_NOTIFICATION_TYPE =
+            "android.app.extra.bugreport_notification_type";
+
+    /**
+     * Notification type for a started remote bugreport flow.
+     *
+     * @hide
+     */
+    public static final int NOTIFICATION_BUGREPORT_STARTED = 1;
+
+    /**
+     * Notification type for a bugreport that has already been accepted to be shared, but is still
+     * being taken.
+     *
+     * @hide
+     */
+    public static final int NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED = 2;
+
+    /**
+     * Notification type for a bugreport that has been taken and can be shared or declined.
+     *
+     * @hide
+     */
+    public static final int NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED = 3;
+
+    /**
      * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that
      * allows a mobile device management application or NFC programmer application which starts
      * managed provisioning to pass data to the management application instance after provisioning.
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index 0a0d77d..8cdfee5 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -69,4 +69,13 @@
      * @return true if the uid is an active admin with the given policy.
      */
     public abstract boolean isActiveAdminWithPolicy(int uid, int reqPolicy);
+
+    /**
+     * Checks if a given package has a device or a profile owner for the given user
+     *
+     * @param packageName The package to check
+     * @param userId the userId to check for.
+     * @return true if package has a device or profile owner, false otherwise.
+     */
+    public abstract boolean hasDeviceOwnerOrProfileOwner(String packageName, int userId);
 }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 0588a9d..bc28ff1 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -121,6 +121,10 @@
 
     private static final int MAX_PACKAGES_PER_APK = 5;
 
+    public static final int APK_SIGNING_UNKNOWN = 0;
+    public static final int APK_SIGNING_V1 = 1;
+    public static final int APK_SIGNING_V2 = 2;
+
     // TODO: switch outError users to PackageParserException
     // TODO: refactor "codePath" to "apkPath"
 
@@ -1058,12 +1062,24 @@
         return pkg;
     }
 
+    public static int getApkSigningVersion(Package pkg) {
+        try {
+            if (ApkSignatureSchemeV2Verifier.hasSignature(pkg.baseCodePath)) {
+                return APK_SIGNING_V2;
+            }
+            return APK_SIGNING_V1;
+        } catch (IOException e) {
+        }
+        return APK_SIGNING_UNKNOWN;
+    }
+
     /**
      * Collect certificates from all the APKs described in the given package,
      * populating {@link Package#mSignatures}. Also asserts that all APK
      * contents are signed correctly and consistently.
      */
-    public static void collectCertificates(Package pkg, int parseFlags) throws PackageParserException {
+    public static void collectCertificates(Package pkg, int parseFlags)
+            throws PackageParserException {
         collectCertificatesInternal(pkg, parseFlags);
         final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
         for (int i = 0; i < childCount; i++) {
@@ -1074,7 +1090,8 @@
         }
     }
 
-    private static void collectCertificatesInternal(Package pkg, int parseFlags) throws PackageParserException {
+    private static void collectCertificatesInternal(Package pkg, int parseFlags)
+            throws PackageParserException {
         pkg.mCertificates = null;
         pkg.mSignatures = null;
         pkg.mSigningKeys = null;
diff --git a/core/java/android/hardware/camera2/DngCreator.java b/core/java/android/hardware/camera2/DngCreator.java
index 57a080b..9478dc0 100644
--- a/core/java/android/hardware/camera2/DngCreator.java
+++ b/core/java/android/hardware/camera2/DngCreator.java
@@ -137,6 +137,11 @@
             throw new IllegalArgumentException("Orientation " + orientation +
                     " is not a valid EXIF orientation value");
         }
+        // ExifInterface and TIFF/EP spec differ on definition of
+        // "Unknown" orientation; other values map directly
+        if (orientation == ExifInterface.ORIENTATION_UNDEFINED) {
+            orientation = TAG_ORIENTATION_UNKNOWN;
+        }
         nativeSetOrientation(orientation);
         return this;
     }
@@ -443,7 +448,7 @@
     private static final String GPS_LONG_REF_WEST = "W";
 
     private static final String GPS_DATE_FORMAT_STR = "yyyy:MM:dd";
-    private static final String TIFF_DATETIME_FORMAT = "yyyy:MM:dd kk:mm:ss";
+    private static final String TIFF_DATETIME_FORMAT = "yyyy:MM:dd HH:mm:ss";
     private static final DateFormat sExifGPSDateStamp = new SimpleDateFormat(GPS_DATE_FORMAT_STR);
     private static final DateFormat sDateTimeStampFormat =
             new SimpleDateFormat(TIFF_DATETIME_FORMAT);
@@ -458,6 +463,9 @@
     private static final int DEFAULT_PIXEL_STRIDE = 2; // bytes per sample
     private static final int BYTES_PER_RGB_PIX = 3; // byts per pixel
 
+    // TIFF tag values needed to map between public API and TIFF spec
+    private static final int TAG_ORIENTATION_UNKNOWN = 9;
+
     /**
      * Offset, rowStride, and pixelStride are given in bytes.  Height and width are given in pixels.
      */
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index e62df3c..4c4adea 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -614,14 +614,16 @@
         return LegacyExceptionUtils.throwOnError(nativeDetectSurfaceDataspace(surface));
     }
 
-    static void configureSurface(Surface surface, int width, int height,
-                                 int pixelFormat) throws BufferQueueAbandonedException {
+    static void connectSurface(Surface surface) throws BufferQueueAbandonedException {
         checkNotNull(surface);
-        checkArgumentPositive(width, "width must be positive.");
-        checkArgumentPositive(height, "height must be positive.");
 
-        LegacyExceptionUtils.throwOnError(nativeConfigureSurface(surface, width, height,
-                pixelFormat));
+        LegacyExceptionUtils.throwOnError(nativeConnectSurface(surface));
+    }
+
+    static void disconnectSurface(Surface surface) throws BufferQueueAbandonedException {
+        if (surface == null) return;
+
+        LegacyExceptionUtils.throwOnError(nativeDisconnectSurface(surface));
     }
 
     static void produceFrame(Surface surface, byte[] pixelBuffer, int width,
@@ -716,8 +718,7 @@
     private static native int nativeDetectSurfaceDimens(Surface surface,
             /*out*/int[/*2*/] dimens);
 
-    private static native int nativeConfigureSurface(Surface surface, int width, int height,
-                                                        int pixelFormat);
+    private static native int nativeConnectSurface(Surface surface);
 
     private static native int nativeProduceFrame(Surface surface, byte[] pixelBuffer, int width,
                                                     int height, int pixelFormat);
@@ -740,5 +741,7 @@
 
     private static native int nativeSetScalingMode(Surface surface, int scalingMode);
 
+    private static native int nativeDisconnectSurface(Surface surface);
+
     static native int nativeGetJpegFooterSize();
 }
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index 1ca7ddf..e8ce3ec 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -365,6 +365,14 @@
             mGLThreadManager.waitUntilIdle();
         }
         resetJpegSurfaceFormats(mCallbackOutputs);
+
+        for (Surface s : mCallbackOutputs) {
+            try {
+                LegacyCameraDevice.disconnectSurface(s);
+            } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
+                Log.w(TAG, "Surface abandoned, skipping...", e);
+            }
+        }
         mPreviewOutputs.clear();
         mCallbackOutputs.clear();
         mJpegSurfaceIds.clear();
@@ -392,6 +400,10 @@
                             mJpegSurfaceIds.add(LegacyCameraDevice.getSurfaceId(s));
                             mCallbackOutputs.add(s);
                             callbackOutputSizes.add(outSize);
+
+                            // LegacyCameraDevice is the producer of JPEG output surfaces
+                            // so LegacyCameraDevice needs to connect to the surfaces.
+                            LegacyCameraDevice.connectSurface(s);
                             break;
                         default:
                             LegacyCameraDevice.setScalingMode(s, LegacyCameraDevice.
diff --git a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
index bc80fc1..70bc2fd 100644
--- a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
+++ b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
@@ -401,6 +401,13 @@
 
     private void clearState() {
         mSurfaces.clear();
+        for (EGLSurfaceHolder holder : mConversionSurfaces) {
+            try {
+                LegacyCameraDevice.disconnectSurface(holder.surface);
+            } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
+                Log.w(TAG, "Surface abandoned, skipping...", e);
+            }
+        }
         mConversionSurfaces.clear();
         mPBufferPixels = null;
         if (mSurfaceTexture != null) {
@@ -631,6 +638,9 @@
                 holder.height = surfaceSize.getHeight();
                 if (LegacyCameraDevice.needsConversion(s)) {
                     mConversionSurfaces.add(holder);
+                    // LegacyCameraDevice is the producer of surfaces if it's not handled by EGL,
+                    // so LegacyCameraDevice needs to connect to the surfaces.
+                    LegacyCameraDevice.connectSurface(s);
                 } else {
                     mSurfaces.add(holder);
                 }
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 03a1ca6..0065cd9 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -478,7 +478,6 @@
         /**
          * Capacity of a root in bytes. This column is optional, and may be
          * {@code null} if unknown or unbounded.
-         * {@hide}
          * <p>
          * Type: INTEGER (long)
          */
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f13f242..a40cf96 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1241,6 +1241,19 @@
     public static final String ACTION_SHOW_ADMIN_SUPPORT_DETAILS
             = "android.settings.SHOW_ADMIN_SUPPORT_DETAILS";
 
+    /**
+     * Activity Action: Show a dialog for remote bugreport flow.
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     *
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_SHOW_REMOTE_BUGREPORT_DIALOG
+            = "android.settings.SHOW_REMOTE_BUGREPORT_DIALOG";
+
     // End of Intent actions for Settings
 
     /**
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
index 728f723..60c7270 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
@@ -75,6 +75,36 @@
     public static final int SF_ATTRIBUTE_ANDROID_APK_SIGNED_ID = 2;
 
     /**
+     * Returns {@code true} if the provided APK contains an APK Signature Scheme V2
+     * signature. The signature will not be verified.
+     */
+    public static boolean hasSignature(String apkFile) throws IOException {
+        try (RandomAccessFile apk = new RandomAccessFile(apkFile, "r")) {
+            long fileSize = apk.length();
+            if (fileSize > Integer.MAX_VALUE) {
+                return false;
+            }
+            MappedByteBuffer apkContents =
+                    apk.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, fileSize);
+            // ZipUtils and APK Signature Scheme v2 verifier expect little-endian byte order.
+            apkContents.order(ByteOrder.LITTLE_ENDIAN);
+
+            final int centralDirOffset =
+                    (int) getCentralDirOffset(apkContents, getEocdOffset(apkContents));
+            // Find the APK Signing Block.
+            int apkSigningBlockOffset = findApkSigningBlock(apkContents, centralDirOffset);
+            ByteBuffer apkSigningBlock =
+                    sliceFromTo(apkContents, apkSigningBlockOffset, centralDirOffset);
+
+            // Find the APK Signature Scheme v2 Block inside the APK Signing Block.
+            findApkSignatureSchemeV2Block(apkSigningBlock);
+            return true;
+        } catch (SignatureNotFoundException e) {
+        }
+        return false;
+    }
+
+    /**
      * Verifies APK Signature Scheme v2 signatures of the provided APK and returns the certificates
      * associated with each signer.
      *
@@ -130,31 +160,8 @@
         // ZipUtils and APK Signature Scheme v2 verifier expect little-endian byte order.
         apkContents.order(ByteOrder.LITTLE_ENDIAN);
 
-        // Find the offset of ZIP End of Central Directory (EoCD)
-        int eocdOffset = ZipUtils.findZipEndOfCentralDirectoryRecord(apkContents);
-        if (eocdOffset == -1) {
-            throw new SignatureNotFoundException(
-                    "Not an APK file: ZIP End of Central Directory record not found");
-        }
-        if (ZipUtils.isZip64EndOfCentralDirectoryLocatorPresent(apkContents, eocdOffset)) {
-            throw new SignatureNotFoundException("ZIP64 APK not supported");
-        }
-        ByteBuffer eocd = sliceFromTo(apkContents, eocdOffset, apkContents.capacity());
-
-        // Look up the offset of ZIP Central Directory.
-        long centralDirOffsetLong = ZipUtils.getZipEocdCentralDirectoryOffset(eocd);
-        if (centralDirOffsetLong >= eocdOffset) {
-            throw new SignatureNotFoundException(
-                    "ZIP Central Directory offset out of range: " + centralDirOffsetLong
-                    + ". ZIP End of Central Directory offset: " + eocdOffset);
-        }
-        long centralDirSizeLong = ZipUtils.getZipEocdCentralDirectorySizeBytes(eocd);
-        if (centralDirOffsetLong + centralDirSizeLong != eocdOffset) {
-            throw new SignatureNotFoundException(
-                    "ZIP Central Directory is not immediately followed by End of Central"
-                    + " Directory");
-        }
-        int centralDirOffset = (int) centralDirOffsetLong;
+        final int eocdOffset = getEocdOffset(apkContents);
+        final int centralDirOffset = (int) getCentralDirOffset(apkContents, eocdOffset);
 
         // Find the APK Signing Block.
         int apkSigningBlockOffset = findApkSigningBlock(apkContents, centralDirOffset);
@@ -499,6 +506,43 @@
         return result;
     }
 
+    /**
+     * Finds the offset of ZIP End of Central Directory (EoCD).
+     *
+     * @throws SignatureNotFoundException If the EoCD could not be found
+     */
+    private static int getEocdOffset(ByteBuffer apkContents) throws SignatureNotFoundException {
+        int eocdOffset = ZipUtils.findZipEndOfCentralDirectoryRecord(apkContents);
+        if (eocdOffset == -1) {
+            throw new SignatureNotFoundException(
+                    "Not an APK file: ZIP End of Central Directory record not found");
+        }
+        return eocdOffset;
+    }
+
+    private static long getCentralDirOffset(ByteBuffer apkContents, int eocdOffset)
+            throws SignatureNotFoundException {
+        if (ZipUtils.isZip64EndOfCentralDirectoryLocatorPresent(apkContents, eocdOffset)) {
+            throw new SignatureNotFoundException("ZIP64 APK not supported");
+        }
+        ByteBuffer eocd = sliceFromTo(apkContents, eocdOffset, apkContents.capacity());
+
+        // Look up the offset of ZIP Central Directory.
+        long centralDirOffsetLong = ZipUtils.getZipEocdCentralDirectoryOffset(eocd);
+        if (centralDirOffsetLong >= eocdOffset) {
+            throw new SignatureNotFoundException(
+                    "ZIP Central Directory offset out of range: " + centralDirOffsetLong
+                    + ". ZIP End of Central Directory offset: " + eocdOffset);
+        }
+        long centralDirSizeLong = ZipUtils.getZipEocdCentralDirectorySizeBytes(eocd);
+        if (centralDirOffsetLong + centralDirSizeLong != eocdOffset) {
+            throw new SignatureNotFoundException(
+                    "ZIP Central Directory is not immediately followed by End of Central"
+                    + " Directory");
+        }
+        return centralDirOffsetLong;
+    }
+
     private static final int getChunkCount(int inputSizeBytes) {
         return (inputSizeBytes + CHUNK_SIZE_BYTES - 1) / CHUNK_SIZE_BYTES;
     }
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 9543acf..8048301 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -167,7 +167,7 @@
             in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
             int icon, int logo, int windowFlags, IBinder transferFrom, boolean createIfNeeded);
     void setAppVisibility(IBinder token, boolean visible);
-    void notifyAppStopped(IBinder token);
+    void notifyAppStopped(IBinder token, boolean stopped);
     void startAppFreezingScreen(IBinder token, int configChanges);
     void stopAppFreezingScreen(IBinder token, boolean force);
     void removeAppToken(IBinder token);
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 2099b04..72a50ec1 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -17,21 +17,15 @@
 package android.widget;
 
 import android.animation.ObjectAnimator;
+import android.annotation.InterpolatorRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.graphics.PorterDuff;
-
-import android.util.FloatProperty;
-import android.util.IntProperty;
-import android.view.accessibility.AccessibilityNodeInfo;
-import com.android.internal.R;
-
-import android.annotation.InterpolatorRes;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.Shader;
 import android.graphics.drawable.Animatable;
@@ -46,6 +40,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.AttributeSet;
+import android.util.FloatProperty;
 import android.util.MathUtils;
 import android.util.Pools.SynchronizedPool;
 import android.view.Gravity;
@@ -55,6 +50,7 @@
 import android.view.ViewHierarchyEncoder;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.AlphaAnimation;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
@@ -63,6 +59,7 @@
 import android.view.animation.LinearInterpolator;
 import android.view.animation.Transformation;
 import android.widget.RemoteViews.RemoteView;
+import com.android.internal.R;
 
 import java.util.ArrayList;
 
@@ -606,15 +603,30 @@
 
             if (indeterminate) {
                 // swap between indeterminate and regular backgrounds
-                mCurrentDrawable = mIndeterminateDrawable;
+                swapCurrentDrawable(mIndeterminateDrawable);
                 startAnimation();
             } else {
-                mCurrentDrawable = mProgressDrawable;
+                swapCurrentDrawable(mProgressDrawable);
                 stopAnimation();
             }
         }
     }
 
+    private void swapCurrentDrawable(Drawable newDrawable) {
+        final Drawable oldDrawable = mCurrentDrawable;
+        mCurrentDrawable = newDrawable;
+        if (oldDrawable != mCurrentDrawable) {
+            if (oldDrawable != null) {
+                oldDrawable.setVisible(false, false);
+            }
+            if (mCurrentDrawable != null) {
+                mCurrentDrawable.setVisible(
+                        getVisibility() == VISIBLE && getWindowVisibility() == VISIBLE,
+                        false);
+            }
+        }
+    }
+
     /**
      * <p>Get the drawable used to draw the progress bar in
      * indeterminate mode.</p>
@@ -654,7 +666,7 @@
             }
 
             if (mIndeterminate) {
-                mCurrentDrawable = d;
+                swapCurrentDrawable(d);
                 postInvalidate();
             }
         }
@@ -820,7 +832,7 @@
             }
 
             if (!mIndeterminate) {
-                mCurrentDrawable = d;
+                swapCurrentDrawable(d);
                 postInvalidate();
             }
 
@@ -1555,7 +1567,7 @@
      * <p>Start the indeterminate progress animation.</p>
      */
     void startAnimation() {
-        if (getVisibility() != VISIBLE) {
+        if (getVisibility() != VISIBLE || getWindowVisibility() != VISIBLE) {
             return;
         }
 
@@ -1653,14 +1665,30 @@
     protected void onVisibilityChanged(View changedView, int visibility) {
         super.onVisibilityChanged(changedView, visibility);
 
+        updateVisibility();
+    }
+
+    @Override
+    protected void onWindowVisibilityChanged(@Visibility int visibility) {
+        super.onWindowVisibilityChanged(visibility);
+
+        updateVisibility();
+    }
+
+    private void updateVisibility() {
+        final boolean isVisible = getVisibility() == VISIBLE && getWindowVisibility() == VISIBLE;
         if (mIndeterminate) {
             // let's be nice with the UI thread
-            if (visibility == GONE || visibility == INVISIBLE) {
-                stopAnimation();
-            } else {
+            if (isVisible) {
                 startAnimation();
+            } else {
+                stopAnimation();
             }
         }
+
+        if (mCurrentDrawable != null) {
+            mCurrentDrawable.setVisible(isVisible, false);
+        }
     }
 
     @Override
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 816a2c4..623b603 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -7,7 +7,7 @@
 LOCAL_CFLAGS += -Wno-unused-parameter
 LOCAL_CFLAGS += -Wno-non-virtual-dtor
 LOCAL_CFLAGS += -Wno-maybe-uninitialized -Wno-parentheses
-#LOCAL_CFLAGS += -DHWUI_NEW_OPS
+LOCAL_CFLAGS += -DHWUI_NEW_OPS
 LOCAL_CPPFLAGS += -Wno-conversion-null
 
 ifeq ($(TARGET_ARCH), arm)
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index cb0abb6..c6baf1c 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -80,6 +80,13 @@
         return nullptr; \
     }
 
+#define BAIL_IF_EXPR_RET_NULL_SP(expr, jnienv, tagId, writer) \
+    if (expr) { \
+        jniThrowExceptionFmt(jnienv, "java/lang/IllegalArgumentException", \
+                "Invalid metadata for tag %s (%x)", (writer)->getTagName(tagId), (tagId)); \
+        return nullptr; \
+    }
+
 
 #define ANDROID_DNGCREATOR_CTX_JNI_ID     "mNativeContext"
 
@@ -195,8 +202,8 @@
 NativeContext::NativeContext(const CameraMetadata& characteristics, const CameraMetadata& result) :
         mCharacteristics(std::make_shared<CameraMetadata>(characteristics)),
         mResult(std::make_shared<CameraMetadata>(result)), mThumbnailWidth(0),
-        mThumbnailHeight(0), mOrientation(0), mThumbnailSet(false), mGpsSet(false),
-        mDescriptionSet(false), mCaptureTimeSet(false) {}
+        mThumbnailHeight(0), mOrientation(TAG_ORIENTATION_UNKNOWN), mThumbnailSet(false),
+        mGpsSet(false), mDescriptionSet(false), mCaptureTimeSet(false) {}
 
 NativeContext::~NativeContext() {}
 
@@ -1096,7 +1103,7 @@
 
     {
         // Set orientation
-        uint16_t orientation = 1; // Normal
+        uint16_t orientation = TAG_ORIENTATION_NORMAL;
         BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_ORIENTATION, 1, &orientation, TIFF_IFD_0),
                 env, TAG_ORIENTATION, writer);
     }
@@ -1138,12 +1145,27 @@
     }
 
     {
-        // Set blacklevel tags
+        // Set blacklevel tags, using dynamic black level if available
         camera_metadata_entry entry =
-                characteristics.find(ANDROID_SENSOR_BLACK_LEVEL_PATTERN);
-        BAIL_IF_EMPTY_RET_NULL_SP(entry, env, TAG_BLACKLEVEL, writer);
-        const uint32_t* blackLevel = reinterpret_cast<const uint32_t*>(entry.data.i32);
-        BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_BLACKLEVEL, entry.count, blackLevel,
+                results.find(ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL);
+        uint32_t blackLevelRational[8] = {0};
+        if (entry.count != 0) {
+            BAIL_IF_EXPR_RET_NULL_SP(entry.count != 4, env, TAG_BLACKLEVEL, writer);
+            for (size_t i = 0; i < entry.count; i++) {
+                blackLevelRational[i * 2] = static_cast<uint32_t>(entry.data.f[i] * 100);
+                blackLevelRational[i * 2 + 1] = 100;
+            }
+        } else {
+            // Fall back to static black level which is guaranteed
+            entry = characteristics.find(ANDROID_SENSOR_BLACK_LEVEL_PATTERN);
+            BAIL_IF_EXPR_RET_NULL_SP(entry.count != 4, env, TAG_BLACKLEVEL, writer);
+            for (size_t i = 0; i < entry.count; i++) {
+                blackLevelRational[i * 2] = static_cast<uint32_t>(entry.data.i32[i]);
+                blackLevelRational[i * 2 + 1] = 1;
+            }
+
+        }
+        BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_BLACKLEVEL, 4, blackLevelRational,
                 TIFF_IFD_0), env, TAG_BLACKLEVEL, writer);
 
         uint16_t repeatDim[2] = {2, 2};
@@ -1913,8 +1935,10 @@
 
         {
             // Set bits per sample
-            uint16_t bits = BITS_PER_RGB_SAMPLE;
-            BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_BITSPERSAMPLE, 1, &bits, TIFF_IFD_0),
+            uint16_t bits[SAMPLES_PER_RGB_PIXEL];
+            for (int i = 0; i < SAMPLES_PER_RGB_PIXEL; i++) bits[i] = BITS_PER_RGB_SAMPLE;
+            BAIL_IF_INVALID_RET_NULL_SP(
+                    writer->addEntry(TAG_BITSPERSAMPLE, SAMPLES_PER_RGB_PIXEL, bits, TIFF_IFD_0),
                     env, TAG_BITSPERSAMPLE, writer);
         }
 
diff --git a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
index f1ea7ec..80f9d57 100644
--- a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
+++ b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
@@ -29,6 +29,7 @@
 
 #include <gui/Surface.h>
 #include <gui/IGraphicBufferProducer.h>
+#include <gui/IProducerListener.h>
 #include <ui/GraphicBuffer.h>
 #include <system/window.h>
 #include <hardware/camera3.h>
@@ -93,27 +94,17 @@
             cStep, yStride, cStride);
 }
 
-static status_t configureSurface(const sp<ANativeWindow>& anw,
-                                 int32_t width,
-                                 int32_t height,
-                                 int32_t pixelFmt,
-                                 int32_t maxBufferSlack) {
+static status_t connectSurface(const sp<Surface>& surface, int32_t maxBufferSlack) {
     status_t err = NO_ERROR;
-    err = native_window_set_buffers_dimensions(anw.get(), width, height);
-    if (err != NO_ERROR) {
-        ALOGE("%s: Failed to set native window buffer dimensions, error %s (%d).", __FUNCTION__,
+
+    err = surface->connect(NATIVE_WINDOW_API_CAMERA, /*listener*/NULL);
+    if (err != OK) {
+        ALOGE("%s: Unable to connect to surface, error %s (%d).", __FUNCTION__,
                 strerror(-err), err);
         return err;
     }
 
-    err = native_window_set_buffers_format(anw.get(), pixelFmt);
-    if (err != NO_ERROR) {
-        ALOGE("%s: Failed to set native window buffer format, error %s (%d).", __FUNCTION__,
-                strerror(-err), err);
-        return err;
-    }
-
-    err = native_window_set_usage(anw.get(), GRALLOC_USAGE_SW_WRITE_OFTEN);
+    err = native_window_set_usage(surface.get(), GRALLOC_USAGE_SW_WRITE_OFTEN);
     if (err != NO_ERROR) {
         ALOGE("%s: Failed to set native window usage flag, error %s (%d).", __FUNCTION__,
                 strerror(-err), err);
@@ -121,19 +112,17 @@
     }
 
     int minUndequeuedBuffers;
-    err = anw.get()->query(anw.get(),
-            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
-            &minUndequeuedBuffers);
+    err = static_cast<ANativeWindow*>(surface.get())->query(surface.get(),
+            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers);
     if (err != NO_ERROR) {
         ALOGE("%s: Failed to get native window min undequeued buffers, error %s (%d).",
                 __FUNCTION__, strerror(-err), err);
         return err;
     }
 
-    ALOGV("%s: Setting buffer count to %d, size to (%dx%d), fmt (0x%x)", __FUNCTION__,
-          maxBufferSlack + 1 + minUndequeuedBuffers,
-          width, height, pixelFmt);
-    err = native_window_set_buffer_count(anw.get(), maxBufferSlack + 1 + minUndequeuedBuffers);
+    ALOGV("%s: Setting buffer count to %d", __FUNCTION__,
+            maxBufferSlack + 1 + minUndequeuedBuffers);
+    err = native_window_set_buffer_count(surface.get(), maxBufferSlack + 1 + minUndequeuedBuffers);
     if (err != NO_ERROR) {
         ALOGE("%s: Failed to set native window buffer count, error %s (%d).", __FUNCTION__,
                 strerror(-err), err);
@@ -509,6 +498,26 @@
     return usage;
 }
 
+static jint LegacyCameraDevice_nativeDisconnectSurface(JNIEnv* env, jobject thiz,
+          jobject surface) {
+    ALOGV("nativeDisconnectSurface");
+    if (surface == nullptr) return NO_ERROR;
+
+    sp<ANativeWindow> anw;
+    if ((anw = getNativeWindow(env, surface)) == NULL) {
+        ALOGV("Buffer queue has already been abandoned.");
+        return NO_ERROR;
+    }
+
+    status_t err = native_window_api_disconnect(anw.get(), NATIVE_WINDOW_API_CAMERA);
+    if(err != NO_ERROR) {
+        jniThrowException(env, "Ljava/lang/UnsupportedOperationException;",
+            "Error while disconnecting surface");
+        return err;
+    }
+    return NO_ERROR;
+}
+
 static jint LegacyCameraDevice_nativeDetectTextureDimens(JNIEnv* env, jobject thiz,
         jobject surfaceTexture, jintArray dimens) {
     ALOGV("nativeDetectTextureDimens");
@@ -540,15 +549,14 @@
     return NO_ERROR;
 }
 
-static jint LegacyCameraDevice_nativeConfigureSurface(JNIEnv* env, jobject thiz, jobject surface,
-        jint width, jint height, jint pixelFormat) {
-    ALOGV("nativeConfigureSurface");
-    sp<ANativeWindow> anw;
-    if ((anw = getNativeWindow(env, surface)) == NULL) {
-        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
+static jint LegacyCameraDevice_nativeConnectSurface(JNIEnv* env, jobject thiz, jobject surface) {
+    ALOGV("nativeConnectSurface");
+    sp<Surface> s;
+    if ((s = getSurface(env, surface)) == NULL) {
+        ALOGE("%s: Could not retrieve surface.", __FUNCTION__);
         return BAD_VALUE;
     }
-    status_t err = configureSurface(anw, width, height, pixelFormat, CAMERA_DEVICE_BUFFER_SLACK);
+    status_t err = connectSurface(s, CAMERA_DEVICE_BUFFER_SLACK);
     if (err != NO_ERROR) {
         ALOGE("%s: Error while configuring surface %s (%d).", __FUNCTION__, strerror(-err), err);
         return err;
@@ -740,9 +748,9 @@
     { "nativeDetectSurfaceDimens",
     "(Landroid/view/Surface;[I)I",
     (void *)LegacyCameraDevice_nativeDetectSurfaceDimens },
-    { "nativeConfigureSurface",
-    "(Landroid/view/Surface;III)I",
-    (void *)LegacyCameraDevice_nativeConfigureSurface },
+    { "nativeConnectSurface",
+    "(Landroid/view/Surface;)I",
+    (void *)LegacyCameraDevice_nativeConnectSurface },
     { "nativeProduceFrame",
     "(Landroid/view/Surface;[BIII)I",
     (void *)LegacyCameraDevice_nativeProduceFrame },
@@ -773,6 +781,9 @@
     { "nativeSetScalingMode",
     "(Landroid/view/Surface;I)I",
     (void *)LegacyCameraDevice_nativeSetScalingMode },
+    { "nativeDisconnectSurface",
+    "(Landroid/view/Surface;)I",
+    (void *)LegacyCameraDevice_nativeDisconnectSurface },
 };
 
 // Get all the required offsets in java class and register native functions
diff --git a/core/res/res/layout/text_edit_suggestion_container_material.xml b/core/res/res/layout/text_edit_suggestion_container_material.xml
index 15b18dd..d1c65c0 100644
--- a/core/res/res/layout/text_edit_suggestion_container_material.xml
+++ b/core/res/res/layout/text_edit_suggestion_container_material.xml
@@ -33,7 +33,7 @@
             android:id="@+id/suggestionContainer"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:paddingTop="8dp"
+            android:paddingTop="4dp"
             android:paddingBottom="0dp"
             android:divider="@null" />
         <LinearLayout
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 9a2a6eb..7857107 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2440,6 +2440,10 @@
          flag). -->
     <bool name="config_forceWindowDrawsStatusBarBackground">true</bool>
 
+    <!-- If set, this will force the navigation bar to always be drawn with an opaque
+         background. -->
+    <bool name="config_forceNavBarAlwaysOpaque">false</bool>
+
     <!-- Default bounds [left top right bottom] on screen for picture-in-picture windows. -->
     <string translatable="false" name="config_defaultPictureInPictureBounds">"0 0 100 100"</string>
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 7b11302..d8efd63 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2917,20 +2917,18 @@
     <!-- Message of notification shown when ADB is actively connected to the phone. -->
     <string name="adb_active_notification_message">Touch to disable USB debugging.</string>
 
+    <!-- Title of notification shown to indicate that bug report is being collected. -->
+    <string name="taking_remote_bugreport_notification_title">Taking bug report\u2026</string>
     <!-- Title of notification shown to ask for user consent for sharing a bugreport that was requested remotely by the IT administrator. -->
     <string name="share_remote_bugreport_notification_title">Share bug report?</string>
     <!-- Title of notification shown to indicate that bug report is still being collected after sharing was accepted. -->
     <string name="sharing_remote_bugreport_notification_title">Sharing bug report\u2026</string>
-    <!-- Message of notification shown to ask for user consent for sharing a bugreport that was requested remotely by the IT administrator. -->
-    <string name="share_remote_bugreport_notification_message">Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared and your device may temporarily slow down.</string>
-    <!-- Message of notification shown to ask for user consent for sharing a bugreport that was requested remotely by the IT administrator. -->
-    <string name="share_finished_remote_bugreport_notification_message">Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared.</string>
-    <!-- Message of notification shown to shown to indicate that bug report is still being collected after sharing was accepted. -->
-    <string name="sharing_remote_bugreport_notification_message">This may temporarily slow down your device</string>
+    <!-- Message of a notification shown to ask for user consent for sharing a bugreport that was requested remotely by the IT administrator. -->
+    <string name="share_remote_bugreport_notification_message_finished">Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared.</string>
     <!-- Acceptance label of notification shown to ask for user consent for sharing the remote bugreport. -->
-    <string name="share_remote_bugreport_notification_accept">ACCEPT</string>
+    <string name="share_remote_bugreport_action">SHARE</string>
     <!-- Decline label of notification shown to ask for user consent for sharing the remote bugreport. -->
-    <string name="share_remote_bugreport_notification_decline">DECLINE</string>
+    <string name="decline_remote_bugreport_action">DECLINE</string>
 
     <!-- Used to replace %s in urls retreived from the signin server with locales.  For Some        -->
     <!-- devices we don't support all the locales we ship to and need to replace the '%s' with a    -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 11f42ec..15521e4 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1771,13 +1771,12 @@
   <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" />
+  <java-symbol type="string" name="taking_remote_bugreport_notification_title" />
   <java-symbol type="string" name="share_remote_bugreport_notification_title" />
-  <java-symbol type="string" name="share_remote_bugreport_notification_message" />
-  <java-symbol type="string" name="share_finished_remote_bugreport_notification_message" />
   <java-symbol type="string" name="sharing_remote_bugreport_notification_title" />
-  <java-symbol type="string" name="sharing_remote_bugreport_notification_message" />
-  <java-symbol type="string" name="share_remote_bugreport_notification_accept" />
-  <java-symbol type="string" name="share_remote_bugreport_notification_decline" />
+  <java-symbol type="string" name="share_remote_bugreport_notification_message_finished" />
+  <java-symbol type="string" name="share_remote_bugreport_action" />
+  <java-symbol type="string" name="decline_remote_bugreport_action" />
   <java-symbol type="string" name="aerr_application" />
   <java-symbol type="string" name="aerr_process" />
   <java-symbol type="string" name="aerr_application_repeated" />
@@ -2392,6 +2391,7 @@
 
   <java-symbol type="string" name="config_packagedKeyboardName" />
   <java-symbol type="bool" name="config_forceWindowDrawsStatusBarBackground" />
+  <java-symbol type="bool" name="config_forceNavBarAlwaysOpaque" />
   <java-symbol type="color" name="system_bar_background_semi_transparent" />
 
   <!-- EditText suggestion popup. -->
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 54b453d..70995ac 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -2,7 +2,7 @@
 include $(CLEAR_VARS)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
-HWUI_NEW_OPS := false
+HWUI_NEW_OPS := true
 
 # Enables fine-grained GLES error checking
 # If set to true, every GLES call is wrapped & error checked
diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp
index 501cbe5..afe9807 100644
--- a/libs/hwui/ClipArea.cpp
+++ b/libs/hwui/ClipArea.cpp
@@ -375,15 +375,13 @@
             serialization->rect.set(mClipRegion.getBounds());
             break;
         }
+        // TODO: this is only done for draw time, should eventually avoid for record time
+        serialization->rect.snapToPixelBoundaries();
         mLastSerialization = serialization;
     }
     return mLastSerialization;
 }
 
-inline static const Rect& getRect(const ClipBase* scb) {
-    return reinterpret_cast<const ClipRect*>(scb)->rect;
-}
-
 inline static const RectangleList& getRectList(const ClipBase* scb) {
     return reinterpret_cast<const ClipRectList*>(scb)->rectList;
 }
@@ -425,9 +423,10 @@
                 && recordedClip->mode == ClipMode::Rectangle
                 && recordedClipTransform.rectToRect())) {
             // common case - result is a single rectangle
-            auto rectClip = allocator.create<ClipRect>(getRect(recordedClip));
+            auto rectClip = allocator.create<ClipRect>(recordedClip->rect);
             recordedClipTransform.mapRect(rectClip->rect);
             rectClip->rect.doIntersect(mClipRect);
+            rectClip->rect.snapToPixelBoundaries();
             mLastResolutionResult = rectClip;
         } else if (CC_UNLIKELY(mMode == ClipMode::Region
                 || recordedClip->mode == ClipMode::Region
@@ -438,11 +437,11 @@
             case ClipMode::Rectangle:
                 if (CC_LIKELY(recordedClipTransform.rectToRect())) {
                     // simple transform, skip creating SkPath
-                    Rect resultClip(getRect(recordedClip));
+                    Rect resultClip(recordedClip->rect);
                     recordedClipTransform.mapRect(resultClip);
                     other.setRect(resultClip.toSkIRect());
                 } else {
-                    SkPath transformedRect = pathFromTransformedRectangle(getRect(recordedClip),
+                    SkPath transformedRect = pathFromTransformedRectangle(recordedClip->rect,
                             recordedClipTransform);
                     other.setPath(transformedRect, createViewportRegion());
                 }
@@ -474,6 +473,7 @@
                 regionClip->region.op(mClipRegion, other, SkRegion::kIntersect_Op);
                 break;
             }
+            // Don't need to snap, since region's in int bounds
             regionClip->rect.set(regionClip->region.getBounds());
             mLastResolutionResult = regionClip;
         } else {
@@ -484,7 +484,7 @@
             }
 
             if (recordedClip->mode == ClipMode::Rectangle) {
-                rectList.intersectWith(getRect(recordedClip), recordedClipTransform);
+                rectList.intersectWith(recordedClip->rect, recordedClipTransform);
             } else {
                 const RectangleList& other = getRectList(recordedClip);
                 for (int i = 0; i < other.getTransformedRectanglesCount(); i++) {
@@ -495,6 +495,7 @@
                 }
             }
             rectListClip->rect = rectList.calculateBounds();
+            rectListClip->rect.snapToPixelBoundaries();
             mLastResolutionResult = rectListClip;
         }
     }
@@ -505,7 +506,7 @@
     if (!clip) return; // nothing to do
 
     if (CC_LIKELY(clip->mode == ClipMode::Rectangle)) {
-        clipRectWithTransform(getRect(clip), &transform, SkRegion::kIntersect_Op);
+        clipRectWithTransform(clip->rect, &transform, SkRegion::kIntersect_Op);
     } else if (CC_LIKELY(clip->mode == ClipMode::RectangleList)) {
         auto&& rectList = getRectList(clip);
         for (int i = 0; i < rectList.getTransformedRectanglesCount(); i++) {
diff --git a/libs/hwui/tests/unit/ClipAreaTests.cpp b/libs/hwui/tests/unit/ClipAreaTests.cpp
index dc2ea07..822d04f 100644
--- a/libs/hwui/tests/unit/ClipAreaTests.cpp
+++ b/libs/hwui/tests/unit/ClipAreaTests.cpp
@@ -27,7 +27,7 @@
 namespace android {
 namespace uirenderer {
 
-static Rect kViewportBounds(0, 0, 2048, 2048);
+static Rect kViewportBounds(2048, 2048);
 
 static ClipArea createClipArea() {
     ClipArea area;
@@ -140,17 +140,15 @@
 
     // rect list
     Matrix4 rotate;
-    rotate.loadRotate(2.0f);
-    area.clipRectWithTransform(Rect(200, 200), &rotate, SkRegion::kIntersect_Op);
+    rotate.loadRotate(5.0f);
+    area.clipRectWithTransform(Rect(50, 50, 150, 150), &rotate, SkRegion::kIntersect_Op);
     {
         auto serializedClip = area.serializeClip(allocator);
         ASSERT_NE(nullptr, serializedClip);
         ASSERT_EQ(ClipMode::RectangleList, serializedClip->mode);
         auto clipRectList = reinterpret_cast<const ClipRectList*>(serializedClip);
         EXPECT_EQ(2, clipRectList->rectList.getTransformedRectanglesCount());
-        EXPECT_FALSE(clipRectList->rect.isEmpty());
-        EXPECT_FLOAT_EQ(199.87817f, clipRectList->rect.right)
-            << "Right side should be clipped by rotated rect";
+        EXPECT_EQ(Rect(37, 54, 145, 163), clipRectList->rect);
         EXPECT_EQ(serializedClip, area.serializeClip(allocator))
                 << "Requery of clip on unmodified ClipArea must return same pointer.";
     }
@@ -241,5 +239,28 @@
     }
 }
 
+TEST(ClipArea, serializeIntersectedClip_snap) {
+    ClipArea area(createClipArea());
+    area.setClip(100.2, 100.4, 500.6, 500.8);
+    LinearAllocator allocator;
+
+    {
+        // no recorded clip case
+        auto resolvedClip = area.serializeIntersectedClip(allocator, nullptr, Matrix4::identity());
+        EXPECT_EQ(Rect(100, 100, 501, 501), resolvedClip->rect);
+    }
+    {
+        // recorded clip case
+        ClipRect recordedClip(Rect(100.12, 100.74));
+        Matrix4 translateScale;
+        translateScale.loadTranslate(100, 100, 0);
+        translateScale.scale(2, 3, 1); // recorded clip will have non-int coords, even after transform
+        auto resolvedClip = area.serializeIntersectedClip(allocator, &recordedClip, translateScale);
+        ASSERT_NE(nullptr, resolvedClip);
+        EXPECT_EQ(ClipMode::Rectangle, resolvedClip->mode);
+        EXPECT_EQ(Rect(100, 100, 300, 402), resolvedClip->rect);
+    }
+}
+
 } // namespace uirenderer
 } // namespace android
diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
index c39047c..d35b1f9 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -442,9 +442,7 @@
             // since the same clip will be computed at draw time. If such a change is made, this
             // check could be done at record time by querying the clip, or the clip could be altered
             // slightly so that it is serialized.
-            EXPECT_RECT_APPROX_EQ(Rect(58.57864, 58.57864, 341.42136, 341.42136),
-                    (reinterpret_cast<const ClipRect*>(op.localClip))->rect);
-
+            EXPECT_EQ(Rect(59, 59, 341, 341), op.localClip->rect);
             EXPECT_EQ(Rect(400, 400), op.unmappedBounds);
             expectedMatrix.loadIdentity();
             EXPECT_MATRIX_APPROX_EQ(expectedMatrix, op.localMatrix);
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index c7e96cf..8206d23 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2147,9 +2147,10 @@
                                 }
                                 break;
                             case MSSG_RECORDING_CONFIG_CHANGE:
-                                final AudioRecordingCallback cb = (AudioRecordingCallback) msg.obj;
-                                if (cb != null) {
-                                    cb.onRecordConfigChanged();
+                                final RecordConfigChangeCallbackData cbData =
+                                        (RecordConfigChangeCallbackData) msg.obj;
+                                if (cbData.mCb != null) {
+                                    cbData.mCb.onRecordConfigChanged(cbData.mConfigs);
                                 }
                                 break;
                             default:
@@ -2734,8 +2735,10 @@
     public static abstract class AudioRecordingCallback {
         /**
          * Called whenever the device recording configuration has changed.
+         * @param configs array containing the results of
+         *      {@link AudioManager#getActiveRecordConfigurations()}.
          */
-        public void onRecordConfigChanged() {}
+        public void onRecordConfigChanged(AudioRecordConfiguration[] configs) {}
     }
 
     private static class AudioRecordingCallbackInfo {
@@ -2747,6 +2750,17 @@
         }
     }
 
+    private final static class RecordConfigChangeCallbackData {
+        final AudioRecordingCallback mCb;
+        final AudioRecordConfiguration[] mConfigs;
+
+        RecordConfigChangeCallbackData(AudioRecordingCallback cb,
+                AudioRecordConfiguration[] configs) {
+            mCb = cb;
+            mConfigs = configs;
+        }
+    }
+
     /**
      * Register a callback to be notified of audio recording changes through
      * {@link AudioRecordingCallback}
@@ -2882,14 +2896,15 @@
 
     private final IRecordingConfigDispatcher mRecCb = new IRecordingConfigDispatcher.Stub() {
 
-        public void dispatchRecordingConfigChange() {
+        public void dispatchRecordingConfigChange(AudioRecordConfiguration[] configs) {
             synchronized(mRecordCallbackLock) {
                 if (mRecordCallbackList != null) {
                     for (int i=0 ; i < mRecordCallbackList.size() ; i++) {
                         final AudioRecordingCallbackInfo arci = mRecordCallbackList.get(i);
                         if (arci.mHandler != null) {
                             final Message m = arci.mHandler.obtainMessage(
-                                    MSSG_RECORDING_CONFIG_CHANGE/*what*/, arci.mCb/*obj*/);
+                                    MSSG_RECORDING_CONFIG_CHANGE/*what*/,
+                                    new RecordConfigChangeCallbackData(arci.mCb, configs)/*obj*/);
                             arci.mHandler.sendMessage(m);
                         }
                     }
diff --git a/media/java/android/media/AudioRecordConfiguration.java b/media/java/android/media/AudioRecordConfiguration.java
index 2fc8ee8..de78a5a 100644
--- a/media/java/android/media/AudioRecordConfiguration.java
+++ b/media/java/android/media/AudioRecordConfiguration.java
@@ -16,10 +16,13 @@
 
 package android.media;
 
+import android.annotation.IntDef;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Objects;
 
@@ -53,6 +56,19 @@
         mPatchHandle = patchHandle;
     }
 
+    /** @hide */
+    @IntDef({
+        MediaRecorder.AudioSource.DEFAULT,
+        MediaRecorder.AudioSource.VOICE_UPLINK,
+        MediaRecorder.AudioSource.VOICE_DOWNLINK,
+        MediaRecorder.AudioSource.VOICE_CALL,
+        MediaRecorder.AudioSource.CAMCORDER,
+        MediaRecorder.AudioSource.VOICE_RECOGNITION,
+        MediaRecorder.AudioSource.VOICE_COMMUNICATION
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AudioSource {}
+
     /**
      * Returns the audio source being used for the recording.
      * @return one of {@link MediaRecorder.AudioSource#MIC},
@@ -63,7 +79,7 @@
      *       {@link MediaRecorder.AudioSource#VOICE_RECOGNITION},
      *       {@link MediaRecorder.AudioSource#VOICE_COMMUNICATION}.
      */
-    public int getClientAudioSource() { return mClientSource; }
+    public @AudioSource int getClientAudioSource() { return mClientSource; }
 
     /**
      * Returns the session number of the recording, see {@link AudioRecord#getAudioSessionId()}.
diff --git a/media/java/android/media/IRecordingConfigDispatcher.aidl b/media/java/android/media/IRecordingConfigDispatcher.aidl
index a5eb8b9f..eaa92ca 100644
--- a/media/java/android/media/IRecordingConfigDispatcher.aidl
+++ b/media/java/android/media/IRecordingConfigDispatcher.aidl
@@ -16,6 +16,8 @@
 
 package android.media;
 
+import android.media.AudioRecordConfiguration;
+
 /**
  * AIDL for the RecordingActivity monitor in AudioService to signal audio recording updates.
  *
@@ -23,6 +25,6 @@
  */
 oneway interface IRecordingConfigDispatcher {
 
-    void dispatchRecordingConfigChange();
+    void dispatchRecordingConfigChange(in AudioRecordConfiguration[] configs);
 
 }
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index b5ea2a0..f593685 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -370,15 +370,14 @@
      * called when the loading is complete.
      * </p><p>
      * In case the media item does not have any children, call {@link Result#sendResult}
-     * with an empty list which is not {@code null}. If {@code null} is sent that means
-     * the given {@code parentId} is invalid and {@link MediaBrowser.SubscriptionCallback#onError}
-     * will be called.
+     * with an empty list. When the given {@code parentId} is invalid, implementations must
+     * call {@link Result#sendResult result.sendResult} with {@code null}, which will invoke
+     * {@link MediaBrowser.SubscriptionCallback#onError}.
      * </p>
      *
      * @param parentId The id of the parent media item whose children are to be
      *            queried.
-     * @param result The Result to send the list of children to. Send null if the
-     *            id is invalid.
+     * @param result The Result to send the list of children to.
      */
     public abstract void onLoadChildren(@NonNull String parentId,
             @NonNull Result<List<MediaBrowser.MediaItem>> result);
@@ -394,15 +393,14 @@
      * called when the loading is complete.
      * </p><p>
      * In case the media item does not have any children, call {@link Result#sendResult}
-     * with an empty list which is not {@code null}. If {@code null} is sent that means
-     * the given {@code parentId} is invalid and {@link MediaBrowser.SubscriptionCallback#onError}
-     * will be called.
+     * with an empty list. When the given {@code parentId} is invalid, implementations must
+     * call {@link Result#sendResult result.sendResult} with {@code null}, which will invoke
+     * {@link MediaBrowser.SubscriptionCallback#onError}.
      * </p>
      *
      * @param parentId The id of the parent media item whose children are to be
      *            queried.
-     * @param result The Result to send the list of children to. Send null if the
-     *            id is invalid.
+     * @param result The Result to send the list of children to.
      * @param options A bundle of service-specific arguments sent from the media
      *            browse. The information returned through the result should be
      *            affected by the contents of this bundle.
@@ -424,13 +422,18 @@
      * result.detach} may be called before returning from this function, and
      * then {@link Result#sendResult result.sendResult} called when the item has
      * been loaded.
-     * <p>
-     * The default implementation sends a null result.
+     * </p><p>
+     * When the given {@code itemId} is invalid, implementations must call
+     * {@link Result#sendResult result.sendResult} with {@code null}, which will
+     * invoke {@link MediaBrowser.ItemCallback#onError}.
+     * </p><p>
+     * The default implementation calls {@link Result#sendResult result.sendResult}
+     * with {@code null}.
+     * </p>
      *
      * @param itemId The id for the specific
      *            {@link android.media.browse.MediaBrowser.MediaItem}.
-     * @param result The Result to send the item to. Send null if the id is
-     *            invalid.
+     * @param result The Result to send the item to.
      */
     public void onLoadItem(String itemId, Result<MediaBrowser.MediaItem> result) {
         result.sendResult(null);
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 2004a3a..d6994b3 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -1302,7 +1302,10 @@
     jobject patternObj = env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoPatternID);
 
     CryptoPlugin::Pattern pattern;
-    if (patternObj != NULL) {
+    if (patternObj == NULL) {
+        pattern.mEncryptBlocks = 0;
+        pattern.mSkipBlocks = 0;
+    } else {
         pattern.mEncryptBlocks = env->GetIntField(patternObj, gFields.patternEncryptBlocksID);
         pattern.mSkipBlocks = env->GetIntField(patternObj, gFields.patternSkipBlocksID);
     }
diff --git a/packages/DocumentsUI/perf-tests/src/com/android/documentsui/FilesActivityPerfTest.java b/packages/DocumentsUI/perf-tests/src/com/android/documentsui/FilesActivityPerfTest.java
index 05fd2f7..bf056f1 100644
--- a/packages/DocumentsUI/perf-tests/src/com/android/documentsui/FilesActivityPerfTest.java
+++ b/packages/DocumentsUI/perf-tests/src/com/android/documentsui/FilesActivityPerfTest.java
@@ -121,7 +121,7 @@
                 activity.removeEventListener(listener);
             }
 
-            assertEquals(i, measurements.size());
+            assertEquals(i + 1, measurements.size());
 
             // Go back to the empty root.
             bots.roots.openRoot(STRESS_ROOT_0_ID);
diff --git a/packages/DocumentsUI/res/layout/drawer_layout.xml b/packages/DocumentsUI/res/layout/drawer_layout.xml
index 065102b..09f4401 100644
--- a/packages/DocumentsUI/res/layout/drawer_layout.xml
+++ b/packages/DocumentsUI/res/layout/drawer_layout.xml
@@ -46,6 +46,7 @@
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_marginStart="4dp"
+                    android:popupTheme="?actionBarPopupTheme"
                     android:overlapAnchor="true" />
 
             </com.android.documentsui.DocumentsToolbar>
diff --git a/packages/DocumentsUI/res/layout/fixed_layout.xml b/packages/DocumentsUI/res/layout/fixed_layout.xml
index 84a928d..9f7296b 100644
--- a/packages/DocumentsUI/res/layout/fixed_layout.xml
+++ b/packages/DocumentsUI/res/layout/fixed_layout.xml
@@ -44,6 +44,7 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_marginStart="4dp"
+                android:popupTheme="?actionBarPopupTheme"
                 android:overlapAnchor="true" />
 
         </com.android.documentsui.DocumentsToolbar>
diff --git a/packages/DocumentsUI/res/layout/item_subdir.xml b/packages/DocumentsUI/res/layout/item_subdir.xml
index b8251d1..ffe4afe 100644
--- a/packages/DocumentsUI/res/layout/item_subdir.xml
+++ b/packages/DocumentsUI/res/layout/item_subdir.xml
@@ -24,16 +24,6 @@
     android:orientation="horizontal"
     android:baselineAligned="false">
 
-    <ImageView
-        android:id="@+id/subdir"
-        android:layout_width="24dp"
-        android:layout_height="24dp"
-        android:paddingEnd="8dp"
-        android:scaleType="centerInside"
-        android:visibility="gone"
-        android:src="@drawable/ic_subdirectory_arrow"
-        android:contentDescription="@null" />
-
     <TextView
         android:id="@android:id/title"
         android:layout_width="0dp"
diff --git a/packages/DocumentsUI/res/layout/single_pane_layout.xml b/packages/DocumentsUI/res/layout/single_pane_layout.xml
index 235d22d..8bf023f 100644
--- a/packages/DocumentsUI/res/layout/single_pane_layout.xml
+++ b/packages/DocumentsUI/res/layout/single_pane_layout.xml
@@ -43,6 +43,7 @@
                 android:id="@+id/stack"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
+                android:popupTheme="?actionBarPopupTheme"
                 android:layout_marginStart="4dp"
                 android:overlapAnchor="true" />
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java b/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java
index 4cba135..c520204 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/NavigationView.java
@@ -220,17 +220,14 @@
                         .inflate(R.layout.item_subdir, parent, false);
             }
 
-            final ImageView subdir = (ImageView) convertView.findViewById(R.id.subdir);
             final TextView title = (TextView) convertView.findViewById(android.R.id.title);
             final DocumentInfo doc = getItem(position);
 
             if (position == 0) {
                 final RootInfo root = mEnv.getCurrentRoot();
                 title.setText(root.title);
-                subdir.setVisibility(View.GONE);
             } else {
                 title.setText(doc.displayName);
-                subdir.setVisibility(View.VISIBLE);
             }
 
             return convertView;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
index 8b619b6..0831dbf 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
@@ -52,13 +52,14 @@
         super(context, parent, R.layout.item_doc_list);
 
         mTitle = (TextView) itemView.findViewById(android.R.id.title);
-        mDetails = (LinearLayout) itemView.findViewById(R.id.line2);
         mDate = (TextView) itemView.findViewById(R.id.date);
         mSize = (TextView) itemView.findViewById(R.id.size);
         mSummary = (TextView) itemView.findViewById(android.R.id.summary);
         mIconMime = (ImageView) itemView.findViewById(R.id.icon_mime);
         mIconThumb = (ImageView) itemView.findViewById(R.id.icon_thumb);
         mIconCheck = (ImageView) itemView.findViewById(R.id.icon_check);
+        // Warning: mDetails view doesn't exists in layout-sw720dp-land layout
+        mDetails = (LinearLayout) itemView.findViewById(R.id.line2);
 
         mIconHelper = iconHelper;
     }
@@ -110,11 +111,11 @@
         mTitle.setVisibility(View.VISIBLE);
 
 
-        // Note, we don't show any details for any directory...ever.
+        boolean hasDetails = false;
         if (isDirectory) {
-            mDetails.setVisibility(View.GONE);
+            // Note, we don't show any details for any directory...ever.
+            hasDetails = false;
         } else {
-            boolean hasDetails = false;
             if (docSummary != null) {
                 hasDetails = true;
                 mSummary.setText(docSummary);
@@ -136,8 +137,11 @@
                 mSize.setText(Formatter.formatFileSize(mContext, docSize));
             } else {
                 mSize.setVisibility(View.GONE);
-                mDetails.setVisibility(View.GONE);
             }
+        }
+
+        // mDetails view doesn't exists in layout-sw720dp-land layout
+        if (mDetails != null) {
             mDetails.setVisibility(hasDetails ? View.VISIBLE : View.GONE);
         }
     }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index 409f6a7..b1d42e7 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -519,6 +519,9 @@
     @Override
     public void showPromptReason(int reason) {
         if (mCurrentSecuritySelection != SecurityMode.None) {
+            if (reason != PROMPT_REASON_NONE) {
+                Log.i(TAG, "Strong auth required, reason: " + reason);
+            }
             getSecurityView(mCurrentSecuritySelection).showPromptReason(reason);
         }
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
index 2dfdfda..418b138 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
@@ -41,7 +41,7 @@
 public class TileUtils {
 
     private static final boolean DEBUG = false;
-    private static final boolean DEBUG_TIMING = true;
+    private static final boolean DEBUG_TIMING = false;
 
     private static final String LOG_TAG = "TileUtils";
 
diff --git a/packages/SystemUI/res/color/notification_guts_buttons.xml b/packages/SystemUI/res/color/notification_guts_buttons.xml
new file mode 100644
index 0000000..f7a4ee9
--- /dev/null
+++ b/packages/SystemUI/res/color/notification_guts_buttons.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true"
+          android:color="@*android:color/material_deep_teal_500" />
+    <item android:color="@android:color/black"
+          android:alpha=".87" />
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/notification_guts.xml b/packages/SystemUI/res/layout/notification_guts.xml
index 4b0c834..1ab6bf9 100644
--- a/packages/SystemUI/res/layout/notification_guts.xml
+++ b/packages/SystemUI/res/layout/notification_guts.xml
@@ -63,29 +63,32 @@
             android:id="@+id/importance_buttons"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:paddingTop="8dp"
-            android:paddingBottom="8dip"
+            android:paddingTop="4dp"
+            android:paddingBottom="16dip"
             android:paddingEnd="8dp" >
         <RadioButton
                 android:id="@+id/silent_importance"
                 android:layout_width="wrap_content"
                 android:layout_height="48dp"
+                android:paddingStart="32dp"
                 android:text="@string/show_silently"
-                style="@style/TextAppearance.NotificationGuts.Primary"
-                android:buttonTint="#858383" />
+                style="@style/TextAppearance.NotificationGuts.Radio"
+                android:buttonTint="@color/notification_guts_buttons" />
         <RadioButton
                 android:id="@+id/block_importance"
                 android:layout_width="wrap_content"
                 android:layout_height="48dp"
+                android:paddingStart="32dp"
                 android:text="@string/block"
-                style="@style/TextAppearance.NotificationGuts.Primary"
-                android:buttonTint="#858383" />
+                style="@style/TextAppearance.NotificationGuts.Radio"
+                android:buttonTint="@color/notification_guts_buttons" />
         <RadioButton
                 android:id="@+id/reset_importance"
                 android:layout_width="wrap_content"
                 android:layout_height="48dp"
-                style="@style/TextAppearance.NotificationGuts.Primary"
-                android:buttonTint="#858383" />
+                android:paddingStart="32dp"
+                style="@style/TextAppearance.NotificationGuts.Radio"
+                android:buttonTint="@color/notification_guts_buttons" />
     </RadioGroup>
     <!-- Importance slider -->
     <LinearLayout
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 11df681..89890d6 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -323,6 +323,10 @@
         <item name="android:textSize">16sp</item>
     </style>
 
+    <style name="TextAppearance.NotificationGuts.Radio">
+        <item name="android:alpha">.87</item>
+    </style>
+
     <style name="TextAppearance.NotificationGuts.Button">
         <item name="android:textSize">14sp</item>
         <item name="android:textAllCaps">true</item>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 8ccf60d..24b45cc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -167,6 +167,11 @@
         }
     };
 
+    public int getColumnCount() {
+        if (mPages.size() == 0) return 0;
+        return mPages.get(0).mColumns;
+    }
+
     public static class TilePage extends TileLayout {
         private int mMaxRows = 3;
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index c643d67..6137349 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -16,6 +16,7 @@
 
 import android.util.Log;
 import android.view.View;
+import android.view.View.OnAttachStateChangeListener;
 import android.view.View.OnLayoutChangeListener;
 import android.view.animation.PathInterpolator;
 import android.widget.TextView;
@@ -25,14 +26,20 @@
 import com.android.systemui.qs.TouchAnimator.Builder;
 import com.android.systemui.qs.TouchAnimator.Listener;
 import com.android.systemui.statusbar.phone.QSTileHost;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
 
 import java.util.ArrayList;
 import java.util.Collection;
 
-public class QSAnimator implements Callback, PageListener, Listener, OnLayoutChangeListener {
+public class QSAnimator implements Callback, PageListener, Listener, OnLayoutChangeListener,
+        OnAttachStateChangeListener, Tunable {
 
     private static final String TAG = "QSAnimator";
 
+    private static final String ALLOW_FANCY_ANIMATION = "sysui_qs_fancy_anim";
+    private static final String MOVE_FULL_ROWS = "sysui_qs_move_whole_rows";
+
     public static final PathInterpolator TRANSLATION_Y_INTERPOLATOR =
             new PathInterpolator(.1f, .3f, 1, 1);
 
@@ -44,34 +51,77 @@
     private final QSPanel mQsPanel;
     private final QSContainer mQsContainer;
 
+    private PagedTileLayout mPagedLayout;
+
     private boolean mOnFirstPage = true;
     private TouchAnimator mFirstPageAnimator;
     private TouchAnimator mFirstPageDelayedAnimator;
     private TouchAnimator mTranslationYAnimator;
     private TouchAnimator mNonfirstPageAnimator;
 
+    private boolean mOnKeyguard;
+
+    private boolean mAllowFancy;
+    private boolean mFullRows;
+    private int mNumQuickTiles;
+
     public QSAnimator(QSContainer container, QuickQSPanel quickPanel, QSPanel panel) {
         mQsContainer = container;
         mQuickQsPanel = quickPanel;
         mQsPanel = panel;
+        mQsPanel.addOnAttachStateChangeListener(this);
         container.addOnLayoutChangeListener(this);
         QSTileLayout tileLayout = mQsPanel.getTileLayout();
         if (tileLayout instanceof PagedTileLayout) {
-            ((PagedTileLayout) tileLayout).setPageListener(this);
+            mPagedLayout = ((PagedTileLayout) tileLayout);
+            mPagedLayout.setPageListener(this);
         } else {
             Log.w(TAG, "QS Not using page layout");
         }
     }
 
+    public void setOnKeyguard(boolean onKeyguard) {
+        mOnKeyguard = onKeyguard;
+        if (mOnKeyguard) {
+            clearAnimationState();
+        }
+    }
+
     public void setHost(QSTileHost qsh) {
         qsh.addCallback(this);
     }
 
     @Override
+    public void onViewAttachedToWindow(View v) {
+        TunerService.get(mQsContainer.getContext()).addTunable(this, ALLOW_FANCY_ANIMATION,
+                MOVE_FULL_ROWS, QuickQSPanel.NUM_QUICK_TILES);
+    }
+
+    @Override
+    public void onViewDetachedFromWindow(View v) {
+        TunerService.get(mQsContainer.getContext()).removeTunable(this);
+    }
+
+    @Override
+    public void onTuningChanged(String key, String newValue) {
+        if (ALLOW_FANCY_ANIMATION.equals(key)) {
+            mAllowFancy = newValue == null || Integer.parseInt(newValue) != 0;
+            if (!mAllowFancy) {
+                clearAnimationState();
+            }
+        } else if (MOVE_FULL_ROWS.equals(key)) {
+            mFullRows = newValue != null && Integer.parseInt(newValue) != 0;
+        } else if (QuickQSPanel.NUM_QUICK_TILES.equals(key)) {
+            mNumQuickTiles = QuickQSPanel.getNumQuickTiles(mQsContainer.getContext());
+            clearAnimationState();
+        }
+        updateAnimators();
+    }
+
+    @Override
     public void onPageChanged(boolean isFirst) {
         if (mOnFirstPage == isFirst) return;
         if (!isFirst) {
-            setPosition(1);
             clearAnimationState();
         }
         mOnFirstPage = isFirst;
@@ -85,6 +135,7 @@
         int count = 0;
         int[] loc1 = new int[2];
         int[] loc2 = new int[2];
+        int lastYDiff = 0;
         firstPageDelayedBuilder.setStartDelay(EXPANDED_TILE_DELAY);
         firstPageBuilder.setListener(this);
         translationYBuilder.setInterpolator(TRANSLATION_Y_INTERPOLATOR);
@@ -92,18 +143,20 @@
         firstPageDelayedBuilder.addFloat(mQsPanel.getTileLayout(), "alpha", 0, 1);
         mAllViews.clear();
         mTopFiveQs.clear();
+        mAllViews.add((View) mQsPanel.getTileLayout());
         for (QSTile<?> tile : tiles) {
             QSTileBaseView tileView = mQsPanel.getTileView(tile);
             final TextView label = ((QSTileView) tileView).getLabel();
-            if (count++ < 5) {
+            final View tileIcon = tileView.getIcon();
+            if (count < mNumQuickTiles && mAllowFancy) {
                 // Quick tiles.
                 QSTileBaseView quickTileView = mQuickQsPanel.getTileView(tile);
-                final View tileIcon = tileView.getIcon();
 
                 getRelativePosition(loc1, quickTileView.getIcon(), mQsContainer);
                 getRelativePosition(loc2, tileIcon, mQsContainer);
                 final int xDiff = loc2[0] - loc1[0];
                 final int yDiff = loc2[1] - loc1[1];
+                lastYDiff = yDiff;
                 // Move the quick tile right from its location to the new one.
                 firstPageBuilder.addFloat(quickTileView, "translationX", 0, xDiff);
                 translationYBuilder.addFloat(quickTileView, "translationY", 0, yDiff);
@@ -119,20 +172,38 @@
 
                 mTopFiveQs.add(tileIcon);
                 mAllViews.add(tileIcon);
+                mAllViews.add(label);
                 mAllViews.add(quickTileView);
+            } else if (mFullRows && isIconInAnimatedRow(count)) {
+                firstPageBuilder.addFloat(tileView, "translationY", mQsPanel.getHeight(), 0);
+                translationYBuilder.addFloat(label, "translationY", -lastYDiff, 0);
+                translationYBuilder.addFloat(tileIcon, "translationY", -lastYDiff, 0);
+                mAllViews.add(tileIcon);
+                mAllViews.add(label);
             }
             mAllViews.add(tileView);
             mAllViews.add(label);
+            count++;
         }
-        mFirstPageAnimator = firstPageBuilder.build();
-        mFirstPageDelayedAnimator = firstPageDelayedBuilder.build();
-        mTranslationYAnimator = translationYBuilder.build();
+        if (mAllowFancy) {
+            mFirstPageAnimator = firstPageBuilder.build();
+            mFirstPageDelayedAnimator = firstPageDelayedBuilder.build();
+            mTranslationYAnimator = translationYBuilder.build();
+        }
         mNonfirstPageAnimator = new TouchAnimator.Builder()
                 .addFloat(mQuickQsPanel, "alpha", 1, 0)
                 .setEndDelay(.5f)
                 .build();
     }
 
+    private boolean isIconInAnimatedRow(int count) {
+        if (mPagedLayout == null) {
+            return false;
+        }
+        final int columnCount = mPagedLayout.getColumnCount();
+        return count < ((mNumQuickTiles + columnCount - 1) / columnCount) * columnCount;
+    }
+
     private void getRelativePosition(int[] loc1, View view, View parent) {
         loc1[0] = 0 + view.getWidth() / 2;
         loc1[1] = 0;
@@ -148,7 +219,10 @@
 
     public void setPosition(float position) {
         if (mFirstPageAnimator == null) return;
-        if (mOnFirstPage) {
+        if (mOnKeyguard) {
+            return;
+        }
+        if (mOnFirstPage && mAllowFancy) {
             mQuickQsPanel.setAlpha(1);
             mFirstPageAnimator.setPosition(position);
             mFirstPageDelayedAnimator.setPosition(position);
@@ -186,12 +260,17 @@
     private void clearAnimationState() {
         final int N = mAllViews.size();
         mQuickQsPanel.setAlpha(0);
+        mQuickQsPanel.setVisibility(View.VISIBLE);
         for (int i = 0; i < N; i++) {
             View v = mAllViews.get(i);
             v.setAlpha(1);
             v.setTranslationX(1);
             v.setTranslationY(1);
         }
+        final int N2 = mTopFiveQs.size();
+        for (int i = 0; i < N2; i++) {
+            mTopFiveQs.get(i).setVisibility(View.VISIBLE);
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
index c59da8d..c0c1e4d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java
@@ -156,6 +156,7 @@
     public void setKeyguardShowing(boolean keyguardShowing) {
         if (DEBUG) Log.d(TAG, "setKeyguardShowing " + keyguardShowing);
         mKeyguardShowing = keyguardShowing;
+        mQSAnimator.setOnKeyguard(keyguardShowing);
         updateQsState();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 8b826ee..f8a57d0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -26,6 +26,8 @@
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile.SignalState;
 import com.android.systemui.qs.QSTile.State;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -35,6 +37,8 @@
  */
 public class QuickQSPanel extends QSPanel {
 
+    public static final String NUM_QUICK_TILES = "sysui_qqs_count";
+
     private int mMaxTiles;
     private QSPanel mFullPanel;
     private View mHeader;
@@ -52,6 +56,18 @@
     }
 
     @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        TunerService.get(mContext).addTunable(mNumTiles, NUM_QUICK_TILES);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        TunerService.get(mContext).removeTunable(mNumTiles);
+    }
+
+    @Override
     protected void createCustomizePanel() {
         // No customizing from the header.
     }
@@ -86,6 +102,7 @@
 
     public void setMaxTiles(int maxTiles) {
         mMaxTiles = maxTiles;
+        setTiles(mHost.getTiles());
     }
 
     @Override
@@ -114,6 +131,17 @@
         super.setTiles(quickTiles);
     }
 
+    private final Tunable mNumTiles = new Tunable() {
+        @Override
+        public void onTuningChanged(String key, String newValue) {
+            setMaxTiles(getNumQuickTiles(mContext));
+        }
+    };
+
+    public static int getNumQuickTiles(Context context) {
+        return TunerService.get(context).getValue(NUM_QUICK_TILES, 5);
+    }
+
     private static class HeaderTileLayout extends LinearLayout implements QSTileLayout {
 
         private final Space mEndSpacer;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index b60fca8c1..17c3eeb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -672,8 +672,9 @@
 
             boolean isFrontMostTaskInGroup = task.group == null || task.group.isFrontMostTask(task);
             if (isFrontMostTaskInGroup) {
-                getStackTransform(taskProgress, mInitialScrollP, mFocusState, tmpTransform, null,
-                        false /* ignoreSingleTaskCase */, false /* forceUpdate */);
+                getStackTransform(taskProgress, taskProgress, mInitialScrollP, mFocusState,
+                        tmpTransform, null, false /* ignoreSingleTaskCase */,
+                        false /* forceUpdate */);
                 float screenY = tmpTransform.rect.top;
                 boolean hasVisibleThumbnail = (prevScreenY - screenY) > taskBarHeight;
                 if (hasVisibleThumbnail) {
@@ -725,15 +726,16 @@
             return transformOut;
         } else {
             // Return early if we have an invalid index
-            if (task == null || mTaskIndexMap.get(task.key.id, -1) == -1) {
+            int nonOverrideTaskProgress = mTaskIndexMap.get(task.key.id, -1);
+            if (task == null || nonOverrideTaskProgress == -1) {
                 transformOut.reset();
                 return transformOut;
             }
             float taskProgress = ignoreTaskOverrides
-                    ? mTaskIndexMap.get(task.key.id, 0)
+                    ? nonOverrideTaskProgress
                     : getStackScrollForTask(task);
-            getStackTransform(taskProgress, stackScroll, focusState, transformOut,
-                    frontTransform, false /* ignoreSingleTaskCase */, forceUpdate);
+            getStackTransform(taskProgress, nonOverrideTaskProgress, stackScroll, focusState,
+                    transformOut, frontTransform, false /* ignoreSingleTaskCase */, forceUpdate);
             return transformOut;
         }
     }
@@ -758,9 +760,9 @@
      *                             internally to ensure that we can calculate the transform for any
      *                             position in the stack.
      */
-    public void getStackTransform(float taskProgress, float stackScroll, int focusState,
-            TaskViewTransform transformOut, TaskViewTransform frontTransform,
-            boolean ignoreSingleTaskCase, boolean forceUpdate) {
+    public void getStackTransform(float taskProgress, float nonOverrideTaskProgress,
+            float stackScroll, int focusState, TaskViewTransform transformOut,
+            TaskViewTransform frontTransform, boolean ignoreSingleTaskCase, boolean forceUpdate) {
         SystemServicesProxy ssp = Recents.getSystemServices();
 
         // Compute the focused and unfocused offset
@@ -769,6 +771,8 @@
         mFocusedRange.offset(boundedStackScroll);
         float boundedScrollUnfocusedRangeX = mUnfocusedRange.getNormalizedX(taskProgress);
         float boundedScrollFocusedRangeX = mFocusedRange.getNormalizedX(taskProgress);
+        float boundedScrollUnfocusedNonOverrideRangeX =
+                mUnfocusedRange.getNormalizedX(nonOverrideTaskProgress);
         mUnfocusedRange.offset(stackScroll);
         mFocusedRange.offset(stackScroll);
         boolean unfocusedVisible = mUnfocusedRange.isInRange(taskProgress);
@@ -812,7 +816,7 @@
 
             y = (mStackRect.top - mTaskRect.top) +
                     (int) Utilities.mapRange(focusState, unfocusedY, focusedY);
-            z = Utilities.mapRange(Utilities.clamp01(boundedScrollUnfocusedRangeX),
+            z = Utilities.mapRange(Utilities.clamp01(boundedScrollUnfocusedNonOverrideRangeX),
                     mMinTranslationZ, mMaxTranslationZ);
             dimAlpha = Utilities.mapRange(focusState, unfocusedDim, focusedDim);
             viewOutlineAlpha = Utilities.mapRange(Utilities.clamp01(boundedScrollUnfocusedRangeX),
@@ -952,9 +956,9 @@
                 mFocusedRange.relativeMin);
         float max = Utilities.mapRange(mFocusState, mUnfocusedRange.relativeMax,
                 mFocusedRange.relativeMax);
-        getStackTransform(min, 0f, mFocusState, mBackOfStackTransform, null,
+        getStackTransform(min, min, 0f, mFocusState, mBackOfStackTransform, null,
                 true /* ignoreSingleTaskCase */, true /* forceUpdate */);
-        getStackTransform(max, 0f, mFocusState, mFrontOfStackTransform, null,
+        getStackTransform(max, max, 0f, mFocusState, mFrontOfStackTransform, null,
                 true /* ignoreSingleTaskCase */, true /* forceUpdate */);
         mBackOfStackTransform.visible = true;
         mFrontOfStackTransform.visible = true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 469a1fc..143f160 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1891,7 +1891,7 @@
         }
     }
 
-    protected abstract boolean isPanelFullyCollapsed();
+    public abstract boolean isPanelFullyCollapsed();
 
     /**
      * Cancel this notification and tell the StatusBarManagerService / NotificationManagerService
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index ef16388..073a848 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -3554,7 +3554,7 @@
     }
 
     @Override
-    protected boolean isPanelFullyCollapsed() {
+    public boolean isPanelFullyCollapsed() {
         return mNotificationPanel.isFullyCollapsed();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index 256cc6b..326ca2b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -296,7 +296,6 @@
         mHost = host;
         host.setHeaderView(this);
         mHeaderQsPanel.setQSPanelAndHeader(mQsPanel, this);
-        mHeaderQsPanel.setMaxTiles(5);
         mHeaderQsPanel.setHost(host);
         setUserInfoController(host.getUserInfoController());
         setBatteryController(host.getBatteryController());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 0ed6ef8..2524e1a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -125,7 +125,7 @@
     }
 
     @Override
-    protected boolean isPanelFullyCollapsed() {
+    public boolean isPanelFullyCollapsed() {
         return false;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
index fb425ab..285dfd1 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
@@ -50,7 +50,7 @@
     private TextView mPlayPauseDescriptionTextView;
     private View mCloseButtonView;
     private View mCloseDescriptionView;
-    private boolean mMovePipToFullscreen;
+    private boolean mPipMovedToFullscreen;
 
     private MediaController.Callback mMediaControllerCallback = new MediaController.Callback() {
         @Override
@@ -70,7 +70,7 @@
             @Override
             public void onClick(View v) {
                 mPipManager.movePipToFullscreen();
-                mMovePipToFullscreen = true;
+                mPipMovedToFullscreen = true;
                 finish();
             }
         });
@@ -169,7 +169,7 @@
     }
 
     private void restorePipAndFinish() {
-        if (!mMovePipToFullscreen) {
+        if (!mPipMovedToFullscreen) {
             mPipManager.resizePinnedStack(PipManager.STATE_PIP_OVERLAY);
         }
         finish();
@@ -225,7 +225,7 @@
     @Override
     public void finish() {
         super.finish();
-        if (mPipManager.isRecentsShown() && !mMovePipToFullscreen) {
+        if (mPipManager.isRecentsShown() && !mPipMovedToFullscreen) {
             SystemUI[] services = ((SystemUIApplication) getApplication()).getServices();
             for (int i = services.length - 1; i >= 0; i--) {
                 if (services[i] instanceof Recents) {
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 8171b49..f3140d2 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -1798,38 +1798,56 @@
 
     // ACTION: User tapped notification action to cancel a bug report
     // CATEGORY: NOTIFICATION
+    // OS: N
+    // GMS: 7.8.99
     ACTION_BUGREPORT_NOTIFICATION_ACTION_CANCEL = 296;
 
     // ACTION: User tapped notification action to launch bug report details screen
     // CATEGORY: NOTIFICATION
+    // OS: N
+    // GMS: 7.8.99
     ACTION_BUGREPORT_NOTIFICATION_ACTION_DETAILS = 297;
 
     // ACTION: User tapped notification action to take adition screenshot on bug report
     // CATEGORY: NOTIFICATION
+    // OS: N
+    // GMS: 7.8.99
     ACTION_BUGREPORT_NOTIFICATION_ACTION_SCREENSHOT = 298;
 
     // ACTION: User tapped notification to share bug report
     // CATEGORY: NOTIFICATION
+    // OS: N
+    // GMS: 7.8.99
     ACTION_BUGREPORT_NOTIFICATION_ACTION_SHARE = 299;
 
     // ACTION: User changed bug report name using the details screen
     // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N
+    // GMS: 7.8.99
     ACTION_BUGREPORT_DETAILS_NAME_CHANGED = 300;
 
     // ACTION: User changed bug report title using the details screen
     // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N
+    // GMS: 7.8.99
     ACTION_BUGREPORT_DETAILS_TITLE_CHANGED = 301;
 
     // ACTION: User changed bug report description using the details screen
     // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N
+    // GMS: 7.8.99
     ACTION_BUGREPORT_DETAILS_DESCRIPTION_CHANGED = 302;
 
     // ACTION: User tapped Save in the bug report details screen.
     // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N
+    // GMS: 7.8.99
     ACTION_BUGREPORT_DETAILS_SAVED = 303;
 
     // ACTION: User tapped Cancel in the bug report details screen.
     // CATEGORY: GLOBAL_SYSTEM_UI
+    // OS: N
+    // GMS: 7.8.99
     ACTION_BUGREPORT_DETAILS_CANCELED = 304;
 
     // Tuner: Open/close calibrate dialog.
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index f1a9c44..cd4d107d 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -3495,9 +3495,8 @@
             // The agent was running with a stub Application object, so shut it down.
             // !!! We hardcode the confirmation UI's package name here rather than use a
             //     manifest flag!  TODO something less direct.
-            if (app.uid != Process.SYSTEM_UID
-                    && !app.packageName.equals("com.android.backupconfirm")
-                    && app.uid != Process.PHONE_UID) {
+            if (app.uid >= Process.FIRST_APPLICATION_UID
+                    && !app.packageName.equals("com.android.backupconfirm")) {
                 if (MORE_DEBUG) Slog.d(TAG, "Killing agent host process");
                 mActivityManager.killApplicationProcess(app.processName, app.uid);
             } else {
@@ -6881,7 +6880,7 @@
                     // The agent was running with a stub Application object, so shut it down.
                     // !!! We hardcode the confirmation UI's package name here rather than use a
                     //     manifest flag!  TODO something less direct.
-                    if (app.uid != Process.SYSTEM_UID
+                    if (app.uid >= Process.FIRST_APPLICATION_UID
                             && !app.packageName.equals("com.android.backupconfirm")) {
                         if (DEBUG) Slog.d(TAG, "Killing host process");
                         mActivityManager.killApplicationProcess(app.processName, app.uid);
@@ -8625,13 +8624,15 @@
                     // it is explicitly not killed following that operation.
                     //
                     // We execute this kill when these conditions hold:
-                    //    1. the app did not request its own restore (mTargetPackage == null), and either
-                    //    2a. the app is a full-data target (TYPE_FULL_STREAM) or
+                    //    1. it's not a system-uid process,
+                    //    2. the app did not request its own restore (mTargetPackage == null), and either
+                    //    3a. the app is a full-data target (TYPE_FULL_STREAM) or
                     //     b. the app does not state android:killAfterRestore="false" in its manifest
                     final int appFlags = mCurrentPackage.applicationInfo.flags;
                     final boolean killAfterRestore =
-                            (mRestoreDescription.getDataType() == RestoreDescription.TYPE_FULL_STREAM)
-                            || ((appFlags & ApplicationInfo.FLAG_KILL_AFTER_RESTORE) != 0);
+                            (mCurrentPackage.applicationInfo.uid >= Process.FIRST_APPLICATION_UID)
+                            && ((mRestoreDescription.getDataType() == RestoreDescription.TYPE_FULL_STREAM)
+                                    || ((appFlags & ApplicationInfo.FLAG_KILL_AFTER_RESTORE) != 0));
 
                     if (mTargetPackage == null && killAfterRestore) {
                         if (DEBUG) Slog.d(TAG, "Restore complete, killing host process of "
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 079b2f2..86040c2 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -164,7 +164,7 @@
         implements PendingIntent.OnFinished {
     private static final String TAG = "ConnectivityService";
 
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
     private static final boolean VDBG = false;
 
     private static final boolean LOGD_RULES = false;
@@ -455,7 +455,7 @@
      */
     private class LegacyTypeTracker {
 
-        private static final boolean DBG = true;
+        private static final boolean DBG = false;
         private static final boolean VDBG = false;
         private static final String TAG = "CSLegacyTypeTracker";
 
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 63c9822..3b6c62b 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -1960,14 +1960,6 @@
             throw new IllegalArgumentException("Unknown id: " + id);
         }
 
-        if (mCurClient != null && mCurAttribute != null) {
-            // We have already made sure that the package name belongs to the application's UID.
-            // No further UID check is required.
-            if (SystemConfig.getInstance().getFixedImeApps().contains(mCurAttribute.packageName)) {
-                return;
-            }
-        }
-
         // See if we need to notify a subtype change within the same IME.
         if (id.equals(mCurMethodId)) {
             final int subtypeCount = info.getSubtypeCount();
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index f4c6225..11aef17 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -58,7 +58,7 @@
     private static final String TAG = "NsdService";
     private static final String MDNS_TAG = "mDnsConnector";
 
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
 
     private Context mContext;
     private ContentResolver mContentResolver;
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index 1c1784e..73d8bdd 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -105,9 +105,6 @@
     // background while in data-usage save mode, as read from the configuration files.
     final ArraySet<String> mAllowInDataUsageSave = new ArraySet<>();
 
-    // These are the app package names that should not allow IME switching.
-    final ArraySet<String> mFixedImeApps = new ArraySet<>();
-
     // These are the package names of apps which should be in the 'always'
     // URL-handling state upon factory reset.
     final ArraySet<String> mLinkedApps = new ArraySet<>();
@@ -159,10 +156,6 @@
         return mAllowInDataUsageSave;
     }
 
-    public ArraySet<String> getFixedImeApps() {
-        return mFixedImeApps;
-    }
-
     public ArraySet<String> getLinkedApps() {
         return mLinkedApps;
     }
@@ -411,17 +404,6 @@
                     XmlUtils.skipCurrentTag(parser);
                     continue;
 
-                } else if ("fixed-ime-app".equals(name) && allowAll) {
-                    String pkgname = parser.getAttributeValue(null, "package");
-                    if (pkgname == null) {
-                        Slog.w(TAG, "<fixed-ime-app> without package in " + permFile + " at "
-                                + parser.getPositionDescription());
-                    } else {
-                        mFixedImeApps.add(pkgname);
-                    }
-                    XmlUtils.skipCurrentTag(parser);
-                    continue;
-
                 } else if ("app-link".equals(name) && allowAppConfigs) {
                     String pkgname = parser.getAttributeValue(null, "package");
                     if (pkgname == null) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index dee3d02..037ec59 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -101,6 +101,8 @@
 import android.app.PendingIntent;
 import android.app.ProfilerInfo;
 import android.app.admin.DevicePolicyManager;
+import android.app.admin.DevicePolicyManagerInternal;
+import android.app.admin.IDevicePolicyManager;
 import android.app.assist.AssistContent;
 import android.app.assist.AssistStructure;
 import android.app.backup.IBackupManager;
@@ -5261,9 +5263,13 @@
     public boolean clearApplicationUserData(final String packageName,
             final IPackageDataObserver observer, int userId) {
         enforceNotIsolatedCaller("clearApplicationUserData");
-        if (packageName != null && packageName.equals(mDeviceOwnerName)) {
-            throw new SecurityException("Clearing DeviceOwner data is forbidden.");
+
+        final DevicePolicyManagerInternal dpmi = LocalServices
+                .getService(DevicePolicyManagerInternal.class);
+        if (dpmi != null && dpmi.hasDeviceOwnerOrProfileOwner(packageName, userId)) {
+            throw new SecurityException("Cannot clear data for a device owner or a profile owner");
         }
+
         int uid = Binder.getCallingUid();
         int pid = Binder.getCallingPid();
         userId = mUserController.handleIncomingUser(pid, uid, userId, false,
@@ -6287,9 +6293,10 @@
             // If the app is being launched for restore or full backup, set it up specially
             boolean isRestrictedBackupMode = false;
             if (mBackupTarget != null && mBackupAppName.equals(processName)) {
-                isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
-                        || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
-                        || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
+                isRestrictedBackupMode = mBackupTarget.appInfo.uid >= Process.FIRST_APPLICATION_UID
+                        && ((mBackupTarget.backupMode == BackupRecord.RESTORE)
+                                || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
+                                || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL));
             }
 
             notifyPackageUse(app.instrumentationInfo != null
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 74c8363..d1e1d27 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1115,7 +1115,7 @@
             r.stopped = true;
             r.state = ActivityState.STOPPED;
 
-            mWindowManager.notifyAppStopped(r.appToken);
+            mWindowManager.notifyAppStopped(r.appToken, true);
 
             if (getVisibleBehindActivity() == r) {
                 mStackSupervisor.requestVisibleBehindLocked(r, false);
@@ -2247,6 +2247,10 @@
                     next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
                 }
 
+                // Well the app will no longer be stopped.
+                // Clear app token stopped state in window manager if needed.
+                mWindowManager.notifyAppStopped(next.appToken, false);
+
                 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
                         System.identityHashCode(next), next.task.taskId, next.shortComponentName);
 
diff --git a/services/core/java/com/android/server/am/AppErrorDialog.java b/services/core/java/com/android/server/am/AppErrorDialog.java
index 86cdbcc..ddfab4d 100644
--- a/services/core/java/com/android/server/am/AppErrorDialog.java
+++ b/services/core/java/com/android/server/am/AppErrorDialog.java
@@ -25,6 +25,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
+import android.text.BidiFormatter;
 import android.util.Slog;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -68,18 +69,21 @@
         mProc = data.proc;
         mResult = data.result;
         mRepeating = data.repeating;
+        BidiFormatter bidi = BidiFormatter.getInstance();
+
         if ((mProc.pkgList.size() == 1) &&
                 (mName = context.getPackageManager().getApplicationLabel(mProc.info)) != null) {
             setTitle(res.getString(
                     mRepeating ? com.android.internal.R.string.aerr_application_repeated
                             : com.android.internal.R.string.aerr_application,
-                    mName.toString(), mProc.info.processName));
+                    bidi.unicodeWrap(mName.toString()),
+                    bidi.unicodeWrap(mProc.info.processName)));
         } else {
             mName = mProc.processName;
             setTitle(res.getString(
                     mRepeating ? com.android.internal.R.string.aerr_process_repeated
                             : com.android.internal.R.string.aerr_process,
-                    mName.toString()));
+                    bidi.unicodeWrap(mName.toString())));
         }
 
         setCancelable(false);
diff --git a/services/core/java/com/android/server/am/AppNotRespondingDialog.java b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
index 6d1d9f3..c6befd7 100644
--- a/services/core/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
@@ -27,6 +27,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
+import android.text.BidiFormatter;
 import android.util.Slog;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -84,9 +85,11 @@
             }
         }
 
+        BidiFormatter bidi = BidiFormatter.getInstance();
+
         setTitle(name2 != null
-                ? res.getString(resid, name1.toString(), name2.toString())
-                : res.getString(resid, name1.toString()));
+                ? res.getString(resid, bidi.unicodeWrap(name1.toString()), bidi.unicodeWrap(name2.toString()))
+                : res.getString(resid, bidi.unicodeWrap(name1.toString())));
 
         if (aboveSystem) {
             getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
diff --git a/services/core/java/com/android/server/audio/RecordingActivityMonitor.java b/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
index 7e76ac4..86dcd0f 100644
--- a/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
@@ -54,12 +54,15 @@
         if (MediaRecorder.isSystemOnlyAudioSource(source)) {
             return;
         }
-        if (updateSnapshot(event, session, source, recordingInfo)) {
-            final Iterator<RecMonitorClient> clientIterator = mClients.iterator();
+        final AudioRecordConfiguration[] configs =
+                updateSnapshot(event, session, source, recordingInfo);
+        if (configs != null){
             synchronized(mClients) {
+                final Iterator<RecMonitorClient> clientIterator = mClients.iterator();
                 while (clientIterator.hasNext()) {
                     try {
-                        clientIterator.next().mDispatcherCb.dispatchRecordingConfigChange();
+                        clientIterator.next().mDispatcherCb.dispatchRecordingConfigChange(
+                                configs);
                     } catch (RemoteException e) {
                         Log.w(TAG, "Could not call dispatchRecordingConfigChange() on client", e);
                     }
@@ -115,14 +118,19 @@
      * @param recordingFormat see
      *     {@link AudioSystem.AudioRecordingCallback#onRecordingConfigurationChanged(int, int, int, int[])}
      *     for the definition of the contents of the array
-     * @return true if the list of active recording sessions has been modified, false otherwise.
+     * @return null if the list of active recording sessions has not been modified, an array
+     *     with the current active configurations otherwise.
      */
-    private boolean updateSnapshot(int event, int session, int source, int[] recordingInfo) {
+    private AudioRecordConfiguration[] updateSnapshot(int event, int session, int source,
+            int[] recordingInfo) {
+        final boolean configChanged;
+        final AudioRecordConfiguration[] configs;
         synchronized(mRecordConfigs) {
             switch (event) {
             case AudioManager.RECORD_CONFIG_EVENT_STOP:
                 // return failure if an unknown recording session stopped
-                return (mRecordConfigs.remove(new Integer(session)) != null);
+                configChanged = (mRecordConfigs.remove(new Integer(session)) != null);
+                break;
             case AudioManager.RECORD_CONFIG_EVENT_START:
                 final AudioFormat clientFormat = new AudioFormat.Builder()
                         .setEncoding(recordingInfo[0])
@@ -143,25 +151,32 @@
                             new AudioRecordConfiguration(session, source,
                                     clientFormat, deviceFormat, patchHandle);
                     if (updatedConfig.equals(mRecordConfigs.get(sessionKey))) {
-                        return false;
+                        configChanged = false;
                     } else {
                         // config exists but has been modified
                         mRecordConfigs.remove(sessionKey);
                         mRecordConfigs.put(sessionKey, updatedConfig);
-                        return true;
+                        configChanged = true;
                     }
                 } else {
                     mRecordConfigs.put(sessionKey,
                             new AudioRecordConfiguration(session, source,
                                     clientFormat, deviceFormat, patchHandle));
-                    return true;
+                    configChanged = true;
                 }
+                break;
             default:
                 Log.e(TAG, String.format("Unknown event %d for session %d, source %d",
                         event, session, source));
-                return false;
+                configChanged = false;
+            }
+            if (configChanged) {
+                configs = mRecordConfigs.values().toArray(new AudioRecordConfiguration[0]);
+            } else {
+                configs = null;
             }
         }
+        return configs;
     }
 
     /**
diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
index 90c9ddf..9e1f6b8 100644
--- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
+++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
@@ -60,7 +60,7 @@
 public class KeepaliveTracker {
 
     private static final String TAG = "KeepaliveTracker";
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
 
     public static final String PERMISSION = android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD;
 
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index fb8b110..73da427 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -76,7 +76,7 @@
  * {@hide}
  */
 public class NetworkMonitor extends StateMachine {
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
     private static final String TAG = "NetworkMonitor";
     private static final String DEFAULT_SERVER = "connectivitycheck.gstatic.com";
     private static final int SOCKET_TIMEOUT_MS = 10000;
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index debda14..22cefd1 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -54,7 +54,7 @@
  */
 public class PermissionMonitor {
     private static final String TAG = "PermissionMonitor";
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
     private static final boolean SYSTEM = true;
     private static final boolean NETWORK = false;
 
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 760b218..4eecc81 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -90,7 +90,7 @@
 
     private Context mContext;
     private final static String TAG = "Tethering";
-    private final static boolean DBG = true;
+    private final static boolean DBG = false;
     private final static boolean VDBG = false;
 
     // TODO - remove both of these - should be part of interface inspection/selection stuff
diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java
index 9f1435a..2807ec8 100644
--- a/services/core/java/com/android/server/net/IpConfigStore.java
+++ b/services/core/java/com/android/server/net/IpConfigStore.java
@@ -40,7 +40,7 @@
 
 public class IpConfigStore {
     private static final String TAG = "IpConfigStore";
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
 
     protected final DelayedDiskWrite mWriter;
 
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 2900345..3acd2ca 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -1619,7 +1619,7 @@
             try {
                 final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
                 if (oldPolicy != policy) {
-                    setUidPolicyUncheckedLocked(uid, policy, true);
+                    setUidPolicyUncheckedLocked(uid, oldPolicy, policy, true);
                 }
             } finally {
                 Binder.restoreCallingIdentity(token);
@@ -1639,7 +1639,7 @@
             final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
             policy |= oldPolicy;
             if (oldPolicy != policy) {
-                setUidPolicyUncheckedLocked(uid, policy, true);
+                setUidPolicyUncheckedLocked(uid, oldPolicy, policy, true);
             }
         }
     }
@@ -1656,11 +1656,22 @@
             final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
             policy = oldPolicy & ~policy;
             if (oldPolicy != policy) {
-                setUidPolicyUncheckedLocked(uid, policy, true);
+                setUidPolicyUncheckedLocked(uid, oldPolicy, policy, true);
             }
         }
     }
 
+    private void setUidPolicyUncheckedLocked(int uid, int oldPolicy, int policy, boolean persist) {
+        setUidPolicyUncheckedLocked(uid, policy, persist);
+
+        // Checks if app was added or removed to the blacklist.
+        if ((oldPolicy == POLICY_NONE && policy == POLICY_REJECT_METERED_BACKGROUND)
+                || (oldPolicy == POLICY_REJECT_METERED_BACKGROUND && policy == POLICY_NONE)) {
+            mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED, uid, 0)
+                    .sendToTarget();
+        }
+    }
+
     private void setUidPolicyUncheckedLocked(int uid, int policy, boolean persist) {
         mUidPolicy.put(uid, policy);
 
@@ -1988,7 +1999,20 @@
     public int getRestrictBackgroundByCaller() {
         mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
         final int uid = Binder.getCallingUid();
+
         synchronized (mRulesLock) {
+            // Must clear identity because getUidPolicy() is restricted to system.
+            final long token = Binder.clearCallingIdentity();
+            final int policy;
+            try {
+                policy = getUidPolicy(uid);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+            if (policy == POLICY_REJECT_METERED_BACKGROUND) {
+                // App is blacklisted.
+                return RESTRICT_BACKGROUND_STATUS_ENABLED;
+            }
             if (!mRestrictBackground) {
                 return RESTRICT_BACKGROUND_STATUS_DISABLED;
             }
@@ -2519,7 +2543,7 @@
         final List<UserInfo> users = mUserManager.getUsers();
         for (int i = 0; i < users.size(); i++) {
             final UserInfo user = users.get(i);
-            for (int j = mPowerSaveTempWhitelistAppIds.size() - 1; j >= 0; i--) {
+            for (int j = mPowerSaveTempWhitelistAppIds.size() - 1; j >= 0; j--) {
                 int appId = mPowerSaveTempWhitelistAppIds.keyAt(j);
                 int uid = UserHandle.getUid(user.id, appId);
                 updateRuleForAppIdleLocked(uid);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 5562e76..b2ee0b2 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -103,6 +103,7 @@
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.IActivityManager;
+import android.app.admin.DevicePolicyManagerInternal;
 import android.app.admin.IDevicePolicyManager;
 import android.app.backup.IBackupManager;
 import android.content.BroadcastReceiver;
@@ -15110,8 +15111,15 @@
             final IPackageDataObserver observer, final int userId) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
+
         enforceCrossUserPermission(Binder.getCallingUid(), userId,
                 true /* requireFullPermission */, false /* checkShell */, "clear application data");
+
+        final DevicePolicyManagerInternal dpmi = LocalServices
+                .getService(DevicePolicyManagerInternal.class);
+        if (dpmi != null && dpmi.hasDeviceOwnerOrProfileOwner(packageName, userId)) {
+            throw new SecurityException("Cannot clear data for a device owner or a profile owner");
+        }
         // Queue up an async operation since the package deletion may take a little while.
         mHandler.post(new Runnable() {
             public void run() {
@@ -15123,8 +15131,8 @@
                 clearExternalStorageDataSync(packageName, userId, true);
                 if (succeeded) {
                     // invoke DeviceStorageMonitor's update method to clear any notifications
-                    DeviceStorageMonitorInternal
-                            dsm = LocalServices.getService(DeviceStorageMonitorInternal.class);
+                    DeviceStorageMonitorInternal dsm = LocalServices
+                            .getService(DeviceStorageMonitorInternal.class);
                     if (dsm != null) {
                         dsm.checkMemory();
                     }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 310ad53..bf5a8f6 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -2604,7 +2604,6 @@
         if (pkg.volumeUuid != null) {
             serializer.attribute(null, "volumeUuid", pkg.volumeUuid);
         }
-
         if (pkg.parentPackageName != null) {
             serializer.attribute(null, "parentPackageName", pkg.parentPackageName);
         }
@@ -4171,9 +4170,19 @@
     };
 
     static final Object[] PRIVATE_FLAG_DUMP_SPEC = new Object[] {
-        ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, "PRIVILEGED",
-        ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK, "FORWARD_LOCK",
+        ApplicationInfo.PRIVATE_FLAG_HIDDEN, "HIDDEN",
         ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE, "CANT_SAVE_STATE",
+        ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK, "FORWARD_LOCK",
+        ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, "PRIVILEGED",
+        ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS, "HAS_DOMAIN_URLS",
+        ApplicationInfo.PRIVATE_FLAG_FORCE_DEVICE_ENCRYPTED, "FORCE_DEVICE_ENCRYPTED",
+        ApplicationInfo.PRIVATE_FLAG_ENCRYPTION_AWARE, "ENCRYPTION_AWARE",
+        ApplicationInfo.PRIVATE_FLAG_AUTOPLAY, "AUTOPLAY",
+        ApplicationInfo.PRIVATE_FLAG_PARTIALLY_ENCRYPTION_AWARE, "PARTIALLY_ENCRYPTION_AWARE",
+        ApplicationInfo.PRIVATE_FLAG_EPHEMERAL, "EPHEMERAL",
+        ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER, "REQUIRED_FOR_SYSTEM_USER",
+        ApplicationInfo.PRIVATE_FLAG_RESIZEABLE_ACTIVITIES, "RESIZEABLE_ACTIVITIES",
+        ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND, "BACKUP_IN_FOREGROUND",
     };
 
     void dumpVersionLPr(IndentingPrintWriter pw) {
@@ -4316,6 +4325,10 @@
             }
             pw.print(prefix); pw.print("  versionName="); pw.println(ps.pkg.mVersionName);
             pw.print(prefix); pw.print("  splits="); dumpSplitNames(pw, ps.pkg); pw.println();
+            final int apkSigningVersion = PackageParser.getApkSigningVersion(ps.pkg);
+            if (apkSigningVersion != PackageParser.APK_SIGNING_UNKNOWN) {
+                pw.print(prefix); pw.print("  apkSigningVersion="); pw.println(apkSigningVersion);
+            }
             pw.print(prefix); pw.print("  applicationInfo=");
                 pw.println(ps.pkg.applicationInfo.toString());
             pw.print(prefix); pw.print("  flags="); printFlags(pw, ps.pkg.applicationInfo.flags,
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 6320413..252dda7 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -535,6 +535,7 @@
     boolean mForceStatusBar;
     boolean mForceStatusBarFromKeyguard;
     private boolean mForceStatusBarTransparent;
+    boolean mForceNavBarOpaque;
     boolean mHideLockScreen;
     boolean mForcingShowNavBar;
     int mForcingShowNavBarLayer;
@@ -1715,6 +1716,9 @@
         if (mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
             mShortPressWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE;
         }
+
+        mForceNavBarOpaque = res.getBoolean(
+                com.android.internal.R.bool.config_forceNavBarAlwaysOpaque);
     }
 
     @Override
@@ -7080,6 +7084,10 @@
                     | View.SYSTEM_UI_TRANSPARENT);
         }
 
+        if (mForceNavBarOpaque) {
+            vis &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT);
+        }
+
         if (mForceWindowDrawsStatusBarBackground) {
             vis |= View.STATUS_BAR_TRANSPARENT;
             vis &= ~View.STATUS_BAR_TRANSLUCENT;
diff --git a/services/core/java/com/android/server/policy/ShortcutManager.java b/services/core/java/com/android/server/policy/ShortcutManager.java
index 9284442..57ae523 100644
--- a/services/core/java/com/android/server/policy/ShortcutManager.java
+++ b/services/core/java/com/android/server/policy/ShortcutManager.java
@@ -138,14 +138,16 @@
                     ComponentName componentName = new ComponentName(packageName, className);
                     try {
                         info = packageManager.getActivityInfo(componentName,
-                                PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE);
+                                PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+                                | PackageManager.MATCH_UNINSTALLED_PACKAGES);
                     } catch (PackageManager.NameNotFoundException e) {
                         String[] packages = packageManager.canonicalToCurrentPackageNames(
                                 new String[] { packageName });
                         componentName = new ComponentName(packages[0], className);
                         try {
                             info = packageManager.getActivityInfo(componentName,
-                                    PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE);
+                                    PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE
+                                    | PackageManager.MATCH_UNINSTALLED_PACKAGES);
                         } catch (PackageManager.NameNotFoundException e1) {
                             Log.w(TAG, "Unable to add bookmark: " + packageName
                                     + "/" + className, e);
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index ecfbc0a..2731f429 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -354,6 +354,11 @@
                 continue;
             }
 
+            if (DEBUG_ADD_REMOVE) Slog.e(TAG_WM, "win=" + win
+                    + " destroySurfaces: mAppStopped=" + mAppStopped
+                    + " win.mWindowRemovalAllowed=" + win.mWindowRemovalAllowed
+                    + " win.mRemoveOnExit=" + win.mRemoveOnExit);
+
             win.destroyOrSaveSurface();
             if (win.mRemoveOnExit) {
                 win.mAnimatingExit = false;
@@ -372,15 +377,19 @@
         }
     }
 
-    // The application has stopped, so destroy any surfaces which were keeping alive
-    // in case they were still being used.
-    void notifyAppStopped() {
-        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
-        mAppStopped = true;
-        destroySurfaces();
+    /**
+     * If the application has stopped it is okay to destroy any surfaces which were keeping alive
+     * in case they were still being used.
+     */
+    void notifyAppStopped(boolean stopped) {
+        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: stopped=" + stopped + " " + this);
+        mAppStopped = stopped;
 
-        // Remove any starting window that was added for this app if they are still around.
-        mTask.mService.scheduleRemoveStartingWindowLocked(this);
+        if (stopped) {
+            destroySurfaces();
+            // Remove any starting window that was added for this app if they are still around.
+            mTask.mService.scheduleRemoveStartingWindowLocked(this);
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 7c2a8e3..b64aaa8 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -4197,7 +4197,7 @@
     }
 
     @Override
-    public void notifyAppStopped(IBinder token) {
+    public void notifyAppStopped(IBinder token, boolean stopped) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "notifyAppStopped()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
@@ -4210,7 +4210,7 @@
                 Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: " + token);
                 return;
             }
-            wtoken.notifyAppStopped();
+            wtoken.notifyAppStopped(stopped);
         }
     }
 
@@ -4247,6 +4247,8 @@
                 wtoken.appDied = false;
                 wtoken.removeAllWindows();
             } else if (visible) {
+                if (DEBUG_ADD_REMOVE) Slog.v(
+                        TAG_WM, "No longer Stopped: " + wtoken);
                 wtoken.mAppStopped = false;
                 wtoken.setWindowsExiting(false);
             }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 1490109..d8aa5d7 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -31,8 +31,8 @@
 import android.Manifest.permission;
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accounts.AccountManager;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
@@ -151,6 +151,8 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.nio.charset.StandardCharsets;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
@@ -280,6 +282,20 @@
     private static final int PROFILE_KEYGUARD_FEATURES =
             PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER | PROFILE_KEYGUARD_FEATURES_PROFILE_ONLY;
 
+    private static final int CODE_OK = 0;
+    private static final int CODE_HAS_DEVICE_OWNER = 1;
+    private static final int CODE_USER_HAS_PROFILE_OWNER = 2;
+    private static final int CODE_USER_NOT_RUNNING = 3;
+    private static final int CODE_USER_SETUP_COMPLETED = 4;
+    private static final int CODE_NONSYSTEM_USER_EXISTS = 5;
+    private static final int CODE_ACCOUNTS_NOT_EMPTY = 6;
+    private static final int CODE_NOT_SYSTEM_USER = 7;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({ CODE_OK, CODE_HAS_DEVICE_OWNER, CODE_USER_HAS_PROFILE_OWNER, CODE_USER_NOT_RUNNING,
+            CODE_USER_SETUP_COMPLETED, CODE_NOT_SYSTEM_USER })
+    private @interface DeviceOwnerPreConditionCode {}
+
     private static final int DEVICE_ADMIN_DEACTIVATE_TIMEOUT = 10000;
 
     final Context mContext;
@@ -308,7 +324,7 @@
      * Whether or not device admin feature is supported. If it isn't return defaults for all
      * public methods.
      */
-    private boolean mHasFeature;
+    boolean mHasFeature;
 
     private final SecurityLogMonitor mSecurityLogMonitor;
 
@@ -328,7 +344,7 @@
 
         @Override
         public void onReceive(Context context, Intent intent) {
-            if (RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_DISPATCH.equals(intent.getAction())
+            if (DevicePolicyManager.ACTION_REMOTE_BUGREPORT_DISPATCH.equals(intent.getAction())
                     && mRemoteBugreportServiceIsActive.get()) {
                 onBugreportFinished(intent);
             }
@@ -342,10 +358,9 @@
             String action = intent.getAction();
             mInjector.getNotificationManager().cancel(LOG_TAG,
                     RemoteBugreportUtils.NOTIFICATION_ID);
-            if (RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_SHARING_ACCEPTED.equals(action)) {
+            if (DevicePolicyManager.ACTION_BUGREPORT_SHARING_ACCEPTED.equals(action)) {
                 onBugreportSharingAccepted();
-            } else if (RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_SHARING_DECLINED
-                    .equals(action)) {
+            } else if (DevicePolicyManager.ACTION_BUGREPORT_SHARING_DECLINED.equals(action)) {
                 onBugreportSharingDeclined();
             }
             mContext.unregisterReceiver(mRemoteBugreportConsentReceiver);
@@ -437,15 +452,14 @@
                     && userHandle == mOwners.getDeviceOwnerUserId()
                     && getDeviceOwnerRemoteBugreportUri() != null) {
                 IntentFilter filterConsent = new IntentFilter();
-                filterConsent.addAction(
-                        RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_SHARING_DECLINED);
-                filterConsent.addAction(
-                        RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_SHARING_ACCEPTED);
+                filterConsent.addAction(DevicePolicyManager.ACTION_BUGREPORT_SHARING_DECLINED);
+                filterConsent.addAction(DevicePolicyManager.ACTION_BUGREPORT_SHARING_ACCEPTED);
                 mContext.registerReceiver(mRemoteBugreportConsentReceiver, filterConsent);
-                mInjector.getNotificationManager().notify(LOG_TAG,
+                mInjector.getNotificationManager().notifyAsUser(LOG_TAG,
                         RemoteBugreportUtils.NOTIFICATION_ID,
                         RemoteBugreportUtils.buildNotification(mContext,
-                                RemoteBugreportUtils.NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED));
+                                DevicePolicyManager.NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED),
+                                UserHandle.ALL);
             }
             if (Intent.ACTION_BOOT_COMPLETED.equals(action)
                     || ACTION_EXPIRED_PASSWORD_NOTIFICATION.equals(action)) {
@@ -5068,9 +5082,9 @@
             mRemoteBugreportServiceIsActive.set(true);
             mRemoteBugreportSharingAccepted.set(false);
             registerRemoteBugreportReceivers();
-            mInjector.getNotificationManager().notify(LOG_TAG, RemoteBugreportUtils.NOTIFICATION_ID,
+            mInjector.getNotificationManager().notifyAsUser(LOG_TAG, RemoteBugreportUtils.NOTIFICATION_ID,
                     RemoteBugreportUtils.buildNotification(mContext,
-                            RemoteBugreportUtils.NOTIFICATION_BUGREPORT_STARTED));
+                            DevicePolicyManager.NOTIFICATION_BUGREPORT_STARTED), UserHandle.ALL);
             mHandler.postDelayed(mRemoteBugreportTimeoutRunnable,
                     RemoteBugreportUtils.REMOTE_BUGREPORT_TIMEOUT_MILLIS);
             return true;
@@ -5104,7 +5118,7 @@
     private void registerRemoteBugreportReceivers() {
         try {
             IntentFilter filterFinished = new IntentFilter(
-                    RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_DISPATCH,
+                    DevicePolicyManager.ACTION_REMOTE_BUGREPORT_DISPATCH,
                     RemoteBugreportUtils.BUGREPORT_MIMETYPE);
             mContext.registerReceiver(mRemoteBugreportFinishedReceiver, filterFinished);
         } catch (IntentFilter.MalformedMimeTypeException e) {
@@ -5112,8 +5126,8 @@
             Slog.w(LOG_TAG, "Failed to set type " + RemoteBugreportUtils.BUGREPORT_MIMETYPE, e);
         }
         IntentFilter filterConsent = new IntentFilter();
-        filterConsent.addAction(RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_SHARING_DECLINED);
-        filterConsent.addAction(RemoteBugreportUtils.ACTION_REMOTE_BUGREPORT_SHARING_ACCEPTED);
+        filterConsent.addAction(DevicePolicyManager.ACTION_BUGREPORT_SHARING_DECLINED);
+        filterConsent.addAction(DevicePolicyManager.ACTION_BUGREPORT_SHARING_ACCEPTED);
         mContext.registerReceiver(mRemoteBugreportConsentReceiver, filterConsent);
     }
 
@@ -5126,16 +5140,17 @@
             bugreportUriString = bugreportUri.toString();
         }
         String bugreportHash = intent.getStringExtra(
-                RemoteBugreportUtils.EXTRA_REMOTE_BUGREPORT_HASH);
+                DevicePolicyManager.EXTRA_REMOTE_BUGREPORT_HASH);
         if (mRemoteBugreportSharingAccepted.get()) {
             shareBugreportWithDeviceOwnerIfExists(bugreportUriString, bugreportHash);
             mInjector.getNotificationManager().cancel(LOG_TAG,
                     RemoteBugreportUtils.NOTIFICATION_ID);
         } else {
             setDeviceOwnerRemoteBugreportUriAndHash(bugreportUriString, bugreportHash);
-            mInjector.getNotificationManager().notify(LOG_TAG, RemoteBugreportUtils.NOTIFICATION_ID,
+            mInjector.getNotificationManager().notifyAsUser(LOG_TAG, RemoteBugreportUtils.NOTIFICATION_ID,
                     RemoteBugreportUtils.buildNotification(mContext,
-                            RemoteBugreportUtils.NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED));
+                            DevicePolicyManager.NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED),
+                            UserHandle.ALL);
         }
         mContext.unregisterReceiver(mRemoteBugreportFinishedReceiver);
     }
@@ -5166,9 +5181,10 @@
         if (bugreportUriString != null) {
             shareBugreportWithDeviceOwnerIfExists(bugreportUriString, bugreportHash);
         } else if (mRemoteBugreportServiceIsActive.get()) {
-            mInjector.getNotificationManager().notify(LOG_TAG, RemoteBugreportUtils.NOTIFICATION_ID,
+            mInjector.getNotificationManager().notifyAsUser(LOG_TAG, RemoteBugreportUtils.NOTIFICATION_ID,
                     RemoteBugreportUtils.buildNotification(mContext,
-                            RemoteBugreportUtils.NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED));
+                            DevicePolicyManager.NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED),
+                            UserHandle.ALL);
         }
     }
 
@@ -5934,52 +5950,40 @@
     /**
      * The Device owner can only be set by adb or an app with the MANAGE_PROFILE_AND_DEVICE_OWNERS
      * permission.
-     * The device owner can only be set before the setup phase of the primary user has completed,
-     * except for adb if no accounts or additional users are present on the device.
      */
     private void enforceCanSetDeviceOwnerLocked(int userId) {
-        if (mOwners.hasDeviceOwner()) {
-            throw new IllegalStateException("Trying to set the device owner, but device owner "
-                    + "is already set.");
-        }
-        if (mOwners.hasProfileOwner(userId)) {
-            throw new IllegalStateException("Trying to set the device owner, but the user already "
-                    + "has a profile owner.");
-        }
-        if (!mUserManager.isUserRunning(new UserHandle(userId))) {
-            throw new IllegalStateException("User not running: " + userId);
-        }
-
         int callingUid = mInjector.binderGetCallingUid();
-        if (callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID) {
-            if (!hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
-                return;
-            }
-            // STOPSHIP Do proper check in split user mode
-            if (!mInjector.userManagerIsSplitSystemUser()) {
-                if (mUserManager.getUserCount() > 1) {
-                    throw new IllegalStateException(
-                            "Not allowed to set the device owner because there "
-                                    + "are already several users on the device");
-                }
-                if (AccountManager.get(mContext).getAccounts().length > 0) {
-                    throw new IllegalStateException(
-                            "Not allowed to set the device owner because there "
-                                    + "are already some accounts on the device");
-                }
-            }
-            return;
+        boolean isAdb = callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID;
+        if (!isAdb) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS, null);
         }
-        // STOPSHIP check the caller UID with userId
 
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS, null);
-        // STOPSHIP Do proper check in split user mode
-        if (!mInjector.userManagerIsSplitSystemUser()) {
-            if (hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
-                throw new IllegalStateException("Cannot set the device owner if the device is "
-                        + "already set-up");
-            }
+        final int code = checkSetDeviceOwnerPreCondition(userId, isAdb);
+        switch (code) {
+            case CODE_OK:
+                return;
+            case CODE_HAS_DEVICE_OWNER:
+                throw new IllegalStateException(
+                        "Trying to set the device owner, but device owner is already set.");
+            case CODE_USER_HAS_PROFILE_OWNER:
+                throw new IllegalStateException("Trying to set the device owner, but the user "
+                        + "already has a profile owner.");
+            case CODE_USER_NOT_RUNNING:
+                throw new IllegalStateException("User not running: " + userId);
+            case CODE_NOT_SYSTEM_USER:
+                throw new IllegalStateException("User is not system user");
+            case CODE_USER_SETUP_COMPLETED:
+                throw new IllegalStateException(
+                        "Cannot set the device owner if the device is already set-up");
+            case CODE_NONSYSTEM_USER_EXISTS:
+                throw new IllegalStateException("Not allowed to set the device owner because there "
+                        + "are already several users on the device");
+            case CODE_ACCOUNTS_NOT_EMPTY:
+                throw new IllegalStateException("Not allowed to set the device owner because there "
+                        + "are already some accounts on the device");
+            default:
+                throw new IllegalStateException("Unknown @DeviceOwnerPreConditionCode " + code);
         }
     }
 
@@ -7810,6 +7814,26 @@
                 listener.onCrossProfileWidgetProvidersChanged(userId, packages);
             }
         }
+
+        @Override
+        public boolean hasDeviceOwnerOrProfileOwner(String packageName, int userId) {
+            if (!mHasFeature || packageName == null) {
+                return false;
+            }
+            if (userId < 0) {
+                throw new UnsupportedOperationException("userId should be >= 0");
+            }
+            synchronized (DevicePolicyManagerService.this) {
+                if (packageName.equals(mOwners.getProfileOwnerPackage(userId))) {
+                    return true;
+                }
+                if (userId == mOwners.getDeviceOwnerUserId()
+                        && packageName.equals(mOwners.getDeviceOwnerPackageName())) {
+                    return true;
+                }
+            }
+            return false;
+        }
     }
 
     /**
@@ -8036,6 +8060,10 @@
 
     @Override
     public boolean isProvisioningAllowed(String action) {
+        if (!mHasFeature) {
+            return false;
+        }
+
         final int callingUserId = mInjector.userHandleGetCallingUserId();
         if (DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE.equals(action)) {
             if (!hasFeatureManagedUsers()) {
@@ -8100,23 +8128,55 @@
         throw new IllegalArgumentException("Unknown provisioning action " + action);
     }
 
-    private boolean isDeviceOwnerProvisioningAllowed(int callingUserId) {
-        synchronized (this) {
-            if (mOwners.hasDeviceOwner()) {
-                return false;
+    /*
+     * The device owner can only be set before the setup phase of the primary user has completed,
+     * except for adb command if no accounts or additional users are present on the device.
+     */
+    private synchronized @DeviceOwnerPreConditionCode int checkSetDeviceOwnerPreCondition(
+            int deviceOwnerUserId, boolean isAdb) {
+        if (mOwners.hasDeviceOwner()) {
+            return CODE_HAS_DEVICE_OWNER;
+        }
+        if (mOwners.hasProfileOwner(deviceOwnerUserId)) {
+            return CODE_USER_HAS_PROFILE_OWNER;
+        }
+        if (!mUserManager.isUserRunning(new UserHandle(deviceOwnerUserId))) {
+            return CODE_USER_NOT_RUNNING;
+        }
+        if (isAdb) {
+            // if shell command runs after user setup completed check device status. Otherwise, OK.
+            if (hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
+                if (!mInjector.userManagerIsSplitSystemUser()) {
+                    if (mUserManager.getUserCount() > 1) {
+                        return CODE_NONSYSTEM_USER_EXISTS;
+                    }
+                    if (AccountManager.get(mContext).getAccounts().length > 0) {
+                        return CODE_ACCOUNTS_NOT_EMPTY;
+                    }
+                } else {
+                    // STOPSHIP Do proper check in split user mode
+                }
             }
+            return CODE_OK;
+        } else {
+            if (!mInjector.userManagerIsSplitSystemUser()) {
+                // In non-split user mode, DO has to be user 0
+                if (deviceOwnerUserId != UserHandle.USER_SYSTEM) {
+                    return CODE_NOT_SYSTEM_USER;
+                }
+                // In non-split user mode, only provision DO before setup wizard completes
+                if (hasUserSetupCompleted(UserHandle.USER_SYSTEM)) {
+                    return CODE_USER_SETUP_COMPLETED;
+                }
+            } else {
+                // STOPSHIP Do proper check in split user mode
+            }
+            return CODE_OK;
         }
-        if (getProfileOwner(callingUserId) != null) {
-            return false;
-        }
-        if (mInjector.settingsGlobalGetInt(Settings.Global.DEVICE_PROVISIONED, 0) != 0) {
-            return false;
-        }
-        if (callingUserId != UserHandle.USER_SYSTEM) {
-            // Device owner provisioning can only be initiated from system user.
-            return false;
-        }
-        return true;
+    }
+
+    private boolean isDeviceOwnerProvisioningAllowed(int deviceOwnerUserId) {
+        return CODE_OK == checkSetDeviceOwnerPreCondition(deviceOwnerUserId, /* isAdb */ false);
     }
 
     private boolean hasFeatureManagedUsers() {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java
index 117ba15..6d42dc9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportUtils.java
@@ -19,8 +19,12 @@
 import android.annotation.IntDef;
 import android.app.Notification;
 import android.app.PendingIntent;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.os.UserHandle;
+import android.provider.Settings;
 import android.text.format.DateUtils;
 
 import com.android.internal.R;
@@ -37,79 +41,62 @@
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({
-        NOTIFICATION_BUGREPORT_STARTED,
-        NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED,
-        NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED
+        DevicePolicyManager.NOTIFICATION_BUGREPORT_STARTED,
+        DevicePolicyManager.NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED,
+        DevicePolicyManager.NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED
     })
     @interface RemoteBugreportNotificationType {}
-    static final int NOTIFICATION_BUGREPORT_STARTED = 1;
-    static final int NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED = 2;
-    static final int NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED = 3;
 
     static final long REMOTE_BUGREPORT_TIMEOUT_MILLIS = 10 * DateUtils.MINUTE_IN_MILLIS;
 
     static final String CTL_STOP = "ctl.stop";
     static final String REMOTE_BUGREPORT_SERVICE = "bugreportremote";
 
-    static final String ACTION_REMOTE_BUGREPORT_DISPATCH =
-            "android.intent.action.REMOTE_BUGREPORT_DISPATCH";
-    static final String ACTION_REMOTE_BUGREPORT_SHARING_ACCEPTED =
-            "com.android.server.action.REMOTE_BUGREPORT_SHARING_ACCEPTED";
-    static final String ACTION_REMOTE_BUGREPORT_SHARING_DECLINED =
-            "com.android.server.action.REMOTE_BUGREPORT_SHARING_DECLINED";
-    static final String EXTRA_REMOTE_BUGREPORT_HASH = "android.intent.extra.REMOTE_BUGREPORT_HASH";
-
     static final String BUGREPORT_MIMETYPE = "application/vnd.android.bugreport";
 
     static Notification buildNotification(Context context,
             @RemoteBugreportNotificationType int type) {
+        Intent dialogIntent = new Intent(Settings.ACTION_SHOW_REMOTE_BUGREPORT_DIALOG);
+        dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        dialogIntent.putExtra(DevicePolicyManager.EXTRA_BUGREPORT_NOTIFICATION_TYPE, type);
+        PendingIntent pendingDialogIntent = PendingIntent.getActivityAsUser(context, type,
+                dialogIntent, 0, null, UserHandle.CURRENT);
+
         Notification.Builder builder = new Notification.Builder(context)
                 .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
                 .setOngoing(true)
                 .setLocalOnly(true)
+                .setPriority(Notification.PRIORITY_HIGH)
+                .setContentIntent(pendingDialogIntent)
                 .setColor(context.getColor(
                         com.android.internal.R.color.system_notification_accent_color));
 
-        if (type == NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED) {
+        if (type == DevicePolicyManager.NOTIFICATION_BUGREPORT_ACCEPTED_NOT_FINISHED) {
             builder.setContentTitle(context.getString(
-                            R.string.sharing_remote_bugreport_notification_title))
-                    .setContentText(context.getString(
-                            R.string.sharing_remote_bugreport_notification_message))
-                    .setPriority(Notification.PRIORITY_HIGH)
-                    .setProgress(0, 0, true)
-                    .setStyle(new Notification.BigTextStyle().bigText(context.getString(
-                            R.string.sharing_remote_bugreport_notification_message)));
-        } else {
+                        R.string.sharing_remote_bugreport_notification_title))
+                    .setProgress(0, 0, true);
+        } else if (type == DevicePolicyManager.NOTIFICATION_BUGREPORT_STARTED) {
+            builder.setContentTitle(context.getString(
+                        R.string.taking_remote_bugreport_notification_title))
+                    .setProgress(0, 0, true);
+        } else if (type == DevicePolicyManager.NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED) {
             PendingIntent pendingIntentAccept = PendingIntent.getBroadcast(context, NOTIFICATION_ID,
-                    new Intent(ACTION_REMOTE_BUGREPORT_SHARING_ACCEPTED),
+                    new Intent(DevicePolicyManager.ACTION_BUGREPORT_SHARING_ACCEPTED),
                     PendingIntent.FLAG_CANCEL_CURRENT);
             PendingIntent pendingIntentDecline = PendingIntent.getBroadcast(context,
-                    NOTIFICATION_ID, new Intent(ACTION_REMOTE_BUGREPORT_SHARING_DECLINED),
+                    NOTIFICATION_ID, new Intent(
+                            DevicePolicyManager.ACTION_BUGREPORT_SHARING_DECLINED),
                     PendingIntent.FLAG_CANCEL_CURRENT);
             builder.addAction(new Notification.Action.Builder(null /* icon */, context.getString(
-                            R.string.share_remote_bugreport_notification_decline),
-                            pendingIntentDecline).build())
+                        R.string.decline_remote_bugreport_action), pendingIntentDecline).build())
                     .addAction(new Notification.Action.Builder(null /* icon */, context.getString(
-                            R.string.share_remote_bugreport_notification_accept),
-                            pendingIntentAccept).build())
+                        R.string.share_remote_bugreport_action), pendingIntentAccept).build())
                     .setContentTitle(context.getString(
-                            R.string.share_remote_bugreport_notification_title));
-
-            if (type == NOTIFICATION_BUGREPORT_STARTED) {
-                builder.setContentText(context.getString(
-                                R.string.share_remote_bugreport_notification_message))
-                        .setStyle(new Notification.BigTextStyle().bigText(context.getString(
-                                R.string.share_remote_bugreport_notification_message)))
-                        .setProgress(0, 0, true)
-                        .setPriority(Notification.PRIORITY_MAX)
-                        .setVibrate(new long[0]);
-            } else if (type == NOTIFICATION_BUGREPORT_FINISHED_NOT_ACCEPTED) {
-                builder.setContentText(context.getString(
-                                R.string.share_finished_remote_bugreport_notification_message))
-                        .setStyle(new Notification.BigTextStyle().bigText(context.getString(
-                                R.string.share_finished_remote_bugreport_notification_message)))
-                        .setPriority(Notification.PRIORITY_HIGH);
-            }
+                        R.string.share_remote_bugreport_notification_title))
+                    .setContentText(context.getString(
+                        R.string.share_remote_bugreport_notification_message_finished))
+                    .setStyle(new Notification.BigTextStyle().bigText(context.getString(
+                        R.string.share_remote_bugreport_notification_message_finished)));
         }
 
         return builder.build();
diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java
index 4f99bff..e2562cd 100644
--- a/services/net/java/android/net/dhcp/DhcpClient.java
+++ b/services/net/java/android/net/dhcp/DhcpClient.java
@@ -84,10 +84,10 @@
 public class DhcpClient extends StateMachine {
 
     private static final String TAG = "DhcpClient";
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
     private static final boolean STATE_DBG = false;
     private static final boolean MSG_DBG = false;
-    private static final boolean PACKET_DBG = true;
+    private static final boolean PACKET_DBG = false;
 
     // Timers and timeouts.
     private static final int SECONDS = 1000;
@@ -342,14 +342,14 @@
 
         @Override
         public void run() {
-            maybeLog("Receive thread started");
+            if (DBG) Log.d(TAG, "Receive thread started");
             while (!stopped) {
                 int length = 0;  // Or compiler can't tell it's initialized if a parse error occurs.
                 try {
                     length = Os.read(mPacketSock, mPacket, 0, mPacket.length);
                     DhcpPacket packet = null;
                     packet = DhcpPacket.decodeFullPacket(mPacket, length, DhcpPacket.ENCAP_L2);
-                    maybeLog("Received packet: " + packet);
+                    if (DBG) Log.d(TAG, "Received packet: " + packet);
                     sendMessage(CMD_RECEIVED_PACKET, packet);
                 } catch (IOException|ErrnoException e) {
                     if (!stopped) {
@@ -362,7 +362,7 @@
                     }
                 }
             }
-            maybeLog("Receive thread stopped");
+            if (DBG) Log.d(TAG, "Receive thread stopped");
         }
     }
 
@@ -373,12 +373,12 @@
     private boolean transmitPacket(ByteBuffer buf, String description, Inet4Address to) {
         try {
             if (to.equals(INADDR_BROADCAST)) {
-                maybeLog("Broadcasting " + description);
+                if (DBG) Log.d(TAG, "Broadcasting " + description);
                 Os.sendto(mPacketSock, buf.array(), 0, buf.limit(), 0, mInterfaceBroadcastAddr);
             } else {
                 // It's safe to call getpeername here, because we only send unicast packets if we
                 // have an IP address, and we connect the UDP socket in DhcpHaveAddressState#enter.
-                maybeLog("Unicasting " + description + " to " + Os.getpeername(mUdpSock));
+                if (DBG) Log.d(TAG, "Unicasting " + description + " to " + Os.getpeername(mUdpSock));
                 Os.write(mUdpSock, buf);
             }
         } catch(ErrnoException|IOException e) {
@@ -454,10 +454,6 @@
         mController.sendMessage(CMD_ON_QUIT);
     }
 
-    private void maybeLog(String msg) {
-        if (DBG) Log.d(TAG, msg);
-    }
-
     abstract class LoggingState extends State {
         public void enter() {
             if (STATE_DBG) Log.d(TAG, "Entering state " + getName());
@@ -592,7 +588,7 @@
                     transitionTo(mStoppedState);
                     return HANDLED;
                 case CMD_ONESHOT_TIMEOUT:
-                    maybeLog("Timed out");
+                    if (DBG) Log.d(TAG, "Timed out");
                     notifyFailure();
                     return HANDLED;
                 default:
@@ -790,7 +786,7 @@
 
         @Override
         public void exit() {
-            maybeLog("Clearing IP address");
+            if (DBG) Log.d(TAG, "Clearing IP address");
             setIpAddress(new LinkAddress("0.0.0.0/0"));
         }
     }
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index afae956..c7c5015 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -63,7 +63,7 @@
  * @hide
  */
 public class IpManager extends StateMachine {
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
     private static final boolean VDBG = false;
 
     // For message logging.
diff --git a/services/net/java/android/net/ip/IpReachabilityMonitor.java b/services/net/java/android/net/ip/IpReachabilityMonitor.java
index 88155f7..5b4fd50 100644
--- a/services/net/java/android/net/ip/IpReachabilityMonitor.java
+++ b/services/net/java/android/net/ip/IpReachabilityMonitor.java
@@ -132,7 +132,7 @@
  */
 public class IpReachabilityMonitor {
     private static final String TAG = "IpReachabilityMonitor";
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
     private static final boolean VDBG = false;
 
     public interface Callback {
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 212b37c..8c47087 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -969,6 +969,8 @@
 
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
 
+        when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true);
+
         // Make sure the admin packge is installed to each user.
         setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
         setUpPackageManagerForAdmin(admin3, DpmMockContext.CALLER_SYSTEM_USER_UID);
@@ -1008,6 +1010,7 @@
      * finds the right component from a package name upon migration.
      */
     public void testDeviceOwnerMigration() throws Exception {
+        when(mContext.userManagerForMock.isSplitSystemUser()).thenReturn(true);
         checkDeviceOwnerWithMultipleDeviceAdmins();
 
         // Overwrite the device owner setting and clears the clas name.
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 6ab0b99..837b4a4 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -75,7 +75,7 @@
  */
 public class VoiceInteractionManagerService extends SystemService {
     static final String TAG = "VoiceInteractionManagerService";
-    static final boolean DEBUG = true;
+    static final boolean DEBUG = false;
 
     final Context mContext;
     final ContentResolver mResolver;
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 1278c07..cd1c5e9 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -637,7 +637,7 @@
         sDefaults.putBoolean(KEY_SHOW_CDMA_CHOICES_BOOL, false);
         sDefaults.putBoolean(KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL, true);
         sDefaults.putBoolean(KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL, true);
-        sDefaults.putBoolean(KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL, true);
+        sDefaults.putBoolean(KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL, false);
         sDefaults.putBoolean(KEY_SUPPORT_SWAP_AFTER_MERGE_BOOL, true);
         sDefaults.putBoolean(KEY_USE_HFA_FOR_PROVISIONING_BOOL, false);
         sDefaults.putBoolean(KEY_USE_OTASP_FOR_PROVISIONING_BOOL, false);
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index ad007c6..39a9295 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -36,7 +36,7 @@
 public class ServiceState implements Parcelable {
 
     static final String LOG_TAG = "PHONE";
-    static final boolean DBG = true;
+    static final boolean DBG = false;
     static final boolean VDBG = false;  // STOPSHIP if true
 
     /**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index e90be91..b482811 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -4403,7 +4403,6 @@
             Log.e(TAG, "Error calling ITelephony#getDataEnabled", e);
         } catch (NullPointerException e) {
         }
-        Log.d(TAG, "getDataEnabled: retVal=" + retVal);
         return retVal;
     }
 
diff --git a/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java b/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java
index c8a8d6c..6463e1f 100644
--- a/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java
+++ b/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java
@@ -47,7 +47,7 @@
         OnBufferingUpdateListener, OnCompletionListener, OnErrorListener,
         OnAudioFocusChangeListener {
     private static final String TAG = "MediaPlayerManager";
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = false;
     private static long sDebugInstanceId = 0;
 
     private static final String[] SUPPORTED_FEATURES = {
diff --git a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java
index 4770c05..3ca96d2 100644
--- a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java
+++ b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/TestSoundTriggerActivity.java
@@ -40,7 +40,7 @@
 
 public class TestSoundTriggerActivity extends Activity {
     private static final String TAG = "TestSoundTriggerActivity";
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
 
     private SoundTriggerUtil mSoundTriggerUtil;
     private Random mRandom;
diff --git a/tests/SoundTriggerTests/Android.mk b/tests/SoundTriggerTests/Android.mk
index 407a9d7..ac562b9 100644
--- a/tests/SoundTriggerTests/Android.mk
+++ b/tests/SoundTriggerTests/Android.mk
@@ -18,7 +18,14 @@
 
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
+ifeq ($(SOUND_TRIGGER_USE_STUB_MODULE), 1)
+  LOCAL_SRC_FILES := $(call all-subdir-java-files)
+  LOCAL_PRIVILEGED_MODULE := true
+  LOCAL_CERTIFICATE := platform
+  TARGET_OUT_DATA_APPS_PRIVILEGED := $(TARGET_OUT_DATA)/priv-app
+else
+  LOCAL_SRC_FILES := src/android/hardware/soundtrigger/SoundTriggerTest.java
+endif
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
diff --git a/tests/SoundTriggerTests/AndroidManifest.xml b/tests/SoundTriggerTests/AndroidManifest.xml
index 5e5a108..e8b9dd3 100644
--- a/tests/SoundTriggerTests/AndroidManifest.xml
+++ b/tests/SoundTriggerTests/AndroidManifest.xml
@@ -14,7 +14,10 @@
      limitations under the License.
 -->
 
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android.hardware.soundtrigger">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.hardware.soundtrigger">
+    <uses-permission android:name="android.permission.MANAGE_SOUND_TRIGGER" />
+
     <application>
         <uses-library android:name="android.test.runner" />
     </application>
diff --git a/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java
new file mode 100644
index 0000000..7acb472
--- /dev/null
+++ b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.soundtrigger;
+
+import java.util.Random;
+import java.util.UUID;
+
+import android.content.Context;
+import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
+import android.media.soundtrigger.SoundTriggerManager;
+import android.os.ParcelUuid;
+import android.os.ServiceManager;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.internal.app.ISoundTriggerService;
+
+import java.util.Arrays;
+import java.util.Random;
+import java.util.UUID;
+
+public class GenericSoundModelTest extends AndroidTestCase {
+    private Random mRandom = new Random();
+
+    @SmallTest
+    public void testUpdateGenericSoundModel() throws Exception {
+        Context context = getContext();
+        ISoundTriggerService mSoundTriggerService = ISoundTriggerService.Stub.asInterface(
+            ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE));
+        SoundTriggerManager mSoundTriggerManager = (SoundTriggerManager) context.getSystemService(
+            Context.SOUND_TRIGGER_SERVICE);
+
+        byte[] data = new byte[1024];
+        mRandom.nextBytes(data);
+        UUID modelUuid = UUID.randomUUID();
+        UUID mVendorUuid = UUID.randomUUID();
+        GenericSoundModel model = new GenericSoundModel(modelUuid, mVendorUuid, data);
+
+        mSoundTriggerService.updateSoundModel(model);
+        GenericSoundModel returnedModel =
+            mSoundTriggerService.getSoundModel(new ParcelUuid(modelUuid));
+
+        assertEquals(model, returnedModel);
+
+        // Cleanup sound model
+        mSoundTriggerService.deleteSoundModel(new ParcelUuid(modelUuid));
+    }
+
+
+    @SmallTest
+    public void testDeleteGenericSoundModel() throws Exception {
+        Context context = getContext();
+        ISoundTriggerService mSoundTriggerService = ISoundTriggerService.Stub.asInterface(
+            ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE));
+        SoundTriggerManager mSoundTriggerManager = (SoundTriggerManager) context.getSystemService(
+            Context.SOUND_TRIGGER_SERVICE);
+
+        byte[] data = new byte[1024];
+        mRandom.nextBytes(data);
+        UUID modelUuid = UUID.randomUUID();
+        UUID mVendorUuid = UUID.randomUUID();
+        GenericSoundModel model = new GenericSoundModel(modelUuid, mVendorUuid, data);
+
+        mSoundTriggerService.updateSoundModel(model);
+        mSoundTriggerService.deleteSoundModel(new ParcelUuid(modelUuid));
+
+        GenericSoundModel returnedModel =
+            mSoundTriggerService.getSoundModel(new ParcelUuid(modelUuid));
+        assertEquals(null, returnedModel);
+    }
+}
diff --git a/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java b/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java
index 2494db7..54c944f9 100644
--- a/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java
+++ b/tests/VoiceEnrollment/src/com/android/test/voiceenrollment/TestEnrollmentActivity.java
@@ -31,7 +31,7 @@
 
 public class TestEnrollmentActivity extends Activity {
     private static final String TAG = "TestEnrollmentActivity";
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
 
     /** Keyphrase related constants, must match those defined in enrollment_application.xml */
     private static final int KEYPHRASE_ID = 101;
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index d2103c8..97195e4 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -349,7 +349,7 @@
     }
 
     @Override
-    public void notifyAppStopped(IBinder token) throws RemoteException {
+    public void notifyAppStopped(IBinder token, boolean stopped) throws RemoteException {
         // TODO Auto-generated method stub
     }
 
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 69e179d..97dd985 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -192,6 +192,11 @@
          * for a given period
          */
         public int stepCount;
+        /**
+         * Flag to indicate if the scan settings are targeted for PNO scan.
+         * {@hide}
+         */
+        public boolean isPnoScan;
 
         /** Implement the Parcelable interface {@hide} */
         public int describeContents() {
@@ -207,6 +212,7 @@
             dest.writeInt(maxScansToCache);
             dest.writeInt(maxPeriodInMs);
             dest.writeInt(stepCount);
+            dest.writeInt(isPnoScan ? 1 : 0);
 
             if (channels != null) {
                 dest.writeInt(channels.length);
@@ -234,6 +240,7 @@
                         settings.maxScansToCache = in.readInt();
                         settings.maxPeriodInMs = in.readInt();
                         settings.stepCount = in.readInt();
+                        settings.isPnoScan = in.readInt() == 1;
                         int num_channels = in.readInt();
                         settings.channels = new ChannelSpec[num_channels];
                         for (int i = 0; i < num_channels; i++) {
@@ -436,6 +443,158 @@
                 };
     }
 
+    /** {@hide} */
+    public static final String PNO_PARAMS_PNO_SETTINGS_KEY = "PnoSettings";
+    /** {@hide} */
+    public static final String PNO_PARAMS_SCAN_SETTINGS_KEY = "ScanSettings";
+    /**
+     * PNO scan configuration parameters to be sent to {@link #startPnoScan}.
+     * Note: This structure needs to be in sync with |wifi_epno_params| struct in gscan HAL API.
+     * {@hide}
+     */
+    public static class PnoSettings implements Parcelable {
+        /**
+         * Pno network to be added to the PNO scan filtering.
+         * {@hide}
+         */
+        public static class PnoNetwork {
+            /*
+             * Pno flags bitmask to be set in {@link #PnoNetwork.flags}
+             */
+            /** Whether directed scan needs to be performed (for hidden SSIDs) */
+            public static final byte FLAG_DIRECTED_SCAN = (1 << 0);
+            /** Whether PNO event shall be triggered if the network is found on A band */
+            public static final byte FLAG_A_BAND = (1 << 1);
+            /** Whether PNO event shall be triggered if the network is found on G band */
+            public static final byte FLAG_G_BAND = (1 << 2);
+            /**
+             * Whether strict matching is required
+             * If required then the firmware must store the network's SSID and not just a hash
+             */
+            public static final byte FLAG_STRICT_MATCH = (1 << 3);
+            /**
+             * If this SSID should be considered the same network as the currently connected
+             * one for scoring.
+             */
+            public static final byte FLAG_SAME_NETWORK = (1 << 4);
+
+            /*
+             * Code for matching the beacon AUTH IE - additional codes. Bitmask to be set in
+             * {@link #PnoNetwork.authBitField}
+             */
+            /** Open Network */
+            public static final byte AUTH_CODE_OPEN = (1 << 0);
+            /** WPA_PSK or WPA2PSK */
+            public static final byte AUTH_CODE_PSK = (1 << 1);
+            /** any EAPOL */
+            public static final byte AUTH_CODE_EAPOL = (1 << 2);
+
+            /** SSID of the network */
+            public String ssid;
+            /** Network ID in wpa_supplicant */
+            public int networkId;
+            /** Assigned priority for the network */
+            public int priority;
+            /** Bitmask of the FLAG_XXX */
+            public byte flags;
+            /** Bitmask of the ATUH_XXX */
+            public byte authBitField;
+
+            /**
+             * default constructor for PnoNetwork
+             */
+            public PnoNetwork(String ssid) {
+                this.ssid = ssid;
+                flags = 0;
+                authBitField = 0;
+            }
+        }
+
+        /** Connected vs Disconnected PNO flag {@hide} */
+        public boolean isConnected;
+        /** Minimum 5GHz RSSI for a BSSID to be considered */
+        public int min5GHzRssi;
+        /** Minimum 2.4GHz RSSI for a BSSID to be considered */
+        public int min24GHzRssi;
+        /** Maximum score that a network can have before bonuses */
+        public int initialScoreMax;
+        /**
+         *  Only report when there is a network's score this much higher
+         *  than the current connection.
+         */
+        public int currentConnectionBonus;
+        /** score bonus for all networks with the same network flag */
+        public int sameNetworkBonus;
+        /** score bonus for networks that are not open */
+        public int secureBonus;
+        /** 5GHz RSSI score bonus (applied to all 5GHz networks) */
+        public int band5GHzBonus;
+        /** Pno Network filter list */
+        public PnoNetwork[] networkList;
+
+        /** Implement the Parcelable interface {@hide} */
+        public int describeContents() {
+            return 0;
+        }
+
+        /** Implement the Parcelable interface {@hide} */
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeInt(isConnected ? 1 : 0);
+            dest.writeInt(min5GHzRssi);
+            dest.writeInt(min24GHzRssi);
+            dest.writeInt(initialScoreMax);
+            dest.writeInt(currentConnectionBonus);
+            dest.writeInt(sameNetworkBonus);
+            dest.writeInt(secureBonus);
+            dest.writeInt(band5GHzBonus);
+            if (networkList != null) {
+                dest.writeInt(networkList.length);
+                for (int i = 0; i < networkList.length; i++) {
+                    dest.writeString(networkList[i].ssid);
+                    dest.writeInt(networkList[i].networkId);
+                    dest.writeInt(networkList[i].priority);
+                    dest.writeByte(networkList[i].flags);
+                    dest.writeByte(networkList[i].authBitField);
+                }
+            } else {
+                dest.writeInt(0);
+            }
+        }
+
+        /** Implement the Parcelable interface {@hide} */
+        public static final Creator<PnoSettings> CREATOR =
+                new Creator<PnoSettings>() {
+                    public PnoSettings createFromParcel(Parcel in) {
+                        PnoSettings settings = new PnoSettings();
+                        settings.isConnected = in.readInt() == 1;
+                        settings.min5GHzRssi = in.readInt();
+                        settings.min24GHzRssi = in.readInt();
+                        settings.initialScoreMax = in.readInt();
+                        settings.currentConnectionBonus = in.readInt();
+                        settings.sameNetworkBonus = in.readInt();
+                        settings.secureBonus = in.readInt();
+                        settings.band5GHzBonus = in.readInt();
+                        int numNetworks = in.readInt();
+                        settings.networkList = new PnoNetwork[numNetworks];
+                        for (int i = 0; i < numNetworks; i++) {
+                            String ssid = in.readString();
+                            PnoNetwork network = new PnoNetwork(ssid);
+                            network.networkId = in.readInt();
+                            network.priority = in.readInt();
+                            network.flags = in.readByte();
+                            network.authBitField = in.readByte();
+                            settings.networkList[i] = network;
+                        }
+                        return settings;
+                    }
+
+                    public PnoSettings[] newArray(int size) {
+                        return new PnoSettings[size];
+                    }
+                };
+
+    }
+
     /**
      * interface to get scan events on; specify this on {@link #startBackgroundScan} or
      * {@link #startScan}
@@ -456,6 +615,18 @@
         public void onFullResult(ScanResult fullScanResult);
     }
 
+    /**
+     * interface to get PNO scan events on; specify this on {@link #startDisconnectedPnoScan} and
+     * {@link #startConnectedPnoScan}.
+     * {@hide}
+     */
+    public interface PnoScanListener extends ScanListener {
+        /**
+         * Invoked when one of the PNO networks are found in scan results.
+         */
+        void onPnoNetworkFound(ScanResult[] results);
+    }
+
     /** start wifi scan in background
      * @param settings specifies various parameters for the scan; for more information look at
      * {@link ScanSettings}
@@ -521,6 +692,75 @@
         sAsyncChannel.sendMessage(CMD_STOP_SINGLE_SCAN, 0, key);
     }
 
+    private void startPnoScan(ScanSettings scanSettings, PnoSettings pnoSettings, int key) {
+        // Bundle up both the settings and send it across.
+        Bundle pnoParams = new Bundle();
+        if (pnoParams == null) return;
+        // Set the PNO scan flag.
+        scanSettings.isPnoScan = true;
+        pnoParams.putParcelable(PNO_PARAMS_SCAN_SETTINGS_KEY, scanSettings);
+        pnoParams.putParcelable(PNO_PARAMS_PNO_SETTINGS_KEY, pnoSettings);
+        sAsyncChannel.sendMessage(CMD_START_PNO_SCAN, 0, key, pnoParams);
+    }
+    /**
+     * Start wifi connected PNO scan
+     * @param scanSettings specifies various parameters for the scan; for more information look at
+     * {@link ScanSettings}
+     * @param pnoSettings specifies various parameters for PNO; for more information look at
+     * {@link PnoSettings}
+     * @param listener specifies the object to report events to. This object is also treated as a
+     *                 key for this scan, and must also be specified to cancel the scan. Multiple
+     *                 scans should also not share this object.
+     * {@hide}
+     */
+    public void startConnectedPnoScan(ScanSettings scanSettings, PnoSettings pnoSettings,
+            PnoScanListener listener) {
+        Preconditions.checkNotNull(listener, "listener cannot be null");
+        Preconditions.checkNotNull(pnoSettings, "pnoSettings cannot be null");
+        int key = addListener(listener);
+        if (key == INVALID_KEY) return;
+        validateChannel();
+        pnoSettings.isConnected = true;
+        startPnoScan(scanSettings, pnoSettings, key);
+    }
+    /**
+     * Start wifi disconnected PNO scan
+     * @param scanSettings specifies various parameters for the scan; for more information look at
+     * {@link ScanSettings}
+     * @param pnoSettings specifies various parameters for PNO; for more information look at
+     * {@link PnoSettings}
+     * @param listener specifies the object to report events to. This object is also treated as a
+     *                 key for this scan, and must also be specified to cancel the scan. Multiple
+     *                 scans should also not share this object.
+     * {@hide}
+     */
+    public void startDisconnectedPnoScan(ScanSettings scanSettings, PnoSettings pnoSettings,
+            PnoScanListener listener) {
+        Preconditions.checkNotNull(listener, "listener cannot be null");
+        Preconditions.checkNotNull(pnoSettings, "pnoSettings cannot be null");
+        int key = addListener(listener);
+        if (key == INVALID_KEY) return;
+        validateChannel();
+        pnoSettings.isConnected = false;
+        startPnoScan(scanSettings, pnoSettings, key);
+    }
+    /**
+     * Stop an ongoing wifi PNO scan
+     * @param pnoSettings specifies various parameters for PNO; for more information look at
+     * {@link PnoSettings}
+     * @param listener specifies which scan to cancel; must be same object as passed in {@link
+     *  #startPnoScan}
+     * TODO(rpius): Check if we can remove pnoSettings param in stop.
+     * {@hide}
+     */
+    public void stopPnoScan(PnoSettings pnoSettings, ScanListener listener) {
+        Preconditions.checkNotNull(listener, "listener cannot be null");
+        int key = removeListener(listener);
+        if (key == INVALID_KEY) return;
+        validateChannel();
+        sAsyncChannel.sendMessage(CMD_STOP_PNO_SCAN, 0, key, pnoSettings);
+    }
+
     /** specifies information about an access point of interest */
     public static class BssidInfo {
         /** bssid of the access point; in XX:XX:XX:XX:XX:XX format */
@@ -824,6 +1064,12 @@
     public static final int CMD_STOP_SINGLE_SCAN            = BASE + 22;
     /** @hide */
     public static final int CMD_SINGLE_SCAN_COMPLETED       = BASE + 23;
+    /** @hide */
+    public static final int CMD_START_PNO_SCAN              = BASE + 24;
+    /** @hide */
+    public static final int CMD_STOP_PNO_SCAN               = BASE + 25;
+    /** @hide */
+    public static final int CMD_PNO_NETWORK_FOUND           = BASE + 26;
 
     private Context mContext;
     private IWifiScanner mService;
@@ -1110,6 +1356,10 @@
                     if (DBG) Log.d(TAG, "removing listener for single scan");
                     removeListener(msg.arg2);
                     break;
+                case CMD_PNO_NETWORK_FOUND:
+                    ((PnoScanListener) listener).onPnoNetworkFound(
+                            ((ParcelableScanResults) msg.obj).getResults());
+                    return;
                 default:
                     if (DBG) Log.d(TAG, "Ignoring message " + msg.what);
                     return;