Merge "Fix runtime restart" into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index 85475fb..dab4f64 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -968,6 +968,7 @@
     field public static final int pathData = 16843807; // 0x101041f
     field public static final int pathPattern = 16842796; // 0x101002c
     field public static final int pathPrefix = 16842795; // 0x101002b
+    field public static final int patternPathData = 16843979; // 0x10104cb
     field public static final int permission = 16842758; // 0x1010006
     field public static final int permissionFlags = 16843719; // 0x10103c7
     field public static final int permissionGroup = 16842762; // 0x101000a
@@ -8680,15 +8681,17 @@
 
   public class PackageInstaller {
     method public void abandonSession(int);
-    method public void addSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
-    method public void addSessionCallback(android.content.pm.PackageInstaller.SessionCallback, android.os.Handler);
     method public int createSession(android.content.pm.PackageInstaller.SessionParams) throws java.io.IOException;
     method public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getAllSessions();
     method public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getMySessions();
     method public android.content.pm.PackageInstaller.SessionInfo getSessionInfo(int);
     method public android.content.pm.PackageInstaller.Session openSession(int);
-    method public void removeSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
+    method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
+    method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback, android.os.Handler);
     method public void uninstall(java.lang.String, android.content.IntentSender);
+    method public void unregisterSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
+    method public void updateSessionAppIcon(int, android.graphics.Bitmap);
+    method public void updateSessionAppLabel(int, java.lang.CharSequence);
     field public static final java.lang.String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS";
     field public static final java.lang.String EXTRA_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME";
     field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
@@ -8720,6 +8723,7 @@
 
   public static abstract class PackageInstaller.SessionCallback {
     ctor public PackageInstaller.SessionCallback();
+    method public abstract void onBadgingChanged(int);
     method public abstract void onClosed(int);
     method public abstract void onCreated(int);
     method public abstract void onFinished(int, boolean);
@@ -11438,8 +11442,6 @@
     ctor public PorterDuffColorFilter(int, android.graphics.PorterDuff.Mode);
     method public int getColor();
     method public android.graphics.PorterDuff.Mode getMode();
-    method public void setColor(int);
-    method public void setMode(android.graphics.PorterDuff.Mode);
   }
 
   public class PorterDuffXfermode extends android.graphics.Xfermode {
@@ -31507,13 +31509,13 @@
     method public abstract android.graphics.Path getPath(float, float, float, float);
   }
 
