Revert session-transfer change

This reverts:
5d74493f64493cd506d7458b810095259287f623
94deaf7725c418ec1950d810ab86f0d157ddf518

Bug: 64467704
Test: none, 100% revert
Change-Id: I6534c19c594dadfa41457725988485a67f0ed45f
diff --git a/api/current.txt b/api/current.txt
index 3c9cd8e..dc92604 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -10506,7 +10506,6 @@
     method public java.io.OutputStream openWrite(java.lang.String, long, long) throws java.io.IOException;
     method public void removeSplit(java.lang.String) throws java.io.IOException;
     method public void setStagingProgress(float);
-    method public void transfer(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
   }
 
   public static abstract class PackageInstaller.SessionCallback {
@@ -10524,16 +10523,10 @@
     method public android.graphics.Bitmap getAppIcon();
     method public java.lang.CharSequence getAppLabel();
     method public java.lang.String getAppPackageName();
-    method public int getInstallLocation();
     method public int getInstallReason();
     method public java.lang.String getInstallerPackageName();
-    method public int getMode();
-    method public int getOriginatingUid();
-    method public android.net.Uri getOriginatingUri();
     method public float getProgress();
-    method public android.net.Uri getReferrerUri();
     method public int getSessionId();
-    method public long getSize();
     method public boolean isActive();
     method public boolean isSealed();
     method public void writeToParcel(android.os.Parcel, int);
diff --git a/api/system-current.txt b/api/system-current.txt
index 6c1983d..da9f9eb 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -11180,14 +11180,12 @@
     method public void abandon();
     method public void close();
     method public void commit(android.content.IntentSender);
-    method public void commitTransferred(android.content.IntentSender);
     method public void fsync(java.io.OutputStream) throws java.io.IOException;
     method public java.lang.String[] getNames() throws java.io.IOException;
     method public java.io.InputStream openRead(java.lang.String) throws java.io.IOException;
     method public java.io.OutputStream openWrite(java.lang.String, long, long) throws java.io.IOException;
     method public void removeSplit(java.lang.String) throws java.io.IOException;
     method public void setStagingProgress(float);
-    method public void transfer(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
   }
 
   public static abstract class PackageInstaller.SessionCallback {
@@ -11202,26 +11200,13 @@
   public static class PackageInstaller.SessionInfo implements android.os.Parcelable {
     method public android.content.Intent createDetailsIntent();
     method public int describeContents();
-    method public boolean getAllocateAggressive();
-    method public boolean getAllowDowngrade();
     method public android.graphics.Bitmap getAppIcon();
     method public java.lang.CharSequence getAppLabel();
     method public java.lang.String getAppPackageName();
-    method public boolean getDontKillApp();
-    method public java.lang.String[] getGrantedRuntimePermissions();
-    method public boolean getInstallAsFullApp(boolean);
-    method public boolean getInstallAsInstantApp(boolean);
-    method public boolean getInstallAsVirtualPreload();
-    method public int getInstallLocation();
     method public int getInstallReason();
     method public java.lang.String getInstallerPackageName();
-    method public int getMode();
-    method public int getOriginatingUid();
-    method public android.net.Uri getOriginatingUri();
     method public float getProgress();
-    method public android.net.Uri getReferrerUri();
     method public int getSessionId();
-    method public long getSize();
     method public boolean isActive();
     method public boolean isSealed();
     method public void writeToParcel(android.os.Parcel, int);
diff --git a/api/test-current.txt b/api/test-current.txt
index 839964f..3e27470 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -10544,7 +10544,6 @@
     method public java.io.OutputStream openWrite(java.lang.String, long, long) throws java.io.IOException;
     method public void removeSplit(java.lang.String) throws java.io.IOException;
     method public void setStagingProgress(float);
-    method public void transfer(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
   }
 
   public static abstract class PackageInstaller.SessionCallback {
@@ -10562,16 +10561,10 @@
     method public android.graphics.Bitmap getAppIcon();
     method public java.lang.CharSequence getAppLabel();
     method public java.lang.String getAppPackageName();
-    method public int getInstallLocation();
     method public int getInstallReason();
     method public java.lang.String getInstallerPackageName();
-    method public int getMode();
-    method public int getOriginatingUid();
-    method public android.net.Uri getOriginatingUri();
     method public float getProgress();
-    method public android.net.Uri getReferrerUri();
     method public int getSessionId();
-    method public long getSize();
     method public boolean isActive();
     method public boolean isSealed();
     method public void writeToParcel(android.os.Parcel, int);
diff --git a/core/java/android/content/pm/IPackageInstallerSession.aidl b/core/java/android/content/pm/IPackageInstallerSession.aidl
index 0b16852..2a3fac3 100644
--- a/core/java/android/content/pm/IPackageInstallerSession.aidl
+++ b/core/java/android/content/pm/IPackageInstallerSession.aidl
@@ -32,7 +32,6 @@
     void removeSplit(String splitName);
 
     void close();
-    void commit(in IntentSender statusReceiver, boolean forTransferred);
-    void transfer(in String packageName);
+    void commit(in IntentSender statusReceiver);
     void abandon();
 }
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index f4fdcaa..c3ebf55 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -38,7 +38,6 @@
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
-import android.os.ParcelableException;
 import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.system.ErrnoException;
@@ -794,7 +793,7 @@
          * @throws IOException if trouble opening the file for writing, such as
          *             lack of disk space or unavailable media.
          * @throws SecurityException if called after the session has been
-         *             sealed or abandoned
+         *             committed or abandoned.
          */
         public @NonNull OutputStream openWrite(@NonNull String name, long offsetBytes,
                 long lengthBytes) throws IOException {
@@ -919,68 +918,7 @@
          */
         public void commit(@NonNull IntentSender statusReceiver) {
             try {
-                mSession.commit(statusReceiver, false);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        }
-
-        /**
-         * Attempt to commit a session that has been {@link #transfer(String) transferred}.
-         *
-         * <p>If the device reboots before the session has been finalized, you may commit the
-         * session again.
-         *
-         * <p>The caller of this method is responsible to ensure the safety of the session. As the
-         * session was created by another - usually less trusted - app, it is paramount that before
-         * committing <u>all</u> public and system {@link SessionInfo properties of the session}
-         * and <u>all</u> {@link #openRead(String) APKs} are verified by the caller. It might happen
-         * that new properties are added to the session with a new API revision. In this case the
-         * callers need to be updated.
-         *
-         * @param statusReceiver Callbacks called when the state of the session changes.
-         *
-         * @hide
-         */
-        @SystemApi
-        @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES)
-        public void commitTransferred(@NonNull IntentSender statusReceiver) {
-            try {
-                mSession.commit(statusReceiver, true);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        }
-
-        /**
-         * Transfer the session to a new owner.
-         * <p>
-         * Only sessions that update the installing app can be transferred.
-         * <p>
-         * After the transfer to a package with a different uid all method calls on the session
-         * will cause {@link SecurityException}s.
-         * <p>
-         * Once this method is called, the session is sealed and no additional mutations beside
-         * committing it may be performed on the session.
-         *
-         * @param packageName The package of the new owner. Needs to hold the INSTALL_PACKAGES
-         *                    permission.
-         *
-         * @throws PackageManager.NameNotFoundException if the new owner could not be found.
-         * @throws SecurityException if called after the session has been committed or abandoned.
-         * @throws SecurityException if the session does not update the original installer
-         * @throws SecurityException if streams opened through
-         *                           {@link #openWrite(String, long, long) are still open.
-         */
-        public void transfer(@NonNull String packageName)
-                throws PackageManager.NameNotFoundException {
-            Preconditions.checkNotNull(packageName);
-
-            try {
-                mSession.transfer(packageName);
-            } catch (ParcelableException e) {
-                e.maybeRethrow(PackageManager.NameNotFoundException.class);
-                throw new RuntimeException(e);
+                mSession.commit(statusReceiver);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -1103,26 +1041,6 @@
         }
 
         /**
-         * Check if there are hidden options set.
-         *
-         * <p>Hidden options are those options that cannot be verified via public or system-api
-         * methods on {@link SessionInfo}.
-         *
-         * @return {@code true} if any hidden option is set.
-         *
-         * @hide
-         */
-        public boolean areHiddenOptionsSet() {
-            return (installFlags & (PackageManager.INSTALL_ALLOW_DOWNGRADE
-                    | PackageManager.INSTALL_DONT_KILL_APP
-                    | PackageManager.INSTALL_INSTANT_APP
-                    | PackageManager.INSTALL_FULL_APP
-                    | PackageManager.INSTALL_VIRTUAL_PRELOAD
-                    | PackageManager.INSTALL_ALLOCATE_AGGRESSIVE)) != installFlags
-                    || abiOverride != null || volumeUuid != null;
-        }
-
-        /**
          * Provide value of {@link PackageInfo#installLocation}, which may be used
          * to determine where the app will be staged. Defaults to
          * {@link PackageInfo#INSTALL_LOCATION_INTERNAL_ONLY}.
@@ -1382,19 +1300,6 @@
         public CharSequence appLabel;
 
         /** {@hide} */
-        public int installLocation;
-        /** {@hide} */
-        public Uri originatingUri;
-        /** {@hide} */
-        public int originatingUid;
-        /** {@hide} */
-        public Uri referrerUri;
-        /** {@hide} */
-        public String[] grantedRuntimePermissions;
-        /** {@hide} */
-        public int installFlags;
-
-        /** {@hide} */
         public SessionInfo() {
         }
 
@@ -1413,13 +1318,6 @@
             appPackageName = source.readString();
             appIcon = source.readParcelable(null);
             appLabel = source.readString();
-
-            installLocation = source.readInt();
-            originatingUri = source.readParcelable(null);
-            originatingUid = source.readInt();
-            referrerUri = source.readParcelable(null);
-            grantedRuntimePermissions = source.readStringArray();
-            installFlags = source.readInt();
         }
 
         /**
@@ -1543,130 +1441,6 @@
             return intent;
         }
 
-        /**
-         * Get the mode of the session as set in the constructor of the {@link SessionParams}.
-         *
-         * @return One of {@link SessionParams#MODE_FULL_INSTALL}
-         *         or {@link SessionParams#MODE_INHERIT_EXISTING}
-         */
-        public int getMode() {
-            return mode;
-        }
-
-        /**
-         * Get the value set in {@link SessionParams#setInstallLocation(int)}.
-         */
-        public int getInstallLocation() {
-            return installLocation;
-        }
-
-        /**
-         * Get the value as set in {@link SessionParams#setSize(long)}.
-         *
-         * <p>The value is a hint and does not have to match the actual size.
-         */
-        public long getSize() {
-            return sizeBytes;
-        }
-
-        /**
-         * Get the value set in {@link SessionParams#setOriginatingUri(Uri)}.
-         */
-        public @Nullable Uri getOriginatingUri() {
-            return originatingUri;
-        }
-
-        /**
-         * Get the value set in {@link SessionParams#setOriginatingUid(int)}.
-         */
-        public int getOriginatingUid() {
-            return originatingUid;
-        }
-
-        /**
-         * Get the value set in {@link SessionParams#setReferrerUri(Uri)}
-         */
-        public @Nullable Uri getReferrerUri() {
-            return referrerUri;
-        }
-
-        /**
-         * Get the value set in {@link SessionParams#setGrantedRuntimePermissions(String[])}.
-         *
-         * @hide
-         */
-        @SystemApi
-        public @Nullable String[] getGrantedRuntimePermissions() {
-            return grantedRuntimePermissions;
-        }
-
-        /**
-         * Get the value set in {@link SessionParams#setAllowDowngrade(boolean)}.
-         *
-         * @hide
-         */
-        @SystemApi
-        public boolean getAllowDowngrade() {
-            return (installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) != 0;
-        }
-
-        /**
-         * Get the value set in {@link SessionParams#setDontKillApp(boolean)}.
-         *
-         * @hide
-         */
-        @SystemApi
-        public boolean getDontKillApp() {
-            return (installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0;
-        }
-
-        /**
-         * If {@link SessionParams#setInstallAsInstantApp(boolean)} was called with {@code true},
-         * return true. If it was called with {@code false} or if it was not called return false.
-         *
-         * @hide
-         *
-         * @see #getInstallAsFullApp
-         */
-        @SystemApi
-        public boolean getInstallAsInstantApp(boolean isInstantApp) {
-            return (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
-        }
-
-        /**
-         * If {@link SessionParams#setInstallAsInstantApp(boolean)} was called with {@code false},
-         * return true. If it was called with {@code true} or if it was not called return false.
-         *
-         * @hide
-         *
-         * @see #getInstallAsInstantApp
-         */
-        @SystemApi
-        public boolean getInstallAsFullApp(boolean isInstantApp) {
-            return (installFlags & PackageManager.INSTALL_FULL_APP) != 0;
-        }
-
-        /**
-         * Get if {@link SessionParams#setInstallAsVirtualPreload()} was called.
-         *
-         * @hide
-         */
-        @SystemApi
-        public boolean getInstallAsVirtualPreload() {
-            return (installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0;
-        }
-
-        /**
-         * Get the value set in {@link SessionParams#setAllocateAggressive(boolean)}.
-         *
-         * @hide
-         */
-        @SystemApi
-        public boolean getAllocateAggressive() {
-            return (installFlags & PackageManager.INSTALL_ALLOCATE_AGGRESSIVE) != 0;
-        }
-
-
         /** {@hide} */
         @Deprecated
         public @Nullable Intent getDetailsIntent() {
@@ -1693,13 +1467,6 @@
             dest.writeString(appPackageName);
             dest.writeParcelable(appIcon, flags);
             dest.writeString(appLabel != null ? appLabel.toString() : null);
-
-            dest.writeInt(installLocation);
-            dest.writeParcelable(originatingUri, flags);
-            dest.writeInt(originatingUid);
-            dest.writeParcelable(referrerUri, flags);
-            dest.writeStringArray(grantedRuntimePermissions);
-            dest.writeInt(installFlags);
         }
 
         public static final Parcelable.Creator<SessionInfo>
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index c3b93b4..bab7011 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -16,6 +16,17 @@
 
 package com.android.server.pm;
 
+import static com.android.internal.util.XmlUtils.readBitmapAttribute;
+import static com.android.internal.util.XmlUtils.readBooleanAttribute;
+import static com.android.internal.util.XmlUtils.readIntAttribute;
+import static com.android.internal.util.XmlUtils.readLongAttribute;
+import static com.android.internal.util.XmlUtils.readStringAttribute;
+import static com.android.internal.util.XmlUtils.readUriAttribute;
+import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
+import static com.android.internal.util.XmlUtils.writeIntAttribute;
+import static com.android.internal.util.XmlUtils.writeLongAttribute;
+import static com.android.internal.util.XmlUtils.writeStringAttribute;
+import static com.android.internal.util.XmlUtils.writeUriAttribute;
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
 
@@ -43,6 +54,8 @@
 import android.content.pm.ParceledListSlice;
 import android.content.pm.VersionedPackage;
 import android.graphics.Bitmap;
+import android.graphics.Bitmap.CompressFormat;
+import android.graphics.BitmapFactory;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -71,6 +84,9 @@
 import android.util.SparseIntArray;
 import android.util.Xml;
 
+import java.io.CharArrayWriter;
+import libcore.io.IoUtils;
+
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.PackageHelper;
@@ -81,13 +97,10 @@
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.IoThread;
 
-import libcore.io.IoUtils;
-
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
-import java.io.CharArrayWriter;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -112,6 +125,32 @@
 
     /** XML constants used in {@link #mSessionsFile} */
     private static final String TAG_SESSIONS = "sessions";
+    private static final String TAG_SESSION = "session";
+    private static final String TAG_GRANTED_RUNTIME_PERMISSION = "granted-runtime-permission";
+    private static final String ATTR_SESSION_ID = "sessionId";
+    private static final String ATTR_USER_ID = "userId";
+    private static final String ATTR_INSTALLER_PACKAGE_NAME = "installerPackageName";
+    private static final String ATTR_INSTALLER_UID = "installerUid";
+    private static final String ATTR_CREATED_MILLIS = "createdMillis";
+    private static final String ATTR_SESSION_STAGE_DIR = "sessionStageDir";
+    private static final String ATTR_SESSION_STAGE_CID = "sessionStageCid";
+    private static final String ATTR_PREPARED = "prepared";
+    private static final String ATTR_SEALED = "sealed";
+    private static final String ATTR_MODE = "mode";
+    private static final String ATTR_INSTALL_FLAGS = "installFlags";
+    private static final String ATTR_INSTALL_LOCATION = "installLocation";
+    private static final String ATTR_SIZE_BYTES = "sizeBytes";
+    private static final String ATTR_APP_PACKAGE_NAME = "appPackageName";
+    @Deprecated
+    private static final String ATTR_APP_ICON = "appIcon";
+    private static final String ATTR_APP_LABEL = "appLabel";
+    private static final String ATTR_ORIGINATING_URI = "originatingUri";
+    private static final String ATTR_ORIGINATING_UID = "originatingUid";
+    private static final String ATTR_REFERRER_URI = "referrerUri";
+    private static final String ATTR_ABI_OVERRIDE = "abiOverride";
+    private static final String ATTR_VOLUME_UUID = "volumeUuid";
+    private static final String ATTR_NAME = "name";
+    private static final String ATTR_INSTALL_REASON = "installRason";
 
     /** Automatically destroy sessions older than this */
     private static final long MAX_AGE_MILLIS = 3 * DateUtils.DAY_IN_MILLIS;
@@ -318,10 +357,8 @@
             while ((type = in.next()) != END_DOCUMENT) {
                 if (type == START_TAG) {
                     final String tag = in.getName();
-                    if (PackageInstallerSession.TAG_SESSION.equals(tag)) {
-                        final PackageInstallerSession session = PackageInstallerSession.
-                                readFromXml(in, mInternalCallback, mContext, mPm,
-                                        mInstallThread.getLooper(), mSessionsDir);
+                    if (TAG_SESSION.equals(tag)) {
+                        final PackageInstallerSession session = readSessionLocked(in);
                         final long age = System.currentTimeMillis() - session.createdMillis;
 
                         final boolean valid;
@@ -360,10 +397,53 @@
         session.dump(pw);
         mHistoricalSessions.add(writer.toString());
 
-        int installerUid = session.getInstallerUid();
         // Increment the number of sessions by this installerUid.
-        mHistoricalSessionsByInstaller.put(installerUid,
-                mHistoricalSessionsByInstaller.get(installerUid) + 1);
+        mHistoricalSessionsByInstaller.put(
+                session.installerUid,
+                mHistoricalSessionsByInstaller.get(session.installerUid) + 1);
+    }
+
+    private PackageInstallerSession readSessionLocked(XmlPullParser in) throws IOException,
+            XmlPullParserException {
+        final int sessionId = readIntAttribute(in, ATTR_SESSION_ID);
+        final int userId = readIntAttribute(in, ATTR_USER_ID);
+        final String installerPackageName = readStringAttribute(in, ATTR_INSTALLER_PACKAGE_NAME);
+        final int installerUid = readIntAttribute(in, ATTR_INSTALLER_UID, mPm.getPackageUid(
+                installerPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, userId));
+        final long createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
+        final String stageDirRaw = readStringAttribute(in, ATTR_SESSION_STAGE_DIR);
+        final File stageDir = (stageDirRaw != null) ? new File(stageDirRaw) : null;
+        final String stageCid = readStringAttribute(in, ATTR_SESSION_STAGE_CID);
+        final boolean prepared = readBooleanAttribute(in, ATTR_PREPARED, true);
+        final boolean sealed = readBooleanAttribute(in, ATTR_SEALED);
+
+        final SessionParams params = new SessionParams(
+                SessionParams.MODE_INVALID);
+        params.mode = readIntAttribute(in, ATTR_MODE);
+        params.installFlags = readIntAttribute(in, ATTR_INSTALL_FLAGS);
+        params.installLocation = readIntAttribute(in, ATTR_INSTALL_LOCATION);
+        params.sizeBytes = readLongAttribute(in, ATTR_SIZE_BYTES);
+        params.appPackageName = readStringAttribute(in, ATTR_APP_PACKAGE_NAME);
+        params.appIcon = readBitmapAttribute(in, ATTR_APP_ICON);
+        params.appLabel = readStringAttribute(in, ATTR_APP_LABEL);
+        params.originatingUri = readUriAttribute(in, ATTR_ORIGINATING_URI);
+        params.originatingUid =
+                readIntAttribute(in, ATTR_ORIGINATING_UID, SessionParams.UID_UNKNOWN);
+        params.referrerUri = readUriAttribute(in, ATTR_REFERRER_URI);
+        params.abiOverride = readStringAttribute(in, ATTR_ABI_OVERRIDE);
+        params.volumeUuid = readStringAttribute(in, ATTR_VOLUME_UUID);
+        params.grantedRuntimePermissions = readGrantedRuntimePermissions(in);
+        params.installReason = readIntAttribute(in, ATTR_INSTALL_REASON);
+
+        final File appIconFile = buildAppIconFile(sessionId);
+        if (appIconFile.exists()) {
+            params.appIcon = BitmapFactory.decodeFile(appIconFile.getAbsolutePath());
+            params.appIconLastModified = appIconFile.lastModified();
+        }
+
+        return new PackageInstallerSession(mInternalCallback, mContext, mPm,
+                mInstallThread.getLooper(), sessionId, userId, installerPackageName, installerUid,
+                params, createdMillis, stageDir, stageCid, prepared, sealed);
     }
 
     private void writeSessionsLocked() {
@@ -380,7 +460,7 @@
             final int size = mSessions.size();
             for (int i = 0; i < size; i++) {
                 final PackageInstallerSession session = mSessions.valueAt(i);
-                session.write(out, mSessionsDir);
+                writeSessionLocked(out, session);
             }
             out.endTag(null, TAG_SESSIONS);
             out.endDocument();
@@ -393,6 +473,106 @@
         }
     }
 
+    private void writeSessionLocked(XmlSerializer out, PackageInstallerSession session)
+            throws IOException {
+        final SessionParams params = session.params;
+
+        out.startTag(null, TAG_SESSION);
+
+        writeIntAttribute(out, ATTR_SESSION_ID, session.sessionId);
+        writeIntAttribute(out, ATTR_USER_ID, session.userId);
+        writeStringAttribute(out, ATTR_INSTALLER_PACKAGE_NAME,
+                session.installerPackageName);
+        writeIntAttribute(out, ATTR_INSTALLER_UID, session.installerUid);
+        writeLongAttribute(out, ATTR_CREATED_MILLIS, session.createdMillis);
+        if (session.stageDir != null) {
+            writeStringAttribute(out, ATTR_SESSION_STAGE_DIR,
+                    session.stageDir.getAbsolutePath());
+        }
+        if (session.stageCid != null) {
+            writeStringAttribute(out, ATTR_SESSION_STAGE_CID, session.stageCid);
+        }
+        writeBooleanAttribute(out, ATTR_PREPARED, session.isPrepared());
+        writeBooleanAttribute(out, ATTR_SEALED, session.isSealed());
+
+        writeIntAttribute(out, ATTR_MODE, params.mode);
+        writeIntAttribute(out, ATTR_INSTALL_FLAGS, params.installFlags);
+        writeIntAttribute(out, ATTR_INSTALL_LOCATION, params.installLocation);
+        writeLongAttribute(out, ATTR_SIZE_BYTES, params.sizeBytes);
+        writeStringAttribute(out, ATTR_APP_PACKAGE_NAME, params.appPackageName);
+        writeStringAttribute(out, ATTR_APP_LABEL, params.appLabel);
+        writeUriAttribute(out, ATTR_ORIGINATING_URI, params.originatingUri);
+        writeIntAttribute(out, ATTR_ORIGINATING_UID, params.originatingUid);
+        writeUriAttribute(out, ATTR_REFERRER_URI, params.referrerUri);
+        writeStringAttribute(out, ATTR_ABI_OVERRIDE, params.abiOverride);
+        writeStringAttribute(out, ATTR_VOLUME_UUID, params.volumeUuid);
+        writeIntAttribute(out, ATTR_INSTALL_REASON, params.installReason);
+
+        // Persist app icon if changed since last written
+        final File appIconFile = buildAppIconFile(session.sessionId);
+        if (params.appIcon == null && appIconFile.exists()) {
+            appIconFile.delete();
+        } else if (params.appIcon != null
+                && appIconFile.lastModified() != params.appIconLastModified) {
+            if (LOGD) Slog.w(TAG, "Writing changed icon " + appIconFile);
+            FileOutputStream os = null;
+            try {
+                os = new FileOutputStream(appIconFile);
+                params.appIcon.compress(CompressFormat.PNG, 90, os);
+            } catch (IOException e) {
+                Slog.w(TAG, "Failed to write icon " + appIconFile + ": " + e.getMessage());
+            } finally {
+                IoUtils.closeQuietly(os);
+            }
+
+            params.appIconLastModified = appIconFile.lastModified();
+        }
+
+        writeGrantedRuntimePermissions(out, params.grantedRuntimePermissions);
+
+        out.endTag(null, TAG_SESSION);
+    }
+
+    private static void writeGrantedRuntimePermissions(XmlSerializer out,
+            String[] grantedRuntimePermissions) throws IOException {
+        if (grantedRuntimePermissions != null) {
+            for (String permission : grantedRuntimePermissions) {
+                out.startTag(null, TAG_GRANTED_RUNTIME_PERMISSION);
+                writeStringAttribute(out, ATTR_NAME, permission);
+                out.endTag(null, TAG_GRANTED_RUNTIME_PERMISSION);
+            }
+        }
+    }
+
+    private static String[] readGrantedRuntimePermissions(XmlPullParser in)
+            throws IOException, XmlPullParserException {
+        List<String> permissions = null;
+
+        final int outerDepth = in.getDepth();
+        int type;
+        while ((type = in.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || in.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+            if (TAG_GRANTED_RUNTIME_PERMISSION.equals(in.getName())) {
+                String permission = readStringAttribute(in, ATTR_NAME);
+                if (permissions == null) {
+                    permissions = new ArrayList<>();
+                }
+                permissions.add(permission);
+            }
+        }
+
+        if (permissions == null) {
+            return null;
+        }
+
+        String[] permissionsArray = new String[permissions.size()];
+        permissions.toArray(permissionsArray);
+        return permissionsArray;
+    }
+
     private File buildAppIconFile(int sessionId) {
         return new File(mSessionsDir, "app_icon." + sessionId + ".png");
     }
@@ -705,11 +885,9 @@
         synchronized (mSessions) {
             for (int i = 0; i < mSessions.size(); i++) {
                 final PackageInstallerSession session = mSessions.valueAt(i);
-
-                SessionInfo info = session.generateInfo(false);
-                if (Objects.equals(info.getInstallerPackageName(), installerPackageName)
+                if (Objects.equals(session.installerPackageName, installerPackageName)
                         && session.userId == userId) {
-                    result.add(info);
+                    result.add(session.generateInfo(false));
                 }
             }
         }
@@ -784,7 +962,7 @@
         final int size = sessions.size();
         for (int i = 0; i < size; i++) {
             final PackageInstallerSession session = sessions.valueAt(i);
-            if (session.getInstallerUid() == installerUid) {
+            if (session.installerUid == installerUid) {
                 count++;
             }
         }
@@ -796,7 +974,7 @@
         if (callingUid == Process.ROOT_UID) {
             return true;
         } else {
-            return (session != null) && (callingUid == session.getInstallerUid());
+            return (session != null) && (callingUid == session.installerUid);
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 0fd696f..5823771 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -25,22 +25,9 @@
 import static android.system.OsConstants.O_RDONLY;
 import static android.system.OsConstants.O_WRONLY;
 
-import static com.android.internal.util.XmlUtils.readBitmapAttribute;
-import static com.android.internal.util.XmlUtils.readBooleanAttribute;
-import static com.android.internal.util.XmlUtils.readIntAttribute;
-import static com.android.internal.util.XmlUtils.readLongAttribute;
-import static com.android.internal.util.XmlUtils.readStringAttribute;
-import static com.android.internal.util.XmlUtils.readUriAttribute;
-import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
-import static com.android.internal.util.XmlUtils.writeIntAttribute;
-import static com.android.internal.util.XmlUtils.writeLongAttribute;
-import static com.android.internal.util.XmlUtils.writeStringAttribute;
-import static com.android.internal.util.XmlUtils.writeUriAttribute;
 import static com.android.server.pm.PackageInstallerService.prepareExternalStageCid;
 import static com.android.server.pm.PackageInstallerService.prepareStageDir;
 
-import android.Manifest;
-import android.annotation.NonNull;
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.Intent;
@@ -58,8 +45,6 @@
 import android.content.pm.PackageParser.PackageLite;
 import android.content.pm.PackageParser.PackageParserException;
 import android.content.pm.Signature;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.FileBridge;
@@ -68,7 +53,6 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
-import android.os.ParcelableException;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.RevocableFileDescriptor;
@@ -96,14 +80,9 @@
 import libcore.io.IoUtils;
 import libcore.io.Libcore;
 
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileFilter;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.security.cert.Certificate;
 import java.util.ArrayList;
@@ -118,34 +97,6 @@
 
     private static final int MSG_COMMIT = 0;
 
-    /** XML constants used for persisting a session */
-    static final String TAG_SESSION = "session";
-    private static final String TAG_GRANTED_RUNTIME_PERMISSION = "granted-runtime-permission";
-    private static final String ATTR_SESSION_ID = "sessionId";
-    private static final String ATTR_USER_ID = "userId";
-    private static final String ATTR_INSTALLER_PACKAGE_NAME = "installerPackageName";
-    private static final String ATTR_INSTALLER_UID = "installerUid";
-    private static final String ATTR_CREATED_MILLIS = "createdMillis";
-    private static final String ATTR_SESSION_STAGE_DIR = "sessionStageDir";
-    private static final String ATTR_SESSION_STAGE_CID = "sessionStageCid";
-    private static final String ATTR_PREPARED = "prepared";
-    private static final String ATTR_SEALED = "sealed";
-    private static final String ATTR_MODE = "mode";
-    private static final String ATTR_INSTALL_FLAGS = "installFlags";
-    private static final String ATTR_INSTALL_LOCATION = "installLocation";
-    private static final String ATTR_SIZE_BYTES = "sizeBytes";
-    private static final String ATTR_APP_PACKAGE_NAME = "appPackageName";
-    @Deprecated
-    private static final String ATTR_APP_ICON = "appIcon";
-    private static final String ATTR_APP_LABEL = "appLabel";
-    private static final String ATTR_ORIGINATING_URI = "originatingUri";
-    private static final String ATTR_ORIGINATING_UID = "originatingUid";
-    private static final String ATTR_REFERRER_URI = "referrerUri";
-    private static final String ATTR_ABI_OVERRIDE = "abiOverride";
-    private static final String ATTR_VOLUME_UUID = "volumeUuid";
-    private static final String ATTR_NAME = "name";
-    private static final String ATTR_INSTALL_REASON = "installRason";
-
     // TODO: enforce INSTALL_ALLOW_TEST
     // TODO: enforce INSTALL_ALLOW_DOWNGRADE
 
@@ -153,9 +104,12 @@
     private final Context mContext;
     private final PackageManagerService mPm;
     private final Handler mHandler;
+    private final boolean mIsInstallerDeviceOwner;
 
     final int sessionId;
     final int userId;
+    final String installerPackageName;
+    final int installerUid;
     final SessionParams params;
     final long createdMillis;
     final int defaultContainerGid;
@@ -168,17 +122,6 @@
 
     private final Object mLock = new Object();
 
-    /** Uid of the creator of this session. */
-    private final int mOriginalInstallerUid;
-
-    /** Package of the owner of the installer session */
-    @GuardedBy("mLock")
-    private String mInstallerPackageName;
-
-    /** Uid of the owner of the installer session */
-    @GuardedBy("mLock")
-    private int mInstallerUid;
-
     @GuardedBy("mLock")
     private float mClientProgress = 0;
     @GuardedBy("mLock")
@@ -189,25 +132,18 @@
     @GuardedBy("mLock")
     private float mReportedProgress = -1;
 
-    /** State of the session. */
     @GuardedBy("mLock")
     private boolean mPrepared = false;
     @GuardedBy("mLock")
     private boolean mSealed = false;
     @GuardedBy("mLock")
-    private boolean mCommitted = false;
+    private boolean mPermissionsAccepted = false;
     @GuardedBy("mLock")
     private boolean mRelinquished = false;
     @GuardedBy("mLock")
     private boolean mDestroyed = false;
 
-    /** Permissions have been accepted by the user (see {@link #setPermissionsResult}) */
-    @GuardedBy("mLock")
-    private boolean mPermissionsManuallyAccepted = false;
-
-    @GuardedBy("mLock")
     private int mFinalStatus;
-    @GuardedBy("mLock")
     private String mFinalMessage;
 
     @GuardedBy("mLock")
@@ -219,13 +155,9 @@
     private IPackageInstallObserver2 mRemoteObserver;
 
     /** Fields derived from commit parsing */
-    @GuardedBy("mLock")
     private String mPackageName;
-    @GuardedBy("mLock")
     private int mVersionCode;
-    @GuardedBy("mLock")
     private Signature[] mSignatures;
-    @GuardedBy("mLock")
     private Certificate[][] mCertificates;
 
     /**
@@ -273,61 +205,32 @@
     private final Handler.Callback mHandlerCallback = new Handler.Callback() {
         @Override
         public boolean handleMessage(Message msg) {
+            // Cache package manager data without the lock held
+            final PackageInfo pkgInfo = mPm.getPackageInfo(
+                    params.appPackageName, PackageManager.GET_SIGNATURES
+                            | PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
+            final ApplicationInfo appInfo = mPm.getApplicationInfo(
+                    params.appPackageName, 0, userId);
+
             synchronized (mLock) {
                 if (msg.obj != null) {
                     mRemoteObserver = (IPackageInstallObserver2) msg.obj;
                 }
+
                 try {
-                    commitLocked();
+                    commitLocked(pkgInfo, appInfo);
                 } catch (PackageManagerException e) {
                     final String completeMsg = ExceptionUtils.getCompleteMessage(e);
                     Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
                     destroyInternal();
                     dispatchSessionFinished(e.error, completeMsg, null);
                 }
-            }
 
-            return true;
+                return true;
+            }
         }
     };
 
-    /**
-     * @return {@code true} iff the installing is app an device owner?
-     */
-    private boolean isInstallerDeviceOwnerLocked() {
-        DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
-                Context.DEVICE_POLICY_SERVICE);
-
-        return (dpm != null) && dpm.isDeviceOwnerAppOnCallingUser(
-                mInstallerPackageName);
-    }
-
-    /**
-     * Checks if the permissions still need to be confirmed.
-     *
-     * <p>This is dependant on the identity of the installer, hence this cannot be cached if the
-     * installer might still {@link #transfer(String) change}.
-     *
-     * @return {@code true} iff we need to ask to confirm the permissions?
-     */
-    private boolean needToAskForPermissionsLocked() {
-        if (mPermissionsManuallyAccepted) {
-            return false;
-        }
-
-        final boolean isPermissionGranted =
-                (mPm.checkUidPermission(android.Manifest.permission.INSTALL_PACKAGES,
-                        mInstallerUid) == PackageManager.PERMISSION_GRANTED);
-        final boolean isInstallerRoot = (mInstallerUid == Process.ROOT_UID);
-        final boolean forcePermissionPrompt =
-                (params.installFlags & PackageManager.INSTALL_FORCE_PERMISSION_PROMPT) != 0;
-
-        // Device owners are allowed to silently install packages, so the permission check is
-        // waived if the installer is the device owner.
-        return forcePermissionPrompt || !(isPermissionGranted || isInstallerRoot
-                || isInstallerDeviceOwnerLocked());
-    }
-
     public PackageInstallerSession(PackageInstallerService.InternalCallback callback,
             Context context, PackageManagerService pm, Looper looper, int sessionId, int userId,
             String installerPackageName, int installerUid, SessionParams params, long createdMillis,
@@ -339,9 +242,8 @@
 
         this.sessionId = sessionId;
         this.userId = userId;
-        mOriginalInstallerUid = installerUid;
-        mInstallerPackageName = installerPackageName;
-        mInstallerUid = installerUid;
+        this.installerPackageName = installerPackageName;
+        this.installerUid = installerUid;
         this.params = params;
         this.createdMillis = createdMillis;
         this.stageDir = stageDir;
@@ -355,6 +257,26 @@
         mPrepared = prepared;
         mSealed = sealed;
 
+        // Device owners are allowed to silently install packages, so the permission check is
+        // waived if the installer is the device owner.
+        DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+        final boolean isPermissionGranted =
+                (mPm.checkUidPermission(android.Manifest.permission.INSTALL_PACKAGES, installerUid)
+                        == PackageManager.PERMISSION_GRANTED);
+        final boolean isInstallerRoot = (installerUid == Process.ROOT_UID);
+        final boolean forcePermissionPrompt =
+                (params.installFlags & PackageManager.INSTALL_FORCE_PERMISSION_PROMPT) != 0;
+        mIsInstallerDeviceOwner = (dpm != null) && dpm.isDeviceOwnerAppOnCallingUser(
+                installerPackageName);
+        if ((isPermissionGranted
+                        || isInstallerRoot
+                        || mIsInstallerDeviceOwner)
+                && !forcePermissionPrompt) {
+            mPermissionsAccepted = true;
+        } else {
+            mPermissionsAccepted = false;
+        }
         final long identity = Binder.clearCallingIdentity();
         try {
             final int uid = mPm.getPackageUid(PackageManagerService.DEFAULT_CONTAINER_PACKAGE,
@@ -373,7 +295,7 @@
         final SessionInfo info = new SessionInfo();
         synchronized (mLock) {
             info.sessionId = sessionId;
-            info.installerPackageName = mInstallerPackageName;
+            info.installerPackageName = installerPackageName;
             info.resolvedBaseCodePath = (mResolvedBaseFile != null) ?
                     mResolvedBaseFile.getAbsolutePath() : null;
             info.progress = mProgress;
@@ -388,13 +310,6 @@
                 info.appIcon = params.appIcon;
             }
             info.appLabel = params.appLabel;
-
-            info.installLocation = params.installLocation;
-            info.originatingUri = params.originatingUri;
-            info.originatingUid = params.originatingUid;
-            info.referrerUri = params.referrerUri;
-            info.grantedRuntimePermissions = params.grantedRuntimePermissions;
-            info.installFlags = params.installFlags;
         }
         return info;
     }
@@ -411,26 +326,14 @@
         }
     }
 
-    private void assertPreparedAndNotSealedLocked(String cookie) {
-        assertPreparedAndNotCommittedOrDestroyedLocked(cookie);
-        if (mSealed) {
-            throw new SecurityException(cookie + " not allowed after sealing");
-        }
-    }
-
-    private void assertPreparedAndNotCommittedOrDestroyedLocked(String cookie) {
-        assertPreparedAndNotDestroyedLocked(cookie);
-        if (mCommitted) {
-            throw new SecurityException(cookie + " not allowed after commit");
-        }
-    }
-
-    private void assertPreparedAndNotDestroyedLocked(String cookie) {
-        if (!mPrepared) {
-            throw new IllegalStateException(cookie + " before prepared");
-        }
-        if (mDestroyed) {
-            throw new SecurityException(cookie + " not allowed after destruction");
+    private void assertPreparedAndNotSealed(String cookie) {
+        synchronized (mLock) {
+            if (!mPrepared) {
+                throw new IllegalStateException(cookie + " before prepared");
+            }
+            if (mSealed) {
+                throw new SecurityException(cookie + " not allowed after commit");
+            }
         }
     }
 
@@ -439,27 +342,27 @@
      * might point at an ASEC mount point, which is why we delay path resolution
      * until someone actively works with the session.
      */
-    private File resolveStageDirLocked() throws IOException {
-        if (mResolvedStageDir == null) {
-            if (stageDir != null) {
-                mResolvedStageDir = stageDir;
-            } else {
-                final String path = PackageHelper.getSdDir(stageCid);
-                if (path != null) {
-                    mResolvedStageDir = new File(path);
+    private File resolveStageDir() throws IOException {
+        synchronized (mLock) {
+            if (mResolvedStageDir == null) {
+                if (stageDir != null) {
+                    mResolvedStageDir = stageDir;
                 } else {
-                    throw new IOException("Failed to resolve path to container " + stageCid);
+                    final String path = PackageHelper.getSdDir(stageCid);
+                    if (path != null) {
+                        mResolvedStageDir = new File(path);
+                    } else {
+                        throw new IOException("Failed to resolve path to container " + stageCid);
+                    }
                 }
             }
+            return mResolvedStageDir;
         }
-        return mResolvedStageDir;
     }
 
     @Override
     public void setClientProgress(float progress) {
         synchronized (mLock) {
-            assertCallerIsOwnerOrRootLocked();
-
             // Always publish first staging movement
             final boolean forcePublish = (mClientProgress == 0);
             mClientProgress = progress;
@@ -470,8 +373,6 @@
     @Override
     public void addClientProgress(float progress) {
         synchronized (mLock) {
-            assertCallerIsOwnerOrRootLocked();
-
             setClientProgress(mClientProgress + progress);
         }
     }
@@ -489,15 +390,11 @@
 
     @Override
     public String[] getNames() {
-        synchronized (mLock) {
-            assertCallerIsOwnerOrRootLocked();
-            assertPreparedAndNotCommittedOrDestroyedLocked("getNames");
-
-            try {
-                return resolveStageDirLocked().list();
-            } catch (IOException e) {
-                throw ExceptionUtils.wrap(e);
-            }
+        assertPreparedAndNotSealed("getNames");
+        try {
+            return resolveStageDir().list();
+        } catch (IOException e) {
+            throw ExceptionUtils.wrap(e);
         }
     }
 
@@ -506,26 +403,20 @@
         if (TextUtils.isEmpty(params.appPackageName)) {
             throw new IllegalStateException("Must specify package name to remove a split");
         }
-
-        synchronized (mLock) {
-            assertCallerIsOwnerOrRootLocked();
-            assertPreparedAndNotCommittedOrDestroyedLocked("removeSplit");
-
-            try {
-                createRemoveSplitMarkerLocked(splitName);
-            } catch (IOException e) {
-                throw ExceptionUtils.wrap(e);
-            }
+        try {
+            createRemoveSplitMarker(splitName);
+        } catch (IOException e) {
+            throw ExceptionUtils.wrap(e);
         }
     }
 
-    private void createRemoveSplitMarkerLocked(String splitName) throws IOException {
+    private void createRemoveSplitMarker(String splitName) throws IOException {
         try {
             final String markerName = splitName + REMOVE_SPLIT_MARKER_EXTENSION;
             if (!FileUtils.isValidExtFilename(markerName)) {
                 throw new IllegalArgumentException("Invalid marker: " + markerName);
             }
-            final File target = new File(resolveStageDirLocked(), markerName);
+            final File target = new File(resolveStageDir(), markerName);
             target.createNewFile();
             Os.chmod(target.getAbsolutePath(), 0 /*mode*/);
         } catch (ErrnoException e) {
@@ -549,10 +440,8 @@
         // will block any attempted install transitions.
         final RevocableFileDescriptor fd;
         final FileBridge bridge;
-        final File stageDir;
         synchronized (mLock) {
-            assertCallerIsOwnerOrRootLocked();
-            assertPreparedAndNotSealedLocked("openWrite");
+            assertPreparedAndNotSealed("openWrite");
 
             if (PackageInstaller.ENABLE_REVOCABLE_FD) {
                 fd = new RevocableFileDescriptor();
@@ -563,8 +452,6 @@
                 bridge = new FileBridge();
                 mBridges.add(bridge);
             }
-
-            stageDir = resolveStageDirLocked();
         }
 
         try {
@@ -575,7 +462,7 @@
             final File target;
             final long identity = Binder.clearCallingIdentity();
             try {
-                target = new File(stageDir, name);
+                target = new File(resolveStageDir(), name);
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -613,108 +500,55 @@
 
     @Override
     public ParcelFileDescriptor openRead(String name) {
-        synchronized (mLock) {
-            assertCallerIsOwnerOrRootLocked();
-            assertPreparedAndNotCommittedOrDestroyedLocked("openRead");
-            try {
-                return openReadInternalLocked(name);
-            } catch (IOException e) {
-                throw ExceptionUtils.wrap(e);
-            }
+        try {
+            return openReadInternal(name);
+        } catch (IOException e) {
+            throw ExceptionUtils.wrap(e);
         }
     }
 
-    private ParcelFileDescriptor openReadInternalLocked(String name) throws IOException {
+    private ParcelFileDescriptor openReadInternal(String name) throws IOException {
+        assertPreparedAndNotSealed("openRead");
+
         try {
             if (!FileUtils.isValidExtFilename(name)) {
                 throw new IllegalArgumentException("Invalid name: " + name);
             }
-            final File target = new File(resolveStageDirLocked(), name);
+            final File target = new File(resolveStageDir(), name);
+
             final FileDescriptor targetFd = Libcore.os.open(target.getAbsolutePath(), O_RDONLY, 0);
             return new ParcelFileDescriptor(targetFd);
+
         } catch (ErrnoException e) {
             throw e.rethrowAsIOException();
         }
     }
 
-    /**
-     * Check if the caller is the owner of this session. Otherwise throw a
-     * {@link SecurityException}.
-     */
-    private void assertCallerIsOwnerOrRootLocked() {
-        final int callingUid = Binder.getCallingUid();
-        if (callingUid != Process.ROOT_UID && callingUid != mInstallerUid) {
-            throw new SecurityException("Session does not belong to uid " + callingUid);
-        }
-    }
-
-    /**
-     * If anybody is reading or writing data of the session, throw an {@link SecurityException}.
-     */
-    private void assertNoWriteFileTransfersOpenLocked() {
-        // Verify that all writers are hands-off
-        for (RevocableFileDescriptor fd : mFds) {
-            if (!fd.isRevoked()) {
-                throw new SecurityException("Files still open");
-            }
-        }
-        for (FileBridge bridge : mBridges) {
-            if (!bridge.isClosed()) {
-                throw new SecurityException("Files still open");
-            }
-        }
-    }
-
     @Override
-    public void commit(IntentSender statusReceiver, boolean forTransfer) {
+    public void commit(IntentSender statusReceiver) {
         Preconditions.checkNotNull(statusReceiver);
 
-        // Cache package manager data without the lock held
-        final PackageInfo installedPkgInfo = mPm.getPackageInfo(
-                params.appPackageName, PackageManager.GET_SIGNATURES
-                        | PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
-
         final boolean wasSealed;
         synchronized (mLock) {
-            assertCallerIsOwnerOrRootLocked();
-            assertPreparedAndNotDestroyedLocked("commit");
-
-            if (forTransfer) {
-                mContext.enforceCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES, null);
-
-                if (mInstallerUid == mOriginalInstallerUid) {
-                    throw new IllegalArgumentException("Session has not been transferred");
-                }
-            } else {
-                if (mInstallerUid != mOriginalInstallerUid) {
-                    throw new IllegalArgumentException("Session has been transferred");
-                }
-            }
-
             wasSealed = mSealed;
             if (!mSealed) {
-                try {
-                    sealAndValidateLocked(installedPkgInfo);
-                } catch (PackageManagerException e) {
-                    // Do now throw an exception here to stay compatible with O and older
-                    destroyInternal();
-                    dispatchSessionFinished(e.error, ExceptionUtils.getCompleteMessage(e), null);
-                    return;
+                // Verify that all writers are hands-off
+                for (RevocableFileDescriptor fd : mFds) {
+                    if (!fd.isRevoked()) {
+                        throw new SecurityException("Files still open");
+                    }
                 }
+                for (FileBridge bridge : mBridges) {
+                    if (!bridge.isClosed()) {
+                        throw new SecurityException("Files still open");
+                    }
+                }
+                mSealed = true;
             }
 
             // Client staging is fully done at this point
             mClientProgress = 1f;
             computeProgressLocked(true);
-
-            // This ongoing commit should keep session active, even though client
-            // will probably close their end.
-            mActiveCount.incrementAndGet();
-
-            mCommitted = true;
-            final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(
-                    mContext, statusReceiver, sessionId, isInstallerDeviceOwnerLocked(), userId);
-            mHandler.obtainMessage(MSG_COMMIT, adapter.getBinder()).sendToTarget();
         }
 
         if (!wasSealed) {
@@ -723,82 +557,17 @@
             // the session lock, since otherwise it's a lock inversion.
             mCallback.onSessionSealedBlocking(this);
         }
+
+        // This ongoing commit should keep session active, even though client
+        // will probably close their end.
+        mActiveCount.incrementAndGet();
+
+        final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(mContext,
+                statusReceiver, sessionId, mIsInstallerDeviceOwner, userId);
+        mHandler.obtainMessage(MSG_COMMIT, adapter.getBinder()).sendToTarget();
     }
 
-    /**
-     * Seal the session to prevent further modification and validate the contents of it.
-     *
-     * <p>The session will be sealed after calling this method even if it failed.
-     *
-     * @param pkgInfo The package info for {@link #params}.packagename
-     */
-    private void sealAndValidateLocked(PackageInfo pkgInfo)
-            throws PackageManagerException {
-        assertNoWriteFileTransfersOpenLocked();
-
-        mSealed = true;
-
-        // Verify that stage looks sane with respect to existing application.
-        // This currently only ensures packageName, versionCode, and certificate
-        // consistency.
-        validateInstallLocked(pkgInfo);
-
-        // Read transfers from the original owner stay open, but as the session's data
-        // cannot be modified anymore, there is no leak of information.
-    }
-
-    @Override
-    public void transfer(String packageName) {
-        Preconditions.checkNotNull(packageName);
-
-        ApplicationInfo newOwnerAppInfo = mPm.getApplicationInfo(packageName, 0, userId);
-        if (newOwnerAppInfo == null) {
-            throw new ParcelableException(new PackageManager.NameNotFoundException(packageName));
-        }
-
-        if (PackageManager.PERMISSION_GRANTED != mPm.checkUidPermission(
-                Manifest.permission.INSTALL_PACKAGES, newOwnerAppInfo.uid)) {
-            throw new SecurityException("Destination package " + packageName + " does not have "
-                    + "the " + Manifest.permission.INSTALL_PACKAGES + " permission");
-        }
-
-        // Cache package manager data without the lock held
-        final PackageInfo installedPkgInfo = mPm.getPackageInfo(
-                params.appPackageName, PackageManager.GET_SIGNATURES
-                        | PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
-
-        // Only install flags that can be verified by the app the session is transferred to are
-        // allowed. The parameters can be read via PackageInstaller.SessionInfo.
-        if (!params.areHiddenOptionsSet()) {
-            throw new SecurityException("Can only transfer sessions that use public options");
-        }
-
-        synchronized (mLock) {
-            assertCallerIsOwnerOrRootLocked();
-            assertPreparedAndNotSealedLocked("transfer");
-
-            try {
-                sealAndValidateLocked(installedPkgInfo);
-            } catch (PackageManagerException e) {
-                throw new IllegalArgumentException("Package is not valid", e);
-            }
-
-            if (!mPackageName.equals(mInstallerPackageName)) {
-                throw new SecurityException("Can only transfer sessions that update the original "
-                        + "installer");
-            }
-
-            mInstallerPackageName = packageName;
-            mInstallerUid = newOwnerAppInfo.uid;
-        }
-
-        // Persist the fact that we've sealed ourselves to prevent
-        // mutations of any hard links we create. We do this without holding
-        // the session lock, since otherwise it's a lock inversion.
-        mCallback.onSessionSealedBlocking(this);
-    }
-
-    private void commitLocked()
+    private void commitLocked(PackageInfo pkgInfo, ApplicationInfo appInfo)
             throws PackageManagerException {
         if (mDestroyed) {
             throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session destroyed");
@@ -808,17 +577,22 @@
         }
 
         try {
-            resolveStageDirLocked();
+            resolveStageDir();
         } catch (IOException e) {
             throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
                     "Failed to resolve stage location", e);
         }
 
+        // Verify that stage looks sane with respect to existing application.
+        // This currently only ensures packageName, versionCode, and certificate
+        // consistency.
+        validateInstallLocked(pkgInfo, appInfo);
+
         Preconditions.checkNotNull(mPackageName);
         Preconditions.checkNotNull(mSignatures);
         Preconditions.checkNotNull(mResolvedBaseFile);
 
-        if (needToAskForPermissionsLocked()) {
+        if (!mPermissionsAccepted) {
             // User needs to accept permissions; give installer an intent they
             // can use to involve user.
             final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_PERMISSIONS);
@@ -848,7 +622,7 @@
         if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
             try {
                 final List<File> fromFiles = mResolvedInheritedFiles;
-                final File toDir = resolveStageDirLocked();
+                final File toDir = resolveStageDir();
 
                 if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
                 if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
@@ -909,7 +683,7 @@
 
         mRelinquished = true;
         mPm.installStage(mPackageName, stageDir, stageCid, localObserver, params,
-                mInstallerPackageName, mInstallerUid, user, mCertificates);
+                installerPackageName, installerUid, user, mCertificates);
     }
 
     /**
@@ -924,7 +698,8 @@
      * Note that upgrade compatibility is still performed by
      * {@link PackageManagerService}.
      */
-    private void validateInstallLocked(PackageInfo pkgInfo) throws PackageManagerException {
+    private void validateInstallLocked(PackageInfo pkgInfo, ApplicationInfo appInfo)
+            throws PackageManagerException {
         mPackageName = null;
         mVersionCode = -1;
         mSignatures = null;
@@ -977,7 +752,7 @@
                 mCertificates = apk.certificates;
             }
 
-            assertApkConsistentLocked(String.valueOf(addedFile), apk);
+            assertApkConsistent(String.valueOf(addedFile), apk);
 
             // Take this opportunity to enforce uniform naming
             final String targetName;
@@ -1032,14 +807,13 @@
 
         } else {
             // Partial installs must be consistent with existing install
-            if (pkgInfo == null || pkgInfo.applicationInfo == null) {
+            if (appInfo == null) {
                 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
                         "Missing existing base package for " + mPackageName);
             }
 
             final PackageLite existing;
             final ApkLite existingBase;
-            ApplicationInfo appInfo = pkgInfo.applicationInfo;
             try {
                 existing = PackageParser.parsePackageLite(new File(appInfo.getCodePath()), 0);
                 existingBase = PackageParser.parseApkLite(new File(appInfo.getBaseCodePath()),
@@ -1048,7 +822,7 @@
                 throw PackageManagerException.from(e);
             }
 
-            assertApkConsistentLocked("Existing base", existingBase);
+            assertApkConsistent("Existing base", existingBase);
 
             // Inherit base if not overridden
             if (mResolvedBaseFile == null) {
@@ -1104,7 +878,7 @@
         }
     }
 
-    private void assertApkConsistentLocked(String tag, ApkLite apk)
+    private void assertApkConsistent(String tag, ApkLite apk)
             throws PackageManagerException {
         if (!mPackageName.equals(apk.packageName)) {
             throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag + " package "
@@ -1185,15 +959,6 @@
         return true;
     }
 
-    /**
-     * @return the uid of the owner this session
-     */
-    public int getInstallerUid() {
-        synchronized (mLock) {
-            return mInstallerUid;
-        }
-    }
-
     private static String getRelativePath(File file, File base) throws IOException {
         final String pathStr = file.getAbsolutePath();
         final String baseStr = base.getAbsolutePath();
@@ -1341,9 +1106,9 @@
         if (accepted) {
             // Mark and kick off another install pass
             synchronized (mLock) {
-                mPermissionsManuallyAccepted = true;
-                mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
+                mPermissionsAccepted = true;
             }
+            mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
         } else {
             destroyInternal();
             dispatchSessionFinished(INSTALL_FAILED_ABORTED, "User rejected permissions", null);
@@ -1355,9 +1120,7 @@
             mCallback.onSessionActiveChanged(this, true);
         }
 
-        boolean wasPrepared;
         synchronized (mLock) {
-            wasPrepared = mPrepared;
             if (!mPrepared) {
                 if (stageDir != null) {
                     prepareStageDir(stageDir);
@@ -1378,20 +1141,13 @@
                 }
 
                 mPrepared = true;
+                mCallback.onSessionPrepared(this);
             }
         }
-
-        if (!wasPrepared) {
-            mCallback.onSessionPrepared(this);
-        }
     }
 
     @Override
     public void close() {
-        synchronized (mLock) {
-            assertCallerIsOwnerOrRootLocked();
-        }
-
         if (mActiveCount.decrementAndGet() == 0) {
             mCallback.onSessionActiveChanged(this, false);
         }
@@ -1399,33 +1155,21 @@
 
     @Override
     public void abandon() {
-        synchronized (mLock) {
-            assertCallerIsOwnerOrRootLocked();
-
-            if (mRelinquished) {
-                Slog.d(TAG, "Ignoring abandon after commit relinquished control");
-                return;
-            }
-            destroyInternal();
+        if (mRelinquished) {
+            Slog.d(TAG, "Ignoring abandon after commit relinquished control");
+            return;
         }
-
+        destroyInternal();
         dispatchSessionFinished(INSTALL_FAILED_ABORTED, "Session was abandoned", null);
     }
 
     private void dispatchSessionFinished(int returnCode, String msg, Bundle extras) {
-        IPackageInstallObserver2 observer;
-        String packageName;
-        synchronized (mLock) {
-            mFinalStatus = returnCode;
-            mFinalMessage = msg;
+        mFinalStatus = returnCode;
+        mFinalMessage = msg;
 
-            observer = mRemoteObserver;
-            packageName = mPackageName;
-        }
-
-        if (observer != null) {
+        if (mRemoteObserver != null) {
             try {
-                observer.onPackageInstalled(packageName, returnCode, msg, extras);
+                mRemoteObserver.onPackageInstalled(mPackageName, returnCode, msg, extras);
             } catch (RemoteException ignored) {
             }
         }
@@ -1476,9 +1220,8 @@
         pw.increaseIndent();
 
         pw.printPair("userId", userId);
-        pw.printPair("mOriginalInstallerUid", mOriginalInstallerUid);
-        pw.printPair("mInstallerPackageName", mInstallerPackageName);
-        pw.printPair("mInstallerUid", mInstallerUid);
+        pw.printPair("installerPackageName", installerPackageName);
+        pw.printPair("installerUid", installerUid);
         pw.printPair("createdMillis", createdMillis);
         pw.printPair("stageDir", stageDir);
         pw.printPair("stageCid", stageCid);
@@ -1489,7 +1232,7 @@
         pw.printPair("mClientProgress", mClientProgress);
         pw.printPair("mProgress", mProgress);
         pw.printPair("mSealed", mSealed);
-        pw.printPair("mPermissionsManuallyAccepted", mPermissionsManuallyAccepted);
+        pw.printPair("mPermissionsAccepted", mPermissionsAccepted);
         pw.printPair("mRelinquished", mRelinquished);
         pw.printPair("mDestroyed", mDestroyed);
         pw.printPair("mFds", mFds.size());
@@ -1500,170 +1243,4 @@
 
         pw.decreaseIndent();
     }
-
-    private static void writeGrantedRuntimePermissionsLocked(XmlSerializer out,
-            String[] grantedRuntimePermissions) throws IOException {
-        if (grantedRuntimePermissions != null) {
-            for (String permission : grantedRuntimePermissions) {
-                out.startTag(null, TAG_GRANTED_RUNTIME_PERMISSION);
-                writeStringAttribute(out, ATTR_NAME, permission);
-                out.endTag(null, TAG_GRANTED_RUNTIME_PERMISSION);
-            }
-        }
-    }
-
-    private static File buildAppIconFile(int sessionId, @NonNull File sessionsDir) {
-        return new File(sessionsDir, "app_icon." + sessionId + ".png");
-    }
-
-    /**
-     * Write this session to a {@link XmlSerializer}.
-     *
-     * @param out Where to write the session to
-     * @param sessionsDir The directory containing the sessions
-     */
-    void write(@NonNull XmlSerializer out, @NonNull File sessionsDir) throws IOException {
-        synchronized (mLock) {
-            out.startTag(null, TAG_SESSION);
-
-            writeIntAttribute(out, ATTR_SESSION_ID, sessionId);
-            writeIntAttribute(out, ATTR_USER_ID, userId);
-            writeStringAttribute(out, ATTR_INSTALLER_PACKAGE_NAME,
-                    mInstallerPackageName);
-            writeIntAttribute(out, ATTR_INSTALLER_UID, mInstallerUid);
-            writeLongAttribute(out, ATTR_CREATED_MILLIS, createdMillis);
-            if (stageDir != null) {
-                writeStringAttribute(out, ATTR_SESSION_STAGE_DIR,
-                        stageDir.getAbsolutePath());
-            }
-            if (stageCid != null) {
-                writeStringAttribute(out, ATTR_SESSION_STAGE_CID, stageCid);
-            }
-            writeBooleanAttribute(out, ATTR_PREPARED, isPrepared());
-            writeBooleanAttribute(out, ATTR_SEALED, isSealed());
-
-            writeIntAttribute(out, ATTR_MODE, params.mode);
-            writeIntAttribute(out, ATTR_INSTALL_FLAGS, params.installFlags);
-            writeIntAttribute(out, ATTR_INSTALL_LOCATION, params.installLocation);
-            writeLongAttribute(out, ATTR_SIZE_BYTES, params.sizeBytes);
-            writeStringAttribute(out, ATTR_APP_PACKAGE_NAME, params.appPackageName);
-            writeStringAttribute(out, ATTR_APP_LABEL, params.appLabel);
-            writeUriAttribute(out, ATTR_ORIGINATING_URI, params.originatingUri);
-            writeIntAttribute(out, ATTR_ORIGINATING_UID, params.originatingUid);
-            writeUriAttribute(out, ATTR_REFERRER_URI, params.referrerUri);
-            writeStringAttribute(out, ATTR_ABI_OVERRIDE, params.abiOverride);
-            writeStringAttribute(out, ATTR_VOLUME_UUID, params.volumeUuid);
-            writeIntAttribute(out, ATTR_INSTALL_REASON, params.installReason);
-
-            // Persist app icon if changed since last written
-            File appIconFile = buildAppIconFile(sessionId, sessionsDir);
-            if (params.appIcon == null && appIconFile.exists()) {
-                appIconFile.delete();
-            } else if (params.appIcon != null
-                    && appIconFile.lastModified() != params.appIconLastModified) {
-                if (LOGD) Slog.w(TAG, "Writing changed icon " + appIconFile);
-                FileOutputStream os = null;
-                try {
-                    os = new FileOutputStream(appIconFile);
-                    params.appIcon.compress(Bitmap.CompressFormat.PNG, 90, os);
-                } catch (IOException e) {
-                    Slog.w(TAG, "Failed to write icon " + appIconFile + ": " + e.getMessage());
-                } finally {
-                    IoUtils.closeQuietly(os);
-                }
-
-                params.appIconLastModified = appIconFile.lastModified();
-            }
-
-            writeGrantedRuntimePermissionsLocked(out, params.grantedRuntimePermissions);
-        }
-
-        out.endTag(null, TAG_SESSION);
-    }
-
-    private static String[] readGrantedRuntimePermissions(XmlPullParser in)
-            throws IOException, XmlPullParserException {
-        List<String> permissions = null;
-
-        final int outerDepth = in.getDepth();
-        int type;
-        while ((type = in.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || in.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-            if (TAG_GRANTED_RUNTIME_PERMISSION.equals(in.getName())) {
-                String permission = readStringAttribute(in, ATTR_NAME);
-                if (permissions == null) {
-                    permissions = new ArrayList<>();
-                }
-                permissions.add(permission);
-            }
-        }
-
-        if (permissions == null) {
-            return null;
-        }
-
-        String[] permissionsArray = new String[permissions.size()];
-        permissions.toArray(permissionsArray);
-        return permissionsArray;
-    }
-
-    /**
-     * Read new session from a {@link XmlPullParser xml description} and create it.
-     *
-     * @param in The source of the description
-     * @param callback Callback the session uses to notify about changes of it's state
-     * @param context Context to be used by the session
-     * @param pm PackageManager to use by the session
-     * @param installerThread Thread to be used for callbacks of this session
-     * @param sessionsDir The directory the sessions are stored in
-     *
-     * @return The newly created session
-     */
-    public static PackageInstallerSession readFromXml(@NonNull XmlPullParser in,
-            @NonNull PackageInstallerService.InternalCallback callback, @NonNull Context context,
-            @NonNull PackageManagerService pm, Looper installerThread, @NonNull File sessionsDir)
-            throws IOException, XmlPullParserException {
-        final int sessionId = readIntAttribute(in, ATTR_SESSION_ID);
-        final int userId = readIntAttribute(in, ATTR_USER_ID);
-        final String installerPackageName = readStringAttribute(in, ATTR_INSTALLER_PACKAGE_NAME);
-        final int installerUid = readIntAttribute(in, ATTR_INSTALLER_UID, pm.getPackageUid(
-                installerPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, userId));
-        final long createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
-        final String stageDirRaw = readStringAttribute(in, ATTR_SESSION_STAGE_DIR);
-        final File stageDir = (stageDirRaw != null) ? new File(stageDirRaw) : null;
-        final String stageCid = readStringAttribute(in, ATTR_SESSION_STAGE_CID);
-        final boolean prepared = readBooleanAttribute(in, ATTR_PREPARED, true);
-        final boolean sealed = readBooleanAttribute(in, ATTR_SEALED);
-
-        final SessionParams params = new SessionParams(
-                SessionParams.MODE_INVALID);
-        params.mode = readIntAttribute(in, ATTR_MODE);
-        params.installFlags = readIntAttribute(in, ATTR_INSTALL_FLAGS);
-        params.installLocation = readIntAttribute(in, ATTR_INSTALL_LOCATION);
-        params.sizeBytes = readLongAttribute(in, ATTR_SIZE_BYTES);
-        params.appPackageName = readStringAttribute(in, ATTR_APP_PACKAGE_NAME);
-        params.appIcon = readBitmapAttribute(in, ATTR_APP_ICON);
-        params.appLabel = readStringAttribute(in, ATTR_APP_LABEL);
-        params.originatingUri = readUriAttribute(in, ATTR_ORIGINATING_URI);
-        params.originatingUid =
-                readIntAttribute(in, ATTR_ORIGINATING_UID, SessionParams.UID_UNKNOWN);
-        params.referrerUri = readUriAttribute(in, ATTR_REFERRER_URI);
-        params.abiOverride = readStringAttribute(in, ATTR_ABI_OVERRIDE);
-        params.volumeUuid = readStringAttribute(in, ATTR_VOLUME_UUID);
-        params.grantedRuntimePermissions = readGrantedRuntimePermissions(in);
-        params.installReason = readIntAttribute(in, ATTR_INSTALL_REASON);
-
-        final File appIconFile = buildAppIconFile(sessionId, sessionsDir);
-        if (appIconFile.exists()) {
-            params.appIcon = BitmapFactory.decodeFile(appIconFile.getAbsolutePath());
-            params.appIconLastModified = appIconFile.lastModified();
-        }
-
-        return new PackageInstallerSession(callback, context, pm,
-                installerThread, sessionId, userId, installerPackageName, installerUid,
-                params, createdMillis, stageDir, stageCid, prepared, sealed);
-    }
 }