Merge "Move more fields to InstallSource."
diff --git a/services/core/java/com/android/server/pm/InstallSource.java b/services/core/java/com/android/server/pm/InstallSource.java
index b0cf525..990eba1 100644
--- a/services/core/java/com/android/server/pm/InstallSource.java
+++ b/services/core/java/com/android/server/pm/InstallSource.java
@@ -20,40 +20,103 @@
 
 import com.android.internal.util.IndentingPrintWriter;
 
+import java.util.Objects;
+
 /**
  * Immutable class holding information about where the request to install or update an app
  * came from.
  */
 final class InstallSource {
-    private static final InstallSource EMPTY = new InstallSource(null);
-
     /**
-     * The package that requested the installation, if known.
+     * An instance of InstallSource representing an absence of knowledge of the source of
+     * a package. Used in preference to null.
      */
+    static final InstallSource EMPTY = new InstallSource(null, null, false);
+
+    /** The package that requested the installation, if known. */
     @Nullable
     final String initiatingPackageName;
 
-    static InstallSource create(@Nullable String initiatingPackageName) {
-        return initiatingPackageName == null
-                ? EMPTY : new InstallSource(initiatingPackageName.intern());
+    /**
+     * Package name of the app that installed this package (the installer of record). Note that
+     * this may be modified.
+     */
+    @Nullable
+    final String installerPackageName;
+
+    /** Indicates if the package that was the installerPackageName has been uninstalled. */
+    final boolean isOrphaned;
+
+    static InstallSource create(@Nullable String initiatingPackageName,
+            @Nullable String installerPackageName) {
+        return create(initiatingPackageName, installerPackageName, false);
     }
 
-    private InstallSource(@Nullable String initiatingPackageName) {
+    static InstallSource create(@Nullable String initiatingPackageName,
+            @Nullable String installerPackageName, boolean isOrphaned) {
+        if (initiatingPackageName == null && installerPackageName == null && !isOrphaned) {
+            return EMPTY;
+        }
+        return new InstallSource(
+                initiatingPackageName == null ? null : initiatingPackageName.intern(),
+                installerPackageName == null ? null : installerPackageName.intern(),
+                isOrphaned);
+    }
+
+    private InstallSource(@Nullable String initiatingPackageName,
+            @Nullable String installerPackageName, boolean isOrphaned) {
         this.initiatingPackageName = initiatingPackageName;
+        this.isOrphaned = isOrphaned;
+        this.installerPackageName = installerPackageName;
     }
 
     void dump(IndentingPrintWriter pw) {
+        pw.printPair("installerPackageName", installerPackageName);
         pw.printPair("installInitiatingPackageName", initiatingPackageName);
     }
 
     /**
+     * Return an InstallSource the same as this one except with the specified installerPackageName.
+     */
+    InstallSource setInstallerPackage(String installerPackageName) {
+        return Objects.equals(installerPackageName, this.installerPackageName) ? this
+                : create(initiatingPackageName, installerPackageName, isOrphaned);
+    }
+
+    /**
+     * Return an InstallSource the same as this one except with the specified value for isOrphaned.
+     */
+    InstallSource setIsOrphaned(boolean isOrphaned) {
+        return isOrphaned == this.isOrphaned ? this
+                : create(initiatingPackageName, installerPackageName, isOrphaned);
+    }
+
+    /**
      * Return an InstallSource the same as this one except it does not refer to the specified
-     * installer package name.
+     * installer package name (which is being uninstalled).
      */
     InstallSource removeInstallerPackage(String packageName) {
-        if (packageName != null && packageName.equals(initiatingPackageName)) {
-            return create(null);
+        if (packageName == null) {
+            return this;
         }
-        return this;
+
+        boolean modified = false;
+        String initiatingPackageName = this.initiatingPackageName;
+        String installerPackageName = this.installerPackageName;
+        boolean isOrphaned = this.isOrphaned;
+
+        if (packageName.equals(initiatingPackageName)) {
+            initiatingPackageName = null;
+            modified = true;
+        }
+        if (packageName.equals(installerPackageName)) {
+            installerPackageName = null;
+            isOrphaned = true;
+            modified = true;
+        }
+
+        return modified
+                ? create(initiatingPackageName, installerPackageName, isOrphaned)
+                : this;
     }
 }
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index eca93bb..00c0566 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -623,10 +623,11 @@
                 stageCid = buildExternalStageCid(sessionId);
             }
         }
-        InstallSource installSource = InstallSource.create(installerPackageName);
+        InstallSource installSource = InstallSource.create(installerPackageName,
+                requestedInstallerPackageName);
         session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this,
-                mInstallThread.getLooper(), mStagingManager, sessionId, userId,
-                requestedInstallerPackageName, callingUid, installSource, params, createdMillis,
+                mInstallThread.getLooper(), mStagingManager, sessionId, userId, callingUid,
+                installSource, params, createdMillis,
                 stageDir, stageCid, false, false, false, null, SessionInfo.INVALID_ID,
                 false, false, false, SessionInfo.STAGED_SESSION_NO_ERROR, "");
 
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index d8bfa7d..feb1271 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -212,10 +212,6 @@
     /** Uid of the creator of this session. */
     private final int mOriginalInstallerUid;
 
-    /** Package of the owner of the installer session */
-    @GuardedBy("mLock")
-    private @Nullable String mInstallerPackageName;
-
     /** Uid of the owner of the installer session */
     @GuardedBy("mLock")
     private int mInstallerUid;
@@ -374,7 +370,8 @@
         }
         DevicePolicyManagerInternal dpmi =
                 LocalServices.getService(DevicePolicyManagerInternal.class);
-        return dpmi != null && dpmi.canSilentlyInstallPackage(mInstallerPackageName, mInstallerUid);
+        return dpmi != null && dpmi.canSilentlyInstallPackage(
+                mInstallSource.installerPackageName, mInstallerUid);
     }
 
     /**
@@ -418,8 +415,7 @@
     public PackageInstallerSession(PackageInstallerService.InternalCallback callback,
             Context context, PackageManagerService pm,
             PackageSessionProvider sessionProvider, Looper looper, StagingManager stagingManager,
-            int sessionId, int userId,
-            String installerPackageName, int installerUid, @NonNull InstallSource installSource,
+            int sessionId, int userId, int installerUid, @NonNull InstallSource installSource,
             SessionParams params, long createdMillis,
             File stageDir, String stageCid, boolean prepared, boolean committed, boolean sealed,
             @Nullable int[] childSessionIds, int parentSessionId, boolean isReady,
@@ -435,7 +431,6 @@
         this.sessionId = sessionId;
         this.userId = userId;
         mOriginalInstallerUid = installerUid;
-        mInstallerPackageName = installerPackageName;
         mInstallerUid = installerUid;
         mInstallSource = Preconditions.checkNotNull(installSource);
         this.params = params;
@@ -475,7 +470,7 @@
         synchronized (mLock) {
             info.sessionId = sessionId;
             info.userId = userId;
-            info.installerPackageName = mInstallerPackageName;
+            info.installerPackageName = mInstallSource.installerPackageName;
             info.resolvedBaseCodePath = (mResolvedBaseFile != null) ?
                     mResolvedBaseFile.getAbsolutePath() : null;
             info.progress = mProgress;
@@ -1226,14 +1221,13 @@
                 throw new IllegalArgumentException("Package is not valid", e);
             }
 
-            if (!mPackageName.equals(mInstallerPackageName)) {
+            if (!mPackageName.equals(mInstallSource.installerPackageName)) {
                 throw new SecurityException("Can only transfer sessions that update the original "
                         + "installer");
             }
 
-            mInstallerPackageName = packageName;
             mInstallerUid = newOwnerAppInfo.uid;
-            mInstallSource = InstallSource.create(packageName);
+            mInstallSource = InstallSource.create(packageName, packageName);
         }
 
         // Persist the fact that we've sealed ourselves to prevent
@@ -1246,7 +1240,7 @@
         if (isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked()) {
             DevicePolicyEventLogger
                     .createEvent(DevicePolicyEnums.INSTALL_PACKAGE)
-                    .setAdmin(mInstallerPackageName)
+                    .setAdmin(mInstallSource.installerPackageName)
                     .write();
         }
         if (params.isStaged) {
@@ -1452,8 +1446,7 @@
 
         mRelinquished = true;
         return new PackageManagerService.ActiveInstallSession(mPackageName, stageDir,
-                localObserver, params, mInstallerPackageName, mInstallerUid, mInstallSource, user,
-                mSigningDetails);
+                localObserver, params, mInstallerUid, mInstallSource, user, mSigningDetails);
     }
 
     private static void maybeRenameFile(File from, File to) throws PackageManagerException {
@@ -1902,7 +1895,7 @@
 
     String getInstallerPackageName() {
         synchronized (mLock) {
-            return mInstallerPackageName;
+            return mInstallSource.installerPackageName;
         }
     }
 
@@ -2343,9 +2336,8 @@
 
         pw.printPair("userId", userId);
         pw.printPair("mOriginalInstallerUid", mOriginalInstallerUid);
-        pw.printPair("mInstallerPackageName", mInstallerPackageName);
-        pw.printPair("mInstallerUid", mInstallerUid);
         mInstallSource.dump(pw);
+        pw.printPair("mInstallerUid", mInstallerUid);
         pw.printPair("createdMillis", createdMillis);
         pw.printPair("updatedMillis", updatedMillis);
         pw.printPair("stageDir", stageDir);
@@ -2424,7 +2416,7 @@
             writeIntAttribute(out, ATTR_SESSION_ID, sessionId);
             writeIntAttribute(out, ATTR_USER_ID, userId);
             writeStringAttribute(out, ATTR_INSTALLER_PACKAGE_NAME,
-                    mInstallerPackageName);
+                    mInstallSource.installerPackageName);
             writeIntAttribute(out, ATTR_INSTALLER_UID, mInstallerUid);
             writeStringAttribute(out, ATTR_INITIATING_PACKAGE_NAME,
                     mInstallSource.initiatingPackageName);
@@ -2626,10 +2618,11 @@
             childSessionIdsArray = EMPTY_CHILD_SESSION_ARRAY;
         }
 
-        InstallSource installSource = InstallSource.create(installInitiatingPackageName);
+        InstallSource installSource = InstallSource.create(installInitiatingPackageName,
+                installerPackageName);
         return new PackageInstallerSession(callback, context, pm, sessionProvider,
-                installerThread, stagingManager, sessionId, userId, installerPackageName,
-                installerUid, installSource, params, createdMillis, stageDir, stageCid,
+                installerThread, stagingManager, sessionId, userId, installerUid,
+                installSource, params, createdMillis, stageDir, stageCid,
                 prepared, committed, sealed, childSessionIdsArray, parentSessionId,
                 isReady, isFailed, isApplied, stagedSessionErrorCode, stagedSessionErrorMessage);
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d239dc4..0a4415b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1598,7 +1598,7 @@
                         handlePackagePostInstall(parentRes, grantPermissions,
                                 killApp, virtualPreload, grantedPermissions,
                                 whitelistedRestrictedPermissions, didRestore,
-                                args.installerPackageName, args.observer);
+                                args.installSource.installerPackageName, args.observer);
 
                         // Handle the child packages
                         final int childCount = (parentRes.addedChildPackages != null)
@@ -1608,7 +1608,7 @@
                             handlePackagePostInstall(childRes, grantPermissions,
                                     killApp, virtualPreload, grantedPermissions,
                                     whitelistedRestrictedPermissions, false /*didRestore*/,
-                                    args.installerPackageName, args.observer);
+                                    args.installSource.installerPackageName, args.observer);
                         }
 
                         // Log tracing if needed
@@ -10899,7 +10899,7 @@
         }
 
         if (isSystemApp(pkg)) {
-            pkgSetting.isOrphaned = true;
+            pkgSetting.setIsOrphaned(true);
         }
 
         // Take care of first install / last update times.
@@ -12382,7 +12382,7 @@
             int userId) {
         final PackageRemovedInfo info = new PackageRemovedInfo(this);
         info.removedPackage = packageName;
-        info.installerPackageName = pkgSetting.installerPackageName;
+        info.installerPackageName = pkgSetting.installSource.installerPackageName;
         info.removedUsers = new int[] {userId};
         info.broadcastUsers = new int[] {userId};
         info.uid = UserHandle.getUid(userId, pkgSetting.appId);
@@ -13404,9 +13404,11 @@
 
             // Verify: if target already has an installer package, it must
             // be signed with the same cert as the caller.
-            if (targetPackageSetting.installerPackageName != null) {
+            String targetInstallerPackageName =
+                    targetPackageSetting.installSource.installerPackageName;
+            if (targetInstallerPackageName != null) {
                 PackageSetting setting = mSettings.mPackages.get(
-                        targetPackageSetting.installerPackageName);
+                        targetInstallerPackageName);
                 // If the currently set package isn't valid, then it's always
                 // okay to change it.
                 if (setting != null) {
@@ -13415,13 +13417,13 @@
                             != PackageManager.SIGNATURE_MATCH) {
                         throw new SecurityException(
                                 "Caller does not have same cert as old installer package "
-                                + targetPackageSetting.installerPackageName);
+                                + targetInstallerPackageName);
                     }
                 }
             }
 
             // Okay!
-            targetPackageSetting.installerPackageName = installerPackageName;
+            targetPackageSetting.setInstallerPackageName(installerPackageName);
             if (installerPackageName != null) {
                 mSettings.mInstallerPackages.add(installerPackageName);
             }
@@ -13446,7 +13448,7 @@
                     ps, Binder.getCallingUid(), UserHandle.getCallingUserId())) {
                 throw new IllegalArgumentException("Unknown target package " + packageName);
             }
-            if (!Objects.equals(callerPackageName, ps.installerPackageName)) {
+            if (!Objects.equals(callerPackageName, ps.installSource.installerPackageName)) {
                 throw new IllegalArgumentException("Calling package " + callerPackageName
                         + " is not installer for " + packageName);
             }
@@ -13906,8 +13908,7 @@
         final MoveInfo move;
         final IPackageInstallObserver2 observer;
         int installFlags;
-        final String installerPackageName;
-        final InstallSource installSource;
+        @NonNull final InstallSource installSource;
         final String volumeUuid;
         private boolean mVerificationCompleted;
         private boolean mEnableRollbackCompleted;
@@ -13924,8 +13925,7 @@
         final long requiredInstalledVersionCode;
 
         InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
-                int installFlags, String installerPackageName,
-                InstallSource installSource, String volumeUuid,
+                int installFlags, InstallSource installSource, String volumeUuid,
                 VerificationInfo verificationInfo, UserHandle user, String packageAbiOverride,
                 String[] grantedPermissions, List<String> whitelistedRestrictedPermissions,
                 SigningDetails signingDetails, int installReason,
@@ -13935,8 +13935,7 @@
             this.move = move;
             this.observer = observer;
             this.installFlags = installFlags;
-            this.installerPackageName = installerPackageName;
-            this.installSource = installSource;
+            this.installSource = Preconditions.checkNotNull(installSource);
             this.volumeUuid = volumeUuid;
             this.verificationInfo = verificationInfo;
             this.packageAbiOverride = packageAbiOverride;
@@ -13962,12 +13961,12 @@
                     activeInstallSession.getInstallerUid());
             origin = OriginInfo.fromStagedFile(activeInstallSession.getStagedDir());
             move = null;
-            installReason = fixUpInstallReason(activeInstallSession.getInstallerPackageName(),
+            installReason = fixUpInstallReason(
+                    activeInstallSession.getInstallSource().installerPackageName,
                     activeInstallSession.getInstallerUid(),
                     activeInstallSession.getSessionParams().installReason);
             observer = activeInstallSession.getObserver();
             installFlags = activeInstallSession.getSessionParams().installFlags;
-            installerPackageName = activeInstallSession.getInstallerPackageName();
             installSource = activeInstallSession.getInstallSource();
             volumeUuid = activeInstallSession.getSessionParams().volumeUuid;
             packageAbiOverride = activeInstallSession.getSessionParams().abiOverride;
@@ -14219,7 +14218,7 @@
                     verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
 
                     verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
-                            installerPackageName);
+                            installSource.installerPackageName);
 
                     verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS,
                             installFlags);
@@ -14450,8 +14449,7 @@
         final IPackageInstallObserver2 observer;
         // Always refers to PackageManager flags only
         final int installFlags;
-        final String installerPackageName;
-        final InstallSource installSource;
+        @NonNull final InstallSource installSource;
         final String volumeUuid;
         final UserHandle user;
         final String abiOverride;