-  public class PatternMotion extends android.transition.PathMotion {
-    ctor public PatternMotion();
-    ctor public PatternMotion(android.content.Context, android.util.AttributeSet);
-    ctor public PatternMotion(android.graphics.Path);
+  public class PatternPathMotion extends android.transition.PathMotion {
+    ctor public PatternPathMotion();
+    ctor public PatternPathMotion(android.content.Context, android.util.AttributeSet);
+    ctor public PatternPathMotion(android.graphics.Path);
     method public android.graphics.Path getPath(float, float, float, float);
-    method public android.graphics.Path getPattern();
-    method public void setPattern(android.graphics.Path);
+    method public android.graphics.Path getPatternPath();
+    method public void setPatternPath(android.graphics.Path);
   }
 
   public final class Scene {
diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl
index c6c0ff6..6daefc8 100644
--- a/core/java/android/content/pm/IPackageInstaller.aidl
+++ b/core/java/android/content/pm/IPackageInstaller.aidl
@@ -22,14 +22,21 @@
 import android.content.pm.PackageInstaller;
 import android.content.IntentSender;
 
+import android.graphics.Bitmap;
+
 /** {@hide} */
 interface IPackageInstaller {
     int createSession(in PackageInstaller.SessionParams params, String installerPackageName, int userId);
+
+    void updateSessionAppIcon(int sessionId, in Bitmap appIcon);
+    void updateSessionAppLabel(int sessionId, String appLabel);
+
     void abandonSession(int sessionId);
 
     IPackageInstallerSession openSession(int sessionId);
 
     PackageInstaller.SessionInfo getSessionInfo(int sessionId);
+
     List<PackageInstaller.SessionInfo> getAllSessions(int userId);
     List<PackageInstaller.SessionInfo> getMySessions(String installerPackageName, int userId);
 
diff --git a/core/java/android/content/pm/IPackageInstallerCallback.aidl b/core/java/android/content/pm/IPackageInstallerCallback.aidl
index 39ae1a0..fe98ee7 100644
--- a/core/java/android/content/pm/IPackageInstallerCallback.aidl
+++ b/core/java/android/content/pm/IPackageInstallerCallback.aidl
@@ -19,6 +19,7 @@
 /** {@hide} */
 oneway interface IPackageInstallerCallback {
     void onSessionCreated(int sessionId);
+    void onSessionBadgingChanged(int sessionId);
     void onSessionOpened(int sessionId);
     void onSessionProgressChanged(int sessionId, float progress);
     void onSessionClosed(int sessionId);
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 44e24b1..7c34a65 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -312,6 +312,32 @@
         }
     }
 
+    /**
+     * Update the icon representing the app being installed in a specific
+     * session. This should be roughly
+     * {@link ActivityManager#getLauncherLargeIconSize()} in both dimensions.
+     */
+    public void updateSessionAppIcon(int sessionId, @Nullable Bitmap appIcon) {
+        try {
+            mInstaller.updateSessionAppIcon(sessionId, appIcon);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
+     * Update the label representing the app being installed in a specific
+     * session.
+     */
+    public void updateSessionAppLabel(int sessionId, @Nullable CharSequence appLabel) {
+        try {
+            final String val = (appLabel != null) ? appLabel.toString() : null;
+            mInstaller.updateSessionAppLabel(sessionId, val);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
     public void abandonSession(int sessionId) {
         try {
             mInstaller.abandonSession(sessionId);
@@ -321,8 +347,7 @@
     }
 
     /**
-     * Return details for a specific session. To succeed, the caller must either
-     * own this session, or be the current home app.
+     * Return details for a specific session.
      */
     public @Nullable SessionInfo getSessionInfo(int sessionId) {
         try {
@@ -334,7 +359,6 @@
 
     /**
      * Return list of all active install sessions, regardless of the installer.
-     * To succeed, the caller must be the current home app.
      */
     public @NonNull List<SessionInfo> getAllSessions() {
         final ApplicationInfo info = mContext.getApplicationInfo();
@@ -406,6 +430,12 @@
         public abstract void onCreated(int sessionId);
 
         /**
+         * Badging details for an existing session has changed. For example, the
+         * app icon or label has been updated.
+         */
+        public abstract void onBadgingChanged(int sessionId);
+
+        /**
          * Session has been opened. A session is usually opened when the
          * installer is actively writing data.
          */
@@ -436,10 +466,11 @@
     private static class SessionCallbackDelegate extends IPackageInstallerCallback.Stub implements
             Handler.Callback {
         private static final int MSG_SESSION_CREATED = 1;
-        private static final int MSG_SESSION_OPENED = 2;
-        private static final int MSG_SESSION_PROGRESS_CHANGED = 3;
-        private static final int MSG_SESSION_CLOSED = 4;
-        private static final int MSG_SESSION_FINISHED = 5;
+        private static final int MSG_SESSION_BADGING_CHANGED = 2;
+        private static final int MSG_SESSION_OPENED = 3;
+        private static final int MSG_SESSION_PROGRESS_CHANGED = 4;
+        private static final int MSG_SESSION_CLOSED = 5;
+        private static final int MSG_SESSION_FINISHED = 6;
 
         final SessionCallback mCallback;
         final Handler mHandler;
@@ -455,6 +486,9 @@
                 case MSG_SESSION_CREATED:
                     mCallback.onCreated(msg.arg1);
                     return true;
+                case MSG_SESSION_BADGING_CHANGED:
+                    mCallback.onBadgingChanged(msg.arg1);
+                    return true;
                 case MSG_SESSION_OPENED:
                     mCallback.onOpened(msg.arg1);
                     return true;
@@ -477,6 +511,11 @@
         }
 
         @Override
+        public void onSessionBadgingChanged(int sessionId) {
+            mHandler.obtainMessage(MSG_SESSION_BADGING_CHANGED, sessionId, 0).sendToTarget();
+        }
+
+        @Override
         public void onSessionOpened(int sessionId) {
             mHandler.obtainMessage(MSG_SESSION_OPENED, sessionId, 0).sendToTarget();
         }
@@ -499,22 +538,32 @@
         }
     }
 
-    /**
-     * Register to watch for session lifecycle events. To succeed, the caller
-     * must be the current home app.
-     */
+    /** {@hide} */
+    @Deprecated
     public void addSessionCallback(@NonNull SessionCallback callback) {
-        addSessionCallback(callback, new Handler());
+        registerSessionCallback(callback);
     }
 
     /**
-     * Register to watch for session lifecycle events. To succeed, the caller
-     * must be the current home app.
+     * Register to watch for session lifecycle events.
+     */
+    public void registerSessionCallback(@NonNull SessionCallback callback) {
+        registerSessionCallback(callback, new Handler());
+    }
+
+    /** {@hide} */
+    @Deprecated
+    public void addSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
+        registerSessionCallback(callback, handler);
+    }
+
+    /**
+     * Register to watch for session lifecycle events.
      *
      * @param handler to dispatch callback events through, otherwise uses
      *            calling thread.
      */
-    public void addSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
+    public void registerSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
         // TODO: remove this temporary guard once we have new prebuilts
         final ApplicationInfo info = mContext.getApplicationInfo();
         if ("com.google.android.googlequicksearchbox".equals(info.packageName)
@@ -535,10 +584,16 @@
         }
     }
 
+    /** {@hide} */
+    @Deprecated
+    public void removeSessionCallback(@NonNull SessionCallback callback) {
+        unregisterSessionCallback(callback);
+    }
+
     /**
      * Unregister an existing callback.
      */
-    public void removeSessionCallback(@NonNull SessionCallback callback) {
+    public void unregisterSessionCallback(@NonNull SessionCallback callback) {
         synchronized (mDelegates) {
             for (Iterator<SessionCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) {
                 final SessionCallbackDelegate delegate = i.next();
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 6a9d565..097b430 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -216,6 +216,128 @@
      * <p>Configuring a session with an empty or null list will close the current session, if
      * any. This can be used to release the current session's target surfaces for another use.</p>
      *
+     * <p>While any of the sizes from {@link StreamConfigurationMap#getOutputSizes} can be used when
+     * a single output stream is configured, a given camera device may not be able to support all
+     * combination of sizes, formats, and targets when multiple outputs are configured at once.  The
+     * tables below list the maximum guaranteed resolutions for combinations of streams and targets,
+     * given the capabilities of the camera device.</p>
+     *
+     * <p>If an application tries to create a session using a set of targets that exceed the limits
+     * described in the below tables, one of three possibilities may occur. First, the session may
+     * be successfully created and work normally. Second, the session may be successfully created,
+     * but the camera device won't meet the frame rate guarantees as described in
+     * {@link StreamConfigurationMap#getOutputMinFrameDuration}. Or third, if the output set
+     * cannot be used at all, session creation will fail entirely, with
+     * {@link CameraCaptureSession.StateListener#onConfigureFailed} being invoked.</p>
+     *
+     * <p>For the type column, {@code PRIV} refers to any target whose available sizes are found
+     * using {@link StreamConfigurationMap#getOutputSizes(Class)} with no direct application-visible
+     * format, {@code YUV} refers to a target Surface using the
+     * {@link android.graphics.ImageFormat#YUV_420_888} format, {@code JPEG} refers to the
+     * {@link android.graphics.ImageFormat#JPEG} format, and {@code RAW} refers to the
+     * {@link android.graphics.ImageFormat#RAW_SENSOR} format.</p>
+     *
+     * <p>For the maximum size column, {@code PREVIEW} refers to the best size match to the
+     * device's screen resolution, or to 1080p ({@code 1920x1080}), whichever is
+     * smaller. {@code RECORD} refers to the camera device's maximum supported recording resolution,
+     * as determined by {@link android.media.CamcorderProfile}. And {@code MAXIMUM} refers to the
+     * camera device's maximum output resolution for that format or target from
+     * {@link StreamConfigurationMap#getOutputSizes}.</p>
+     *
+     * <p>To use these tables, determine the number and the formats/targets of outputs needed, and
+     * find the row(s) of the table with those targets. The sizes indicate the maximum set of sizes
+     * that can be used; it is guaranteed that for those targets, the listed sizes and anything
+     * smaller from the list given by {@link StreamConfigurationMap#getOutputSizes} can be
+     * successfully used to create a session.  For example, if a row indicates that a 8 megapixel
+     * (MP) YUV_420_888 output can be used together with a 2 MP {@code PRIV} output, then a session
+     * can be created with targets {@code [8 MP YUV, 2 MP PRIV]} or targets {@code [2 MP YUV, 2 MP
+     * PRIV]}; but a session with targets {@code [8 MP YUV, 4 MP PRIV]}, targets {@code [4 MP YUV, 4
+     * MP PRIV]}, or targets {@code [8 MP PRIV, 2 MP YUV]} would not be guaranteed to work, unless
+     * some other row of the table lists such a combination.</p>
+     *
+     * <style scoped>
+     *  #rb { border-right-width: thick; }
+     * </style>
+     * <p>Legacy devices ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
+     * {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY}) support at
+     * least the following stream combinations:
+     *
+     * <table>
+     * <tr><th colspan="7">LEGACY-level guaranteed configurations</th></tr>
+     * <tr> <th colspan="2" id="rb">Target 1</th> <th colspan="2" id="rb">Target 2</th>  <th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
+     * <tr> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th></tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>Simple preview, GPU video processing, or no-preview video recording.</td> </tr>
+     * <tr> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>No-viewfinder still image capture.</td> </tr>
+     * <tr> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>In-application video/image processing.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>Standard still imaging.</td> </tr>
+     * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>In-app processing plus still capture.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td colspan="2" id="rb"></td> <td>Standard recording.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td colspan="2" id="rb"></td> <td>Preview plus in-app processing.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>Still capture plus in-app processing.</td> </tr>
+     * </table><br>
+     * </p>
+     *
+     * <p>Limited-capability ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
+     * {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED}) devices
+     * support at least the following stream combinations in addition to those for
+     * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY} devices:
+     *
+     * <table>
+     * <tr><th colspan="7">LIMITED-level additional guaranteed configurations</th></tr>
+     * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
+     * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code RECORD }</td> <td colspan="2" id="rb"></td> <td>High-resolution video recording with preview.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code RECORD }</td> <td colspan="2" id="rb"></td> <td>High-resolution in-app video processing with preview.</td> </tr>
+     * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code RECORD }</td> <td colspan="2" id="rb"></td> <td>Two-input in-app video processing.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code RECORD }</td> <td>{@code JPEG}</td><td id="rb">{@code RECORD }</td> <td>High-resolution recording with video snapshot.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code RECORD }</td> <td>{@code JPEG}</td><td id="rb">{@code RECORD }</td> <td>High-resolution in-app processing with video snapshot.</td> </tr>
+     * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>Two-input in-app processing with still capture.</td> </tr>
+     * </table><br>
+     * </p>
+     *
+     * <p>FULL-capability ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
+     * {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}) devices
+     * support at least the following stream combinations in addition to those for
+     * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices:
+     *
+     * <table>
+     * <tr><th colspan="7">FULL-capability additional guaranteed configurations</th></tr>
+     * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
+     * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution GPU processing with preview.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution in-app processing with preview.</td> </tr>
+     * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution two-input in-app processsing.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>Video recording with maximum-size video snapshot</td> </tr>
+     * <tr> <td>{@code YUV }</td><td id="rb">{@code 640x480}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td>Standard video recording plus maximum-resolution in-app processing.</td> </tr>
+     * <tr> <td>{@code YUV }</td><td id="rb">{@code 640x480}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td>Preview plus two-input maximum-resolution in-app processing.</td> </tr>
+     * </table><br>
+     * </p>
+     *
+     * <p>RAW-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes
+     * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_RAW RAW}) devices additionally support
+     * at least the following stream combinations on both
+     * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL} and
+     * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices:
+     *
+     * <table>
+     * <tr><th colspan="7">RAW-capability additional guaranteed configurations</th></tr>
+     * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
+     * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
+     * <tr> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>No-preview DNG capture.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>Standard DNG capture.</td> </tr>
+     * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>In-app processing plus DNG capture.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td>Video recording with DNG capture.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td>Preview with in-app processing and DNG capture.</td> </tr>
+     * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td>Two-input in-app processing plus DNG capture.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td>Still capture with simultaneous JPEG and DNG.</td> </tr>
+     * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td>In-app processing with simultaneous JPEG and DNG.</td> </tr>
+     * </table><br>
+     * </p>
+     *
+     * <p>Since the capabilities of camera devices vary greatly, a given camera device may support
+     * target combinations with sizes outside of these guarantees, but this can only be tested for
+     * by attempting to create a session with such targets.</p>
+     *
      * @param outputs The new set of Surfaces that should be made available as
      *                targets for captured image data.
      * @param listener The listener to notify about the status of the new capture session.
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index c0b7967..5d226e3 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -142,7 +142,7 @@
      * or in {@link PixelFormat} (and there is no possibility of collision).</p>
      *
      * <p>Formats listed in this array are guaranteed to return true if queried with
-     * {@link #isOutputSupportedFor(int).</p>
+     * {@link #isOutputSupportedFor(int)}.</p>
      *
      * @return an array of integer format
      *
diff --git a/core/java/android/transition/ArcMotion.java b/core/java/android/transition/ArcMotion.java
index a27063d..f95fb49 100644
--- a/core/java/android/transition/ArcMotion.java
+++ b/core/java/android/transition/ArcMotion.java
@@ -41,9 +41,9 @@
  * {@code
  * &lt;changeBounds>
  *   &lt;arcMotion android:minimumHorizontalAngle="15"
- *     android:minimumVerticalAngle="0" android:maximumAngle="90"/>
- * &lt;/changeBounds>
- * }
+ *              android:minimumVerticalAngle="0"
+ *              android:maximumAngle="90"/>
+ * &lt;/changeBounds>}
  * </pre>
  */
 public class ArcMotion extends PathMotion {
diff --git a/core/java/android/transition/ChangeTransform.java b/core/java/android/transition/ChangeTransform.java
index cb0a875..1b8d57c 100644
--- a/core/java/android/transition/ChangeTransform.java
+++ b/core/java/android/transition/ChangeTransform.java
@@ -99,6 +99,7 @@
      * @return <code>true</code> when a changed parent should execute the transition
      * inside the scene root's overlay or <code>false</code> if a parent change only
      * affects the transform of the transitioning view.
+     * @attr ref android.R.styleable#ChangeTransform_reparentWithOverlay
      */
     public boolean getReparentWithOverlay() {
         return mUseOverlay;
@@ -120,6 +121,7 @@
      * @return <code>true</code> when a changed parent should execute the transition
      * inside the scene root's overlay or <code>false</code> if a parent change only
      * affects the transform of the transitioning view.
+     * @attr ref android.R.styleable#ChangeTransform_reparentWithOverlay
      */
     public void setReparentWithOverlay(boolean reparentWithOverlay) {
         mUseOverlay = reparentWithOverlay;
@@ -132,6 +134,7 @@
      * view will be tracked. Default is true.
      *
      * @return whether parent changes will be tracked by the ChangeTransform.
+     * @attr ref android.R.styleable#ChangeTransform_reparent
      */
     public boolean getReparent() {
         return mReparent;
@@ -145,6 +148,7 @@
      *
      * @param reparent Set to true to track parent changes or false to only track changes
      *                 of the transitioning view without considering the parent change.
+     * @attr ref android.R.styleable#ChangeTransform_reparent
      */
     public void setReparent(boolean reparent) {
         mReparent = reparent;
diff --git a/core/java/android/transition/PatternMotion.java b/core/java/android/transition/PatternPathMotion.java
similarity index 68%
rename from core/java/android/transition/PatternMotion.java
rename to core/java/android/transition/PatternPathMotion.java
index e4045b4..a609df6 100644
--- a/core/java/android/transition/PatternMotion.java
+++ b/core/java/android/transition/PatternPathMotion.java
@@ -34,36 +34,35 @@
  * <pre>
  * {@code
  * &lt;changeBounds>
- *     &lt;patternMotion android:pathData="M0 0 L0 100 L100 100"/>
- * &lt;/changeBounds>
- * }
+ *     &lt;patternPathMotion android:patternPathData="M0 0 L0 100 L100 100"/>
+ * &lt;/changeBounds>}
  * </pre>
  */
-public class PatternMotion extends PathMotion {
+public class PatternPathMotion extends PathMotion {
 
-    private Path mOriginalPattern;
+    private Path mOriginalPatternPath;
 
-    private final Path mPattern = new Path();
+    private final Path mPatternPath = new Path();
 
     private final Matrix mTempMatrix = new Matrix();
 
     /**
-     * Constructs a PatternMotion with a straight-line pattern.
+     * Constructs a PatternPathMotion with a straight-line pattern.
      */
-    public PatternMotion() {
-        mPattern.lineTo(1, 0);
-        mOriginalPattern = mPattern;
+    public PatternPathMotion() {
+        mPatternPath.lineTo(1, 0);
+        mOriginalPatternPath = mPatternPath;
     }
 
-    public PatternMotion(Context context, AttributeSet attrs) {
-        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PatternMotion);
+    public PatternPathMotion(Context context, AttributeSet attrs) {
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PatternPathMotion);
         try {
-            String pathData = a.getString(R.styleable.PatternMotion_pathData);
+            String pathData = a.getString(R.styleable.PatternPathMotion_patternPathData);
             if (pathData == null) {
-                throw new RuntimeException("pathData must be supplied for patternMotion");
+                throw new RuntimeException("pathData must be supplied for patternPathMotion");
             }
             Path pattern = PathParser.createPathFromPathData(pathData);
-            setPattern(pattern);
+            setPatternPath(pattern);
         } finally {
             a.recycle();
         }
@@ -71,14 +70,15 @@
     }
 
     /**
-     * Creates a PatternMotion with the Path defining a pattern of motion between two coordinates.
-     * The pattern will be translated, rotated, and scaled to fit between the start and end points.
-     * The pattern must not be empty and must have the end point differ from the start point.
+     * Creates a PatternPathMotion with the Path defining a pattern of motion between two
+     * coordinates. The pattern will be translated, rotated, and scaled to fit between the start
+     * and end points. The pattern must not be empty and must have the end point differ from the
+     * start point.
      *
-     * @param pattern A Path to be used as a pattern for two-dimensional motion.
+     * @param patternPath A Path to be used as a pattern for two-dimensional motion.
      */
-    public PatternMotion(Path pattern) {
-        setPattern(pattern);
+    public PatternPathMotion(Path patternPath) {
+        setPatternPath(patternPath);
     }
 
     /**
@@ -87,10 +87,10 @@
      * The pattern must not be empty and must have the end point differ from the start point.
      *
      * @return the Path defining a pattern of motion between two coordinates.
-     * @attr ref android.R.styleable#PatternMotion_pathData
+     * @attr ref android.R.styleable#PatternPathMotion_patternPathData
      */
-    public Path getPattern() {
-        return mOriginalPattern;
+    public Path getPatternPath() {
+        return mOriginalPatternPath;
     }
 
     /**
@@ -98,11 +98,11 @@
      * The pattern will be translated, rotated, and scaled to fit between the start and end points.
      * The pattern must not be empty and must have the end point differ from the start point.
      *
-     * @param pattern A Path to be used as a pattern for two-dimensional motion.
-     * @attr ref android.R.styleable#PatternMotion_pathData
+     * @param patternPath A Path to be used as a pattern for two-dimensional motion.
+     * @attr ref android.R.styleable#PatternPathMotion_patternPathData
      */
-    public void setPattern(Path pattern) {
-        PathMeasure pathMeasure = new PathMeasure(pattern, false);
+    public void setPatternPath(Path patternPath) {
+        PathMeasure pathMeasure = new PathMeasure(patternPath, false);
         float length = pathMeasure.getLength();
         float[] pos = new float[2];
         pathMeasure.getPosTan(length, pos, null);
@@ -124,8 +124,8 @@
         mTempMatrix.postScale(scale, scale);
         double angle = Math.atan2(dy, dx);
         mTempMatrix.postRotate((float) Math.toDegrees(-angle));
-        pattern.transform(mTempMatrix, mPattern);
-        mOriginalPattern = pattern;
+        patternPath.transform(mTempMatrix, mPatternPath);
+        mOriginalPatternPath = patternPath;
     }
 
     @Override
@@ -139,7 +139,7 @@
         mTempMatrix.postRotate((float) Math.toDegrees(angle));
         mTempMatrix.postTranslate(startX, startY);
         Path path = new Path();
-        mPattern.transform(mTempMatrix, path);
+        mPatternPath.transform(mTempMatrix, path);
         return path;
     }
 
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index bd52e71..0d1b568 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -1989,8 +1989,33 @@
      *     by extending PathMotion and implementing
      *     {@link android.transition.PathMotion#getPath(float, float, float, float)}.
      * </p>
+     * <p>
+     *     When describing in XML, use a nested XML tag for the path motion. It can be one of
+     *     the built-in tags <code>arcMotion</code> or <code>patternPathMotion</code> or it can
+     *     be a custom PathMotion using <code>pathMotion</code> with the <code>class</code>
+     *     attributed with the fully-described class name. For example:</p>
+     * <pre>
+     * {@code
+     * &lt;changeBounds>
+     *     &lt;pathMotion class="my.app.transition.MyPathMotion"/>
+     * &lt;/changeBounds>
+     * }
+     * </pre>
+     * <p>or</p>
+     * <pre>
+     * {@code
+     * &lt;changeBounds>
+     *   &lt;arcMotion android:minimumHorizontalAngle="15"
+     *     android:minimumVerticalAngle="0" android:maximumAngle="90"/>
+     * &lt;/changeBounds>
+     * }
+     * </pre>
+     *
      * @param pathMotion Algorithm object to use for determining how to interpolate in two
      *                   dimensions. If null, a straight-path algorithm will be used.
+     * @see android.transition.ArcMotion
+     * @see PatternPathMotion
+     * @see android.transition.PathMotion
      */
     public void setPathMotion(PathMotion pathMotion) {
         if (pathMotion == null) {
@@ -2004,7 +2029,31 @@
      * Returns the algorithm object used to interpolate along two dimensions. This is typically
      * used to determine the View motion between two points.
      *
+     * <p>
+     *     When describing in XML, use a nested XML tag for the path motion. It can be one of
+     *     the built-in tags <code>arcMotion</code> or <code>patternPathMotion</code> or it can
+     *     be a custom PathMotion using <code>pathMotion</code> with the <code>class</code>
+     *     attributed with the fully-described class name. For example:</p>
+     * <pre>
+     * {@code
+     * &lt;changeBounds>
+     *     &lt;pathMotion class="my.app.transition.MyPathMotion"/>
+     * &lt;/changeBounds>}
+     * </pre>
+     * <p>or</p>
+     * <pre>
+     * {@code
+     * &lt;changeBounds>
+     *   &lt;arcMotion android:minimumHorizontalAngle="15"
+     *              android:minimumVerticalAngle="0"
+     *              android:maximumAngle="90"/>
+     * &lt;/changeBounds>}
+     * </pre>
+     *
      * @return The algorithm object used to interpolate along two dimensions.
+     * @see android.transition.ArcMotion
+     * @see PatternPathMotion
+     * @see android.transition.PathMotion
      */
     public PathMotion getPathMotion() {
         return mPathMotion;
diff --git a/core/java/android/transition/TransitionInflater.java b/core/java/android/transition/TransitionInflater.java
index 760ffe1..9009d6a 100644
--- a/core/java/android/transition/TransitionInflater.java
+++ b/core/java/android/transition/TransitionInflater.java
@@ -171,8 +171,8 @@
                 parent.setPathMotion(new ArcMotion(mContext, attrs));
             } else if ("pathMotion".equals(name)) {
                 parent.setPathMotion((PathMotion)createCustom(attrs, PathMotion.class, "pathMotion"));
-            } else if ("patternMotion".equals(name)) {
-                parent.setPathMotion(new PatternMotion(mContext, attrs));
+            } else if ("patternPathMotion".equals(name)) {
+                parent.setPathMotion(new PatternPathMotion(mContext, attrs));
             } else {
                 throw new RuntimeException("Unknown scene name: " + parser.getName());
             }
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index ceea9f8..076f1e2 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -800,28 +800,6 @@
     }
 
     @Override
-    public void drawPicture(Picture picture, Rect dst) {
-        save();
-        translate(dst.left, dst.top);
-        if (picture.getWidth() > 0 && picture.getHeight() > 0) {
-            scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
-        }
-        drawPicture(picture);
-        restore();
-    }
-
-    @Override
-    public void drawPicture(Picture picture, RectF dst) {
-        save();
-        translate(dst.left, dst.top);
-        if (picture.getWidth() > 0 && picture.getHeight() > 0) {
-            scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
-        }
-        drawPicture(picture);
-        restore();
-    }
-
-    @Override
     public void drawPoint(float x, float y, Paint paint) {
         float[] point = getPointStorage();
         point[0] = x;
diff --git a/core/jni/android_ddm_DdmHandleNativeHeap.cpp b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
index f5eaf94..9b96320 100644
--- a/core/jni/android_ddm_DdmHandleNativeHeap.cpp
+++ b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
@@ -35,7 +35,15 @@
 
 extern "C" void free_malloc_leak_info(uint8_t* info);
 
+#define DDMS_HEADER_SIGNATURE 0x812345dd
+#define DDMS_VERSION 2
+
 struct Header {
+#if defined(__LP64__)
+    uint32_t signature;
+    uint16_t version;
+    uint16_t pointerSize;
+#endif
     size_t mapSize;
     size_t allocSize;
     size_t allocInfoSize;
@@ -77,6 +85,12 @@
     ALOGD("*** mapSize: %d allocSize: %d allocInfoSize: %d totalMemory: %d",
           header.mapSize, header.allocSize, header.allocInfoSize, header.totalMemory);
 
+#if defined(__LP64__)
+    header.signature = DDMS_HEADER_SIGNATURE;
+    header.version = DDMS_VERSION;
+    header.pointerSize = sizeof(void*);
+#endif
+
     jbyteArray array = env->NewByteArray(sizeof(Header) + header.mapSize + header.allocSize);
     if (array != NULL) {
         env->SetByteArrayRegion(array, 0,
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 3629cbb..d1cc1fd 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5686,12 +5686,12 @@
         <attr name="maximumAngle" format="float" />
     </declare-styleable>
 
-    <!-- Use <code>patternMotion</code> as the root tag of the XML resource that
-         describes a {@link android.transition.PatternMotion}. This must be used
+    <!-- Use <code>patternPathMotion</code> as the root tag of the XML resource that
+         describes a {@link android.transition.PatternPathMotion}. This must be used
          within a transition with which the PathMotion should be associated. -->
-    <declare-styleable name="PatternMotion">
-        <!-- The path string describing the pattern to use for the PathMotion. -->
-        <attr name="pathData" />
+    <declare-styleable name="PatternPathMotion">
+        <!-- The path string describing the pattern to use for the PathPathMotion. -->
+        <attr name="patternPathData" format="string" />
     </declare-styleable>
 
     <!-- ========================== -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 4bf4531..a4c3474 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2290,6 +2290,7 @@
   <public type="attr" name="fragmentReenterTransition" />
   <public type="attr" name="fragmentAllowEnterTransitionOverlap" />
   <public type="attr" name="fragmentAllowReturnTransitionOverlap" />
+  <public type="attr" name="patternPathData" />
 
   <public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
 
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index f18694b..0927ffd 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -203,7 +203,7 @@
      */
     public void setBitmap(@Nullable Bitmap bitmap) {
         if (isHardwareAccelerated()) {
-            throw new RuntimeException("Can't set a bitmap device on a GL canvas");
+            throw new RuntimeException("Can't set a bitmap device on a HW accelerated canvas");
         }
 
         if (bitmap == null) {
diff --git a/graphics/java/android/graphics/Picture.java b/graphics/java/android/graphics/Picture.java
index 5aa7c6a..d28c3d5 100644
--- a/graphics/java/android/graphics/Picture.java
+++ b/graphics/java/android/graphics/Picture.java
@@ -122,6 +122,11 @@
      * @param canvas  The picture is drawn to this canvas
      */
     public void draw(Canvas canvas) {
+        if (canvas.isHardwareAccelerated()) {
+            throw new IllegalArgumentException(
+                    "Picture playback is only supported on software canvas.");
+        }
+
         if (mRecordingCanvas != null) {
             endRecording();
         }
diff --git a/graphics/java/android/graphics/PorterDuffColorFilter.java b/graphics/java/android/graphics/PorterDuffColorFilter.java
index c078c1c..705f5e6 100644
--- a/graphics/java/android/graphics/PorterDuffColorFilter.java
+++ b/graphics/java/android/graphics/PorterDuffColorFilter.java
@@ -60,6 +60,8 @@
      * @see Color
      * @see #getColor()
      * @see #getMode()
+     *
+     * @hide
      */
     public void setColor(int color) {
         mColor = color;
@@ -84,6 +86,8 @@
      * @see PorterDuff
      * @see #getMode()
      * @see #getColor()
+     *
+     * @hide
      */
     public void setMode(PorterDuff.Mode mode) {
         mMode = mode;
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 329033c..1d16793 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -1777,6 +1777,15 @@
             return;
         }
 
+        if ( (mode == AudioSystem.MODE_IN_CALL) &&
+                (mContext.checkCallingOrSelfPermission(
+                        android.Manifest.permission.MODIFY_PHONE_STATE)
+                            != PackageManager.PERMISSION_GRANTED)) {
+            Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setMode(MODE_IN_CALL) from pid="
+                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
+            return;
+        }
+
         if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) {
             return;
         }
@@ -1798,7 +1807,7 @@
     // must be called synchronized on mSetModeDeathHandlers
     // setModeInt() returns a valid PID if the audio mode was successfully set to
     // any mode other than NORMAL.
-    int setModeInt(int mode, IBinder cb, int pid) {
+    private int setModeInt(int mode, IBinder cb, int pid) {
         if (DEBUG_MODE) { Log.v(TAG, "setModeInt(mode=" + mode + ", pid=" + pid + ")"); }
         int newModeOwnerPid = 0;
         if (cb == null) {
@@ -3058,7 +3067,7 @@
     }
 
     boolean checkAudioSettingsPermission(String method) {
-        if (mContext.checkCallingOrSelfPermission("android.permission.MODIFY_AUDIO_SETTINGS")
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS)
                 == PackageManager.PERMISSION_GRANTED) {
             return true;
         }
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 3f7a607..9a00923 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -47,12 +47,12 @@
 import android.content.pm.IPackageInstallerCallback;
 import android.content.pm.IPackageInstallerSession;
 import android.content.pm.PackageInstaller;
-import android.content.pm.PackageParser;
 import android.content.pm.PackageInstaller.SessionInfo;
 import android.content.pm.PackageInstaller.SessionParams;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
 import android.content.pm.PackageParser.PackageLite;
 import android.content.pm.PackageParser.PackageParserException;
-import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Binder;
@@ -581,6 +581,30 @@
     }
 
     @Override
+    public void updateSessionAppIcon(int sessionId, Bitmap appIcon) {
+        synchronized (mSessions) {
+            final PackageInstallerSession session = mSessions.get(sessionId);
+            if (session == null || !isCallingUidOwner(session)) {
+                throw new SecurityException("Caller has no access to session " + sessionId);
+            }
+            session.params.appIcon = appIcon;
+            mInternalCallback.onSessionBadgingChanged(session);
+        }
+    }
+
+    @Override
+    public void updateSessionAppLabel(int sessionId, String appLabel) {
+        synchronized (mSessions) {
+            final PackageInstallerSession session = mSessions.get(sessionId);
+            if (session == null || !isCallingUidOwner(session)) {
+                throw new SecurityException("Caller has no access to session " + sessionId);
+            }
+            session.params.appLabel = appLabel;
+            mInternalCallback.onSessionBadgingChanged(session);
+        }
+    }
+
+    @Override
     public void abandonSession(int sessionId) {
         synchronized (mSessions) {
             final PackageInstallerSession session = mSessions.get(sessionId);
@@ -681,9 +705,6 @@
     public SessionInfo getSessionInfo(int sessionId) {
         synchronized (mSessions) {
             final PackageInstallerSession session = mSessions.get(sessionId);
-            if (!isCallingUidOwner(session)) {
-                enforceCallerCanReadSessions();
-            }
             return session != null ? session.generateInfo() : null;
         }
     }
@@ -691,7 +712,6 @@
     @Override
     public List<SessionInfo> getAllSessions(int userId) {
         mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "getAllSessions");
-        enforceCallerCanReadSessions();
 
         final List<SessionInfo> result = new ArrayList<>();
         synchronized (mSessions) {
@@ -755,8 +775,6 @@
     @Override
     public void registerCallback(IPackageInstallerCallback callback, int userId) {
         mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "registerCallback");
-        enforceCallerCanReadSessions();
-
         mCallbacks.register(callback, userId);
     }
 
@@ -787,21 +805,6 @@
         }
     }
 
-    /**
-     * We allow those with permission, or the current home app.
-     */
-    private void enforceCallerCanReadSessions() {
-        final boolean hasPermission = (mContext.checkCallingOrSelfPermission(
-                android.Manifest.permission.READ_INSTALL_SESSIONS)
-                == PackageManager.PERMISSION_GRANTED);
-        final boolean isHomeApp = mPm.checkCallerIsHomeApp();
-        if (hasPermission || isHomeApp) {
-            return;
-        } else {
-            throw new SecurityException("Caller must be current home app to read install sessions");
-        }
-    }
-
     static class PackageDeleteObserverAdapter extends PackageDeleteObserver {
         private final Context mContext;
         private final IntentSender mTarget;
@@ -893,10 +896,11 @@
 
     private static class Callbacks extends Handler {
         private static final int MSG_SESSION_CREATED = 1;
-        private static final int MSG_SESSION_OPENED = 2;
-        private static final int MSG_SESSION_PROGRESS_CHANGED = 3;
-        private static final int MSG_SESSION_CLOSED = 4;
-        private static final int MSG_SESSION_FINISHED = 5;
+        private static final int MSG_SESSION_BADGING_CHANGED = 2;
+        private static final int MSG_SESSION_OPENED = 3;
+        private static final int MSG_SESSION_PROGRESS_CHANGED = 4;
+        private static final int MSG_SESSION_CLOSED = 5;
+        private static final int MSG_SESSION_FINISHED = 6;
 
         private final RemoteCallbackList<IPackageInstallerCallback>
                 mCallbacks = new RemoteCallbackList<>();
@@ -938,6 +942,9 @@
                 case MSG_SESSION_CREATED:
                     callback.onSessionCreated(sessionId);
                     break;
+                case MSG_SESSION_BADGING_CHANGED:
+                    callback.onSessionBadgingChanged(sessionId);
+                    break;
                 case MSG_SESSION_OPENED:
                     callback.onSessionOpened(sessionId);
                     break;
@@ -957,6 +964,10 @@
             obtainMessage(MSG_SESSION_CREATED, sessionId, userId).sendToTarget();
         }
 
+        private void notifySessionBadgingChanged(int sessionId, int userId) {
+            obtainMessage(MSG_SESSION_BADGING_CHANGED, sessionId, userId).sendToTarget();
+        }
+
         private void notifySessionOpened(int sessionId, int userId) {
             obtainMessage(MSG_SESSION_OPENED, sessionId, userId).sendToTarget();
         }
@@ -1006,14 +1017,19 @@
     }
 
     class InternalCallback {
-        public void onSessionProgressChanged(PackageInstallerSession session, float progress) {
-            mCallbacks.notifySessionProgressChanged(session.sessionId, session.userId, progress);
+        public void onSessionBadgingChanged(PackageInstallerSession session) {
+            mCallbacks.notifySessionBadgingChanged(session.sessionId, session.userId);
+            writeSessionsAsync();
         }
 
         public void onSessionOpened(PackageInstallerSession session) {
             mCallbacks.notifySessionOpened(session.sessionId, session.userId);
         }
 
+        public void onSessionProgressChanged(PackageInstallerSession session, float progress) {
+            mCallbacks.notifySessionProgressChanged(session.sessionId, session.userId, progress);
+        }
+
         public void onSessionClosed(PackageInstallerSession session) {
             mCallbacks.notifySessionClosed(session.sessionId, session.userId);
         }
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 5264fc4..85ff54e 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -294,7 +294,9 @@
     }
 
     private void computeProgressLocked() {
-        mProgress = MathUtils.constrain(mClientProgress * 0.8f, 0f, 0.8f);
+        if (mProgress <= 0.8f) {
+            mProgress = MathUtils.constrain(mClientProgress * 0.8f, 0f, 0.8f);
+        }
     }
 
     private void maybePublishProgress() {
@@ -485,7 +487,8 @@
         }
 
         // TODO: surface more granular state from dexopt
-        mCallback.onSessionProgressChanged(this, 0.9f);
+        mProgress = 0.9f;
+        maybePublishProgress();
 
         // Unpack native libraries
         extractNativeLibraries(mResolvedStageDir, params.abiOverride);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a4d4914..d2a627e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -11746,47 +11746,6 @@
                         preferred.activityInfo.name);
     }
 
-    /**
-     * Check if calling UID is the current home app. This handles both the case
-     * where the user has selected a specific home app, and where there is only
-     * one home app.
-     */
-    public boolean checkCallerIsHomeApp() {
-        final Intent intent = new Intent(Intent.ACTION_MAIN);
-        intent.addCategory(Intent.CATEGORY_HOME);
-
-        final int callingUid = Binder.getCallingUid();
-        final int callingUserId = UserHandle.getCallingUserId();
-        final List<ResolveInfo> allHomes = queryIntentActivities(intent, null, 0, callingUserId);
-        final ResolveInfo preferredHome = findPreferredActivity(intent, null, 0, allHomes, 0, true,
-                false, false, callingUserId);
-
-        if (preferredHome != null) {
-            if (callingUid == preferredHome.activityInfo.applicationInfo.uid) {
-                return true;
-            }
-        } else {
-            for (ResolveInfo info : allHomes) {
-                if (callingUid == info.activityInfo.applicationInfo.uid) {
-                    return true;
-                }
-            }
-        }
-
-        return false;
-    }
-
-    /**
-     * Enforce that calling UID is the current home app. This handles both the
-     * case where the user has selected a specific home app, and where there is
-     * only one home app.
-     */
-    public void enforceCallerIsHomeApp() {
-        if (!checkCallerIsHomeApp()) {
-            throw new SecurityException("Caller is not currently selected home app");
-        }
-    }
-
     @Override
     public void setApplicationEnabledSetting(String appPackageName,
             int newState, int flags, int userId, String callingPackage) {