@@ -14470,8 +14468,7 @@
         /* nullable */ String[] instructionSets;
 
         InstallArgs(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
-                int installFlags, String installerPackageName,
-                InstallSource installSource, String volumeUuid,
+                int installFlags, InstallSource installSource, String volumeUuid,
                 UserHandle user, String[] instructionSets,
                 String abiOverride, String[] installGrantPermissions,
                 List<String> whitelistedRestrictedPermissions,
@@ -14482,8 +14479,7 @@
             this.move = move;
             this.installFlags = installFlags;
             this.observer = observer;
-            this.installerPackageName = installerPackageName;
-            this.installSource = installSource;
+            this.installSource = Preconditions.checkNotNull(installSource);
             this.volumeUuid = volumeUuid;
             this.user = user;
             this.instructionSets = instructionSets;
@@ -14500,7 +14496,7 @@
         /** New install */
         InstallArgs(InstallParams params) {
             this(params.origin, params.move, params.observer, params.installFlags,
-                    params.installerPackageName, params.installSource, params.volumeUuid,
+                    params.installSource, params.volumeUuid,
                     params.getUser(), null /*instructionSets*/, params.packageAbiOverride,
                     params.grantedRuntimePermissions, params.whitelistedRestrictedPermissions,
                     params.traceMethod, params.traceCookie, params.signingDetails,
@@ -14592,8 +14588,9 @@
 
         /** Existing install */
         FileInstallArgs(String codePath, String resourcePath, String[] instructionSets) {
-            super(OriginInfo.fromNothing(), null, null, 0, null, null, null, null, instructionSets,
-                    null, null, null, null, 0, PackageParser.SigningDetails.UNKNOWN,
+            super(OriginInfo.fromNothing(), null, null, 0, InstallSource.EMPTY,
+                    null, null, instructionSets, null, null, null, null, 0,
+                    PackageParser.SigningDetails.UNKNOWN,
                     PackageManager.INSTALL_REASON_UNKNOWN, null /* parent */);
             this.codeFile = (codePath != null) ? new File(codePath) : null;
             this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
@@ -15049,7 +15046,7 @@
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings");
 
         final String pkgName = pkg.packageName;
-        final String installerPackageName = installArgs.installerPackageName;
+        final String installerPackageName = installArgs.installSource.installerPackageName;
         final int[] installedForUsers = res.origUsers;
         final int installReason = installArgs.installReason;
 
@@ -15817,7 +15814,8 @@
                     Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
                 }
                 request.installResult.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
-                request.installResult.installerPackageName = request.args.installerPackageName;
+                request.installResult.installerPackageName =
+                        request.args.installSource.installerPackageName;
 
                 final String packageName = prepareResult.packageToScan.packageName;
                 prepareResults.put(packageName, prepareResult);
@@ -16163,7 +16161,8 @@
                     if ((mPackages.containsKey(childPkg.packageName))) {
                         childRes.removedInfo = new PackageRemovedInfo(this);
                         childRes.removedInfo.removedPackage = childPkg.packageName;
-                        childRes.removedInfo.installerPackageName = childPs.installerPackageName;
+                        childRes.removedInfo.installerPackageName =
+                                childPs.installSource.installerPackageName;
                     }
                     if (res.addedChildPackages == null) {
                         res.addedChildPackages = new ArrayMap<>();
@@ -16611,7 +16610,7 @@
                 res.removedInfo = new PackageRemovedInfo(this);
                 res.removedInfo.uid = oldPackage.applicationInfo.uid;
                 res.removedInfo.removedPackage = oldPackage.packageName;
-                res.removedInfo.installerPackageName = ps.installerPackageName;
+                res.removedInfo.installerPackageName = ps.installSource.installerPackageName;
                 res.removedInfo.isStaticSharedLib = pkg.staticSharedLibName != null;
                 res.removedInfo.isUpdate = true;
                 res.removedInfo.origUsers = installedUsers;
@@ -16634,7 +16633,7 @@
                                 childRes.removedInfo.removedPackage = childPkg.packageName;
                                 if (childPs != null) {
                                     childRes.removedInfo.installerPackageName =
-                                            childPs.installerPackageName;
+                                            childPs.installSource.installerPackageName;
                                 }
                                 childRes.removedInfo.isUpdate = true;
                                 childRes.removedInfo.installReasons =
@@ -16646,7 +16645,8 @@
                             PackageRemovedInfo childRemovedRes = new PackageRemovedInfo(this);
                             childRemovedRes.removedPackage = childPkg.packageName;
                             if (childPs != null) {
-                                childRemovedRes.installerPackageName = childPs.installerPackageName;
+                                childRemovedRes.installerPackageName =
+                                        childPs.installSource.installerPackageName;
                             }
                             childRemovedRes.isUpdate = false;
                             childRemovedRes.dataRemoved = true;
@@ -17668,7 +17668,7 @@
         final PackageParser.Package deletedPkg = deletedPs.pkg;
         if (outInfo != null) {
             outInfo.removedPackage = packageName;
-            outInfo.installerPackageName = deletedPs.installerPackageName;
+            outInfo.installerPackageName = deletedPs.installSource.installerPackageName;
             outInfo.isStaticSharedLib = deletedPkg != null
                     && deletedPkg.staticSharedLibName != null;
             outInfo.populateUsers(deletedPs == null ? null
@@ -18263,7 +18263,7 @@
                     String childPackageName = ps.childPackageNames.get(i);
                     PackageRemovedInfo childInfo = new PackageRemovedInfo(this);
                     childInfo.removedPackage = childPackageName;
-                    childInfo.installerPackageName = ps.installerPackageName;
+                    childInfo.installerPackageName = ps.installSource.installerPackageName;
                     outInfo.removedChildPackages.put(childPackageName, childInfo);
                     PackageSetting childPs = mSettings.getPackageLPr(childPackageName);
                     if (childPs != null) {
@@ -18403,7 +18403,7 @@
 
         if (outInfo != null) {
             outInfo.removedPackage = ps.name;
-            outInfo.installerPackageName = ps.installerPackageName;
+            outInfo.installerPackageName = ps.installSource.installerPackageName;
             outInfo.isStaticSharedLib = pkg != null && pkg.staticSharedLibName != null;
             outInfo.removedAppId = ps.appId;
             outInfo.removedUsers = userIds;
@@ -21868,7 +21868,6 @@
 
         final String currentVolumeUuid;
         final File codeFile;
-        final String installerPackageName;
         final InstallSource installSource;
         final String packageAbiOverride;
         final int appId;
@@ -21926,7 +21925,6 @@
 
             isCurrentLocationExternal = isExternal(pkg);
             codeFile = new File(pkg.codePath);
-            installerPackageName = ps.installerPackageName;
             installSource = ps.installSource;
             packageAbiOverride = ps.cpuAbiOverrideString;
             appId = UserHandle.getAppId(pkg.applicationInfo.uid);
@@ -22073,7 +22071,7 @@
         final Message msg = mHandler.obtainMessage(INIT_COPY);
         final OriginInfo origin = OriginInfo.fromExistingFile(codeFile);
         final InstallParams params = new InstallParams(origin, move, installObserver, installFlags,
-                installerPackageName, installSource, volumeUuid, null /*verificationInfo*/, user,
+                installSource, volumeUuid, null /*verificationInfo*/, user,
                 packageAbiOverride, null /*grantedPermissions*/,
                 null /*whitelistedRestrictedPermissions*/, PackageParser.SigningDetails.UNKNOWN,
                 PackageManager.INSTALL_REASON_UNKNOWN, PackageManager.VERSION_CODE_HIGHEST);
@@ -23535,7 +23533,7 @@
                     return false;
                 }
                 final PackageSetting installerPackageSetting =
-                        mSettings.mPackages.get(packageSetting.installerPackageName);
+                        mSettings.mPackages.get(packageSetting.installSource.installerPackageName);
                 return installerPackageSetting != null
                         && UserHandle.isSameApp(installerPackageSetting.appId, callingUid);
             }
@@ -23958,23 +23956,20 @@
         private final File mStagedDir;
         private final IPackageInstallObserver2 mObserver;
         private final PackageInstaller.SessionParams mSessionParams;
-        private final String mInstallerPackageName;
         private final int mInstallerUid;
-        private final InstallSource mInstallSource;
+        @NonNull private final InstallSource mInstallSource;
         private final UserHandle mUser;
         private final SigningDetails mSigningDetails;
 
         ActiveInstallSession(String packageName, File stagedDir, IPackageInstallObserver2 observer,
-                PackageInstaller.SessionParams sessionParams, String installerPackageName,
-                int installerUid, InstallSource installSource,
-                UserHandle user, SigningDetails signingDetails) {
+                PackageInstaller.SessionParams sessionParams, int installerUid,
+                InstallSource installSource, UserHandle user, SigningDetails signingDetails) {
             mPackageName = packageName;
             mStagedDir = stagedDir;
             mObserver = observer;
             mSessionParams = sessionParams;
-            mInstallerPackageName = installerPackageName;
             mInstallerUid = installerUid;
-            mInstallSource = installSource;
+            mInstallSource = Preconditions.checkNotNull(installSource);
             mUser = user;
             mSigningDetails = signingDetails;
         }
@@ -23995,14 +23990,11 @@
             return mSessionParams;
         }
 
-        public String getInstallerPackageName() {
-            return mInstallerPackageName;
-        }
-
         public int getInstallerUid() {
             return mInstallerUid;
         }
 
+        @NonNull
         public InstallSource getInstallSource() {
             return mInstallSource;
         }
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index be0621b..4fca91a 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -187,7 +187,7 @@
         proto.write(PackageProto.VERSION_CODE, versionCode);
         proto.write(PackageProto.INSTALL_TIME_MS, firstInstallTime);
         proto.write(PackageProto.UPDATE_TIME_MS, lastUpdateTime);
-        proto.write(PackageProto.INSTALLER_NAME, installerPackageName);
+        proto.write(PackageProto.INSTALLER_NAME, installSource.installerPackageName);
 
         if (pkg != null) {
             proto.write(PackageProto.VERSION_STRING, pkg.mVersionName);
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index f0857dd..45ab357 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -36,6 +36,7 @@
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -122,13 +123,8 @@
      */
     Set<String> mOldCodePaths;
 
-    /** Package name of the app that installed this package */
-    String installerPackageName;
-    /** Indicates if the package that installed this app has been uninstalled */
-    boolean isOrphaned;
-    /** Information about the initial install of this package. */
-    @NonNull
-    InstallSource installSource;
+    /** Information about how this package was installed/updated. */
+    @NonNull InstallSource installSource;
     /** UUID of {@link VolumeInfo} hosting this app */
     String volumeUuid;
     /** The category of this app, as hinted by the installer */
@@ -162,7 +158,7 @@
         this.cpuAbiOverrideString = cpuAbiOverrideString;
         this.versionCode = pVersionCode;
         this.signatures = new PackageSignatures();
-        this.installSource = InstallSource.create(null);
+        this.installSource = InstallSource.EMPTY;
     }
 
     /**
@@ -180,28 +176,21 @@
     }
 
     public void setInstallerPackageName(String packageName) {
-        installerPackageName = packageName;
-    }
-
-    public String getInstallerPackageName() {
-        return installerPackageName;
+        installSource = installSource.setInstallerPackage(packageName);
     }
 
     public void setInstallSource(InstallSource installSource) {
-        this.installSource = installSource == null ? InstallSource.create(null) : installSource;
+        this.installSource = Preconditions.checkNotNull(installSource);
     }
 
     void removeInstallerPackage(String packageName) {
-        if (packageName == null) {
-            return;
-        }
-        if (packageName.equals(installerPackageName)) {
-            installerPackageName = null;
-            isOrphaned = true;
-        }
         installSource = installSource.removeInstallerPackage(packageName);
     }
 
+    public void setIsOrphaned(boolean isOrphaned) {
+        installSource = installSource.setIsOrphaned(isOrphaned);
+    }
+
     public void setVolumeUuid(String volumeUuid) {
         this.volumeUuid = volumeUuid;
     }
@@ -253,9 +242,7 @@
         cpuAbiOverrideString = orig.cpuAbiOverrideString;
         firstInstallTime = orig.firstInstallTime;
         installPermissionsFixed = orig.installPermissionsFixed;
-        installerPackageName = orig.installerPackageName;
         installSource = orig.installSource;
-        isOrphaned = orig.isOrphaned;
         keySetData = orig.keySetData;
         lastUpdateTime = orig.lastUpdateTime;
         legacyNativeLibraryPathString = orig.legacyNativeLibraryPathString;
@@ -703,8 +690,7 @@
         this.signatures = other.signatures;
         this.installPermissionsFixed = other.installPermissionsFixed;
         this.keySetData = other.keySetData;
-        this.installerPackageName = other.installerPackageName;
-        this.isOrphaned = other.isOrphaned;
+        this.installSource = other.installSource;
         this.volumeUuid = other.volumeUuid;
         this.categoryHint = other.categoryHint;
         this.updateAvailable = other.updateAvailable;
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 5e209965..a11ae8c 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -2838,13 +2838,13 @@
         if (pkg.uidError) {
             serializer.attribute(null, "uidError", "true");
         }
-        if (pkg.installerPackageName != null) {
-            serializer.attribute(null, "installer", pkg.installerPackageName);
+        InstallSource installSource = pkg.installSource;
+        if (installSource.installerPackageName != null) {
+            serializer.attribute(null, "installer", installSource.installerPackageName);
         }
-        if (pkg.isOrphaned) {
+        if (installSource.isOrphaned) {
             serializer.attribute(null, "isOrphaned", "true");
         }
-        InstallSource installSource = pkg.installSource;
         if (installSource.initiatingPackageName != null) {
             serializer.attribute(null, "installInitiator", installSource.initiatingPackageName);
         }
@@ -3807,9 +3807,8 @@
         }
         if (packageSetting != null) {
             packageSetting.uidError = "true".equals(uidError);
-            packageSetting.installerPackageName = installerPackageName;
-            packageSetting.isOrphaned = "true".equals(isOrphaned);
-            packageSetting.installSource = InstallSource.create(installInitiatingPackageName);
+            packageSetting.installSource = InstallSource.create(
+                    installInitiatingPackageName, installerPackageName, "true".equals(isOrphaned));
             packageSetting.volumeUuid = volumeUuid;
             packageSetting.categoryHint = categoryHint;
             packageSetting.legacyNativeLibraryPathString = legacyNativeLibraryPathStr;
@@ -4252,7 +4251,7 @@
         if (pkg == null) {
             throw new IllegalArgumentException("Unknown package: " + packageName);
         }
-        return pkg.installerPackageName;
+        return pkg.installSource.installerPackageName;
     }
 
     boolean isOrphaned(String packageName) {
@@ -4260,7 +4259,7 @@
         if (pkg == null) {
             throw new IllegalArgumentException("Unknown package: " + packageName);
         }
-        return pkg.isOrphaned;
+        return pkg.installSource.isOrphaned;
     }
 
     int getApplicationEnabledSettingLPr(String packageName, int userId) {
@@ -4313,8 +4312,9 @@
             pkgSetting.setStopped(stopped, userId);
             // pkgSetting.pkg.mSetStopped = stopped;
             if (pkgSetting.getNotLaunched(userId)) {
-                if (pkgSetting.installerPackageName != null) {
-                    pm.notifyFirstLaunch(pkgSetting.name, pkgSetting.installerPackageName, userId);
+                if (pkgSetting.installSource.installerPackageName != null) {
+                    pm.notifyFirstLaunch(pkgSetting.name,
+                            pkgSetting.installSource.installerPackageName, userId);
                 }
                 pkgSetting.setNotLaunched(false, userId);
             }
@@ -4477,7 +4477,8 @@
             pw.print(",");
             pw.print(ps.lastUpdateTime);
             pw.print(",");
-            pw.print(ps.installerPackageName != null ? ps.installerPackageName : "?");
+            pw.print(ps.installSource.installerPackageName != null
+                    ? ps.installSource.installerPackageName : "?");
             pw.println();
             if (ps.pkg != null) {
                 pw.print(checkinTag); pw.print("-"); pw.print("splt,");
@@ -4690,9 +4691,9 @@
         pw.print(prefix); pw.print("  lastUpdateTime=");
             date.setTime(ps.lastUpdateTime);
             pw.println(sdf.format(date));
-        if (ps.installerPackageName != null) {
+        if (ps.installSource.installerPackageName != null) {
             pw.print(prefix); pw.print("  installerPackageName=");
-                    pw.println(ps.installerPackageName);
+            pw.println(ps.installSource.installerPackageName);
         }
         if (ps.volumeUuid != null) {
             pw.print(prefix); pw.print("  volumeUuid=");
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
index 7c2a097..3c10447 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
@@ -165,9 +165,8 @@
                 /* stagingManager */ null,
                 /* sessionId */ sessionId,
                 /* userId */  456,
-                /* installerPackageName */ "testInstaller",
                 /* installerUid */ -1,
-                InstallSource.create("testInstaller"),
+                /* installSource */ InstallSource.create("testInstaller", "testInstaller"),
                 /* sessionParams */ params,
                 /* createdMillis */ 0L,
                 /* stageDir */ mTmpDir,
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 15032c5..1106be2 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -812,11 +812,9 @@
         assertSame(origPkgSetting.cpuAbiOverrideString, testPkgSetting.cpuAbiOverrideString);
         assertThat(origPkgSetting.cpuAbiOverrideString, is(testPkgSetting.cpuAbiOverrideString));
         assertThat(origPkgSetting.firstInstallTime, is(testPkgSetting.firstInstallTime));
-        assertSame(origPkgSetting.installerPackageName, testPkgSetting.installerPackageName);
-        assertThat(origPkgSetting.installerPackageName, is(testPkgSetting.installerPackageName));
+        assertSame(origPkgSetting.installSource, testPkgSetting.installSource);
         assertThat(origPkgSetting.installPermissionsFixed,
                 is(testPkgSetting.installPermissionsFixed));
-        assertThat(origPkgSetting.isOrphaned, is(testPkgSetting.isOrphaned));
         assertSame(origPkgSetting.keySetData, testPkgSetting.keySetData);
         assertThat(origPkgSetting.keySetData, is(testPkgSetting.keySetData));
         assertThat(origPkgSetting.lastUpdateTime, is(testPkgSetting.lastUpdateTime));
diff --git a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
index 05905d9..3ea3b3c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
@@ -429,7 +429,7 @@
 
         final PackageManagerService.ScanResult scanResult = executeScan(scanRequest);
 
-        assertThat(scanResult.pkgSetting.isOrphaned, is(true));
+        assertThat(scanResult.pkgSetting.installSource.isOrphaned, is(true));
     }
 
     private static Matcher<Integer> hasFlag(final int flag) {