Add a new API to let app installer to flag package source.

Bug: 202130031
Test: Able to boot without error
Test: When app is installed by PackageInstaller app, restricted
settings app ops is set to MODE_ERRORED.
Test: atest InstallSourceInfoTest

Change-Id: I190583809d43386e671a82ded721a1829cb64dbb
diff --git a/core/api/current.txt b/core/api/current.txt
index fee4944..db1993f 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -11295,6 +11295,7 @@
     method @Nullable public android.content.pm.SigningInfo getInitiatingPackageSigningInfo();
     method @Nullable public String getInstallingPackageName();
     method @Nullable public String getOriginatingPackageName();
+    method public int getPackageSource();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.InstallSourceInfo> CREATOR;
   }
@@ -11502,6 +11503,11 @@
     field public static final String EXTRA_STATUS = "android.content.pm.extra.STATUS";
     field public static final String EXTRA_STATUS_MESSAGE = "android.content.pm.extra.STATUS_MESSAGE";
     field public static final String EXTRA_STORAGE_PATH = "android.content.pm.extra.STORAGE_PATH";
+    field public static final int PACKAGE_SOURCE_DOWNLOADED_FILE = 4; // 0x4
+    field public static final int PACKAGE_SOURCE_LOCAL_FILE = 3; // 0x3
+    field public static final int PACKAGE_SOURCE_OTHER = 1; // 0x1
+    field public static final int PACKAGE_SOURCE_STORE = 2; // 0x2
+    field public static final int PACKAGE_SOURCE_UNSPECIFIED = 0; // 0x0
     field public static final int STATUS_FAILURE = 1; // 0x1
     field public static final int STATUS_FAILURE_ABORTED = 3; // 0x3
     field public static final int STATUS_FAILURE_BLOCKED = 2; // 0x2
@@ -11558,6 +11564,7 @@
     method public int getMode();
     method public int getOriginatingUid();
     method @Nullable public android.net.Uri getOriginatingUri();
+    method public int getPackageSource();
     method public int getParentSessionId();
     method public float getProgress();
     method @Nullable public android.net.Uri getReferrerUri();
@@ -11606,6 +11613,7 @@
     method public void setMultiPackage();
     method public void setOriginatingUid(int);
     method public void setOriginatingUri(@Nullable android.net.Uri);
+    method public void setPackageSource(int);
     method public void setReferrerUri(@Nullable android.net.Uri);
     method public void setRequireUserAction(int);
     method public void setSize(long);
diff --git a/core/java/android/content/pm/InstallSourceInfo.java b/core/java/android/content/pm/InstallSourceInfo.java
index 84d2ca3..88f1a16 100644
--- a/core/java/android/content/pm/InstallSourceInfo.java
+++ b/core/java/android/content/pm/InstallSourceInfo.java
@@ -35,14 +35,26 @@
 
     @Nullable private final String mInstallingPackageName;
 
+    @Nullable private final int mPackageSource;
+
     /** @hide */
     public InstallSourceInfo(@Nullable String initiatingPackageName,
             @Nullable SigningInfo initiatingPackageSigningInfo,
             @Nullable String originatingPackageName, @Nullable String installingPackageName) {
+        this(initiatingPackageName, initiatingPackageSigningInfo, originatingPackageName,
+                installingPackageName, PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED);
+    }
+
+    /** @hide */
+    public InstallSourceInfo(@Nullable String initiatingPackageName,
+            @Nullable SigningInfo initiatingPackageSigningInfo,
+            @Nullable String originatingPackageName, @Nullable String installingPackageName,
+            int packageSource) {
         mInitiatingPackageName = initiatingPackageName;
         mInitiatingPackageSigningInfo = initiatingPackageSigningInfo;
         mOriginatingPackageName = originatingPackageName;
         mInstallingPackageName = installingPackageName;
+        mPackageSource = packageSource;
     }
 
     @Override
@@ -57,6 +69,7 @@
         dest.writeParcelable(mInitiatingPackageSigningInfo, flags);
         dest.writeString(mOriginatingPackageName);
         dest.writeString(mInstallingPackageName);
+        dest.writeInt(mPackageSource);
     }
 
     private InstallSourceInfo(Parcel source) {
@@ -64,6 +77,7 @@
         mInitiatingPackageSigningInfo = source.readParcelable(SigningInfo.class.getClassLoader(), android.content.pm.SigningInfo.class);
         mOriginatingPackageName = source.readString();
         mInstallingPackageName = source.readString();
+        mPackageSource = source.readInt();
     }
 
     /**
@@ -122,6 +136,13 @@
         return mInstallingPackageName;
     }
 
+    /**
+     * Information about the package source when installer installed this app.
+     */
+    public @PackageInstaller.PackageSourceType int getPackageSource() {
+        return mPackageSource;
+    }
+
     @NonNull
     public static final Parcelable.Creator<InstallSourceInfo> CREATOR =
             new Creator<InstallSourceInfo>() {
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 08b07a7..67a2dc8 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -418,6 +418,48 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface FileLocation{}
 
+    /**
+     * The installer did not call SessionParams#setPackageSource(int) to specify the package
+     * source.
+     */
+    public static final int PACKAGE_SOURCE_UNSPECIFIED = 0;
+
+    /**
+     * Code indicating that the package being installed is from a source not reflected by any
+     * other package source constant.
+     */
+    public static final int PACKAGE_SOURCE_OTHER = 1;
+
+    /**
+     * Code indicating that the package being installed is from a store. An app store that
+     * installs an app for the user would use this.
+     */
+    public static final int PACKAGE_SOURCE_STORE = 2;
+
+    /**
+     * Code indicating that the package being installed comes from a local file on the device. A
+     * file manager that is facilitating the installation of an APK file would use this.
+     */
+    public static final int PACKAGE_SOURCE_LOCAL_FILE = 3;
+
+    /**
+     * Code indicating that the package being installed comes from a file that was downloaded to
+     * the device by the user. For use in place of PACKAGE_SOURCE_LOCAL_FILE when the installer
+     * knows the package was downloaded.
+     */
+    public static final int PACKAGE_SOURCE_DOWNLOADED_FILE = 4;
+
+    /** @hide */
+    @IntDef(prefix = { "PACKAGE_SOURCE_" }, value = {
+            PACKAGE_SOURCE_UNSPECIFIED,
+            PACKAGE_SOURCE_STORE,
+            PACKAGE_SOURCE_LOCAL_FILE,
+            PACKAGE_SOURCE_DOWNLOADED_FILE,
+            PACKAGE_SOURCE_OTHER
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface PackageSourceType{}
+
     /** Default set of checksums - includes all available checksums.
      * @see Session#requestChecksums  */
     private static final int DEFAULT_CHECKSUMS =
@@ -1722,6 +1764,8 @@
         /** {@hide} */
         public boolean isMultiPackage;
         /** {@hide} */
+        public int packageSource = PACKAGE_SOURCE_UNSPECIFIED;
+        /** {@hide} */
         public boolean isStaged;
         /** {@hide} */
         public long requiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST;
@@ -1776,6 +1820,7 @@
             }
             rollbackDataPolicy = source.readInt();
             requireUserAction = source.readInt();
+            packageSource = source.readInt();
         }
 
         /** {@hide} */
@@ -1805,6 +1850,7 @@
             ret.dataLoaderParams = dataLoaderParams;
             ret.rollbackDataPolicy = rollbackDataPolicy;
             ret.requireUserAction = requireUserAction;
+            ret.packageSource = packageSource;
             return ret;
         }
 
@@ -1926,6 +1972,13 @@
         }
 
         /**
+         * Sets the apk package installation source.
+         */
+        public void setPackageSource(@PackageSourceType int packageSource) {
+            this.packageSource = packageSource;
+        }
+
+        /**
          * Sets which restricted permissions to be allowlisted for the app. Allowlisting
          * is not granting the permissions, rather it allows the app to hold permissions
          * which are otherwise restricted. Allowlisting a non restricted permission has
@@ -2289,6 +2342,7 @@
             pw.printPair("abiOverride", abiOverride);
             pw.printPair("volumeUuid", volumeUuid);
             pw.printPair("grantedRuntimePermissions", grantedRuntimePermissions);
+            pw.printPair("packageSource", packageSource);
             pw.printPair("whitelistedRestrictedPermissions", whitelistedRestrictedPermissions);
             pw.printPair("autoRevokePermissions", autoRevokePermissionsMode);
             pw.printPair("installerPackageName", installerPackageName);
@@ -2338,6 +2392,7 @@
             }
             dest.writeInt(rollbackDataPolicy);
             dest.writeInt(requireUserAction);
+            dest.writeInt(packageSource);
         }
 
         public static final Parcelable.Creator<SessionParams>
@@ -2540,6 +2595,9 @@
         public int requireUserAction;
 
         /** {@hide} */
+        public int packageSource = PACKAGE_SOURCE_UNSPECIFIED;
+
+        /** {@hide} */
         public int installerUid;
 
         /** {@hide} */
@@ -2593,6 +2651,7 @@
             createdMillis = source.readLong();
             requireUserAction = source.readInt();
             installerUid = source.readInt();
+            packageSource = source.readInt();
         }
 
         /**
@@ -2929,6 +2988,13 @@
         }
 
         /**
+         * Gets the apk package installation source.
+         */
+        public @PackageSourceType int getPackageSource() {
+            return packageSource;
+        }
+
+        /**
          * Returns true if this session is a multi-package session containing references to other
          * sessions.
          */
@@ -3163,6 +3229,7 @@
             dest.writeLong(createdMillis);
             dest.writeInt(requireUserAction);
             dest.writeInt(installerUid);
+            dest.writeInt(packageSource);
         }
 
         public static final Parcelable.Creator<SessionInfo>
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
index b65e976..3aa8dbf4 100755
--- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
@@ -130,8 +130,12 @@
             } else {
                 PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
                         PackageInstaller.SessionParams.MODE_FULL_INSTALL);
+                final Uri referrerUri = getIntent().getParcelableExtra(Intent.EXTRA_REFERRER);
+                params.setPackageSource(
+                        referrerUri != null ? PackageInstaller.PACKAGE_SOURCE_DOWNLOADED_FILE
+                                : PackageInstaller.PACKAGE_SOURCE_LOCAL_FILE);
                 params.setInstallAsInstantApp(false);
-                params.setReferrerUri(getIntent().getParcelableExtra(Intent.EXTRA_REFERRER));
+                params.setReferrerUri(referrerUri);
                 params.setOriginatingUri(getIntent()
                         .getParcelableExtra(Intent.EXTRA_ORIGINATING_URI));
                 params.setOriginatingUid(getIntent().getIntExtra(Intent.EXTRA_ORIGINATING_UID,
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index 691bf9f..c942a43 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -5033,7 +5033,7 @@
         }
 
         return new InstallSourceInfo(initiatingPackageName, initiatingPackageSigningInfo,
-                originatingPackageName, installerPackageName);
+                originatingPackageName, installerPackageName, installSource.packageSource);
     }
 
     @PackageManager.EnabledState
diff --git a/services/core/java/com/android/server/pm/FileInstallArgs.java b/services/core/java/com/android/server/pm/FileInstallArgs.java
index 02c8c12..85c3cc9 100644
--- a/services/core/java/com/android/server/pm/FileInstallArgs.java
+++ b/services/core/java/com/android/server/pm/FileInstallArgs.java
@@ -28,6 +28,7 @@
 import static com.android.server.pm.PackageManagerServiceUtils.makeDirRecursive;
 
 import android.content.pm.DataLoaderType;
+import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
 import android.content.pm.SigningDetails;
 import android.content.pm.parsing.ApkLiteParseUtils;
@@ -80,7 +81,8 @@
                 null, null, instructionSets, null, null, null, MODE_DEFAULT, null, 0,
                 SigningDetails.UNKNOWN,
                 PackageManager.INSTALL_REASON_UNKNOWN, PackageManager.INSTALL_SCENARIO_DEFAULT,
-                false, DataLoaderType.NONE, pm);
+                false, DataLoaderType.NONE,
+                PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED, pm);
         mCodeFile = (codePath != null) ? new File(codePath) : null;
     }
 
diff --git a/services/core/java/com/android/server/pm/InstallArgs.java b/services/core/java/com/android/server/pm/InstallArgs.java
index c544ad2..03c68d9 100644
--- a/services/core/java/com/android/server/pm/InstallArgs.java
+++ b/services/core/java/com/android/server/pm/InstallArgs.java
@@ -53,6 +53,7 @@
     final int mInstallScenario;
     final boolean mForceQueryableOverride;
     final int mDataLoaderType;
+    final int mPackageSource;
 
     // The list of instruction sets supported by this app. This is currently
     // only used during the rmdex() phase to clean up resources. We can get rid of this
@@ -70,7 +71,7 @@
             int autoRevokePermissionsMode,
             String traceMethod, int traceCookie, SigningDetails signingDetails,
             int installReason, int installScenario, boolean forceQueryableOverride,
-            int dataLoaderType, PackageManagerService pm) {
+            int dataLoaderType, int packageSource, PackageManagerService pm) {
         mOriginInfo = originInfo;
         mMoveInfo = moveInfo;
         mInstallFlags = installFlags;
@@ -90,6 +91,7 @@
         mInstallScenario = installScenario;
         mForceQueryableOverride = forceQueryableOverride;
         mDataLoaderType = dataLoaderType;
+        mPackageSource = packageSource;
         mPm = pm;
         mRemovePackageHelper = new RemovePackageHelper(mPm);
     }
@@ -103,7 +105,7 @@
                 params.mAutoRevokePermissionsMode,
                 params.mTraceMethod, params.mTraceCookie, params.mSigningDetails,
                 params.mInstallReason, params.mInstallScenario, params.mForceQueryableOverride,
-                params.mDataLoaderType, params.mPm);
+                params.mDataLoaderType, params.mPackageSource, params.mPm);
     }
 
     abstract int copyApk();
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 336da2a..82681ec 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -91,6 +91,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
+import android.app.AppOpsManager;
 import android.app.ApplicationPackageManager;
 import android.app.backup.IBackupManager;
 import android.content.ContentResolver;
@@ -2152,6 +2153,12 @@
                 final ScanResult scanResult = reconciledPkg.mScanResult;
                 mPm.mPermissionManager.onPackageInstalled(pkg, scanResult.mPreviousAppId,
                         permissionParamsBuilder.build(), userId);
+                // Apply restricted settings on potentially dangerous packages.
+                if (installArgs.mPackageSource == PackageInstaller.PACKAGE_SOURCE_LOCAL_FILE
+                        || installArgs.mPackageSource
+                        == PackageInstaller.PACKAGE_SOURCE_DOWNLOADED_FILE) {
+                    enableRestrictedSettings(pkgName, pkg.getUid());
+                }
             }
             res.mName = pkgName;
             res.mUid = pkg.getUid();
@@ -2166,6 +2173,18 @@
         Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
     }
 
+    private void enableRestrictedSettings(String pkgName, int appId) {
+        final AppOpsManager appOpsManager = mPm.mContext.getSystemService(AppOpsManager.class);
+        final int[] allUsersList = mPm.mUserManager.getUserIds();
+        for (int userId : allUsersList) {
+            final int uid = UserHandle.getUid(userId, appId);
+            appOpsManager.setMode(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
+                    uid,
+                    pkgName,
+                    AppOpsManager.MODE_ERRORED);
+        }
+    }
+
     /**
      * On successful install, executes remaining steps after commit completes and the package lock
      * is released. These are typically more expensive or require calls to installd, which often
@@ -2968,6 +2987,8 @@
                             PermissionManagerServiceInternal.PackageInstalledParams.DEFAULT,
                             UserHandle.USER_ALL);
                     mPm.writeSettingsLPrTEMP();
+                    // Since compressed package can be system app only, we do not need to
+                    // set restricted settings on it.
                 }
             } catch (PackageManagerException e) {
                 // Whoops! Something went very wrong; roll back to the stub and disable the package
diff --git a/services/core/java/com/android/server/pm/InstallParams.java b/services/core/java/com/android/server/pm/InstallParams.java
index 7e845c7..6c80976 100644
--- a/services/core/java/com/android/server/pm/InstallParams.java
+++ b/services/core/java/com/android/server/pm/InstallParams.java
@@ -74,12 +74,13 @@
     final boolean mForceQueryableOverride;
     final int mDataLoaderType;
     final long mRequiredInstalledVersionCode;
+    final int mPackageSource;
     final PackageLite mPackageLite;
 
     InstallParams(OriginInfo originInfo, MoveInfo moveInfo, IPackageInstallObserver2 observer,
             int installFlags, InstallSource installSource, String volumeUuid,
-            UserHandle user, String packageAbiOverride, PackageLite packageLite,
-            PackageManagerService pm) {
+            UserHandle user, String packageAbiOverride, int packageSource,
+            PackageLite packageLite, PackageManagerService pm) {
         super(user, pm);
         mOriginInfo = originInfo;
         mMoveInfo = moveInfo;
@@ -98,6 +99,7 @@
         mForceQueryableOverride = false;
         mDataLoaderType = DataLoaderType.NONE;
         mRequiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST;
+        mPackageSource = packageSource;
         mPackageLite = packageLite;
     }
 
@@ -124,6 +126,7 @@
         mDataLoaderType = (sessionParams.dataLoaderParams != null)
                 ? sessionParams.dataLoaderParams.getType() : DataLoaderType.NONE;
         mRequiredInstalledVersionCode = sessionParams.requiredInstalledVersionCode;
+        mPackageSource = sessionParams.packageSource;
         mPackageLite = packageLite;
     }
 
diff --git a/services/core/java/com/android/server/pm/InstallSource.java b/services/core/java/com/android/server/pm/InstallSource.java
index 2b56c71..404285c 100644
--- a/services/core/java/com/android/server/pm/InstallSource.java
+++ b/services/core/java/com/android/server/pm/InstallSource.java
@@ -17,6 +17,7 @@
 package com.android.server.pm;
 
 import android.annotation.Nullable;
+import android.content.pm.PackageInstaller;
 
 import com.android.internal.util.Preconditions;
 
@@ -32,11 +33,12 @@
      * a package. Used in preference to null.
      */
     static final InstallSource EMPTY = new InstallSource(null, null, null, null, false, false,
-            null);
+            null, PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED);
 
     /** We also memoize this case because it is common - all un-updated system apps. */
     private static final InstallSource EMPTY_ORPHANED = new InstallSource(
-            null, null, null, null, true, false, null);
+            null, null, null, null, true, false, null,
+            PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED);
 
     /**
      * The package that requested the installation, if known. May not correspond to a currently
@@ -84,28 +86,47 @@
      */
     final boolean isInitiatingPackageUninstalled;
 
+    final int packageSource;
+
     static InstallSource create(@Nullable String initiatingPackageName,
             @Nullable String originatingPackageName, @Nullable String installerPackageName,
             @Nullable String installerAttributionTag) {
         return create(initiatingPackageName, originatingPackageName, installerPackageName,
-                installerAttributionTag, false, false);
+                installerAttributionTag, PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED);
     }
 
     static InstallSource create(@Nullable String initiatingPackageName,
             @Nullable String originatingPackageName, @Nullable String installerPackageName,
             @Nullable String installerAttributionTag, boolean isOrphaned,
             boolean isInitiatingPackageUninstalled) {
+        return create(initiatingPackageName, originatingPackageName, installerPackageName,
+                installerAttributionTag, PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED, isOrphaned,
+                isInitiatingPackageUninstalled);
+    }
+
+    static InstallSource create(@Nullable String initiatingPackageName,
+            @Nullable String originatingPackageName, @Nullable String installerPackageName,
+            @Nullable String installerAttributionTag, int packageSource) {
+        return create(initiatingPackageName, originatingPackageName, installerPackageName,
+                installerAttributionTag, packageSource, false, false);
+    }
+
+    static InstallSource create(@Nullable String initiatingPackageName,
+            @Nullable String originatingPackageName, @Nullable String installerPackageName,
+            @Nullable String installerAttributionTag, int packageSource, boolean isOrphaned,
+            boolean isInitiatingPackageUninstalled) {
         return createInternal(
                 intern(initiatingPackageName),
                 intern(originatingPackageName),
                 intern(installerPackageName),
                 installerAttributionTag,
+                packageSource,
                 isOrphaned, isInitiatingPackageUninstalled, null);
     }
 
     private static InstallSource createInternal(@Nullable String initiatingPackageName,
             @Nullable String originatingPackageName, @Nullable String installerPackageName,
-            @Nullable String installerAttributionTag, boolean isOrphaned,
+            @Nullable String installerAttributionTag, int packageSource, boolean isOrphaned,
             boolean isInitiatingPackageUninstalled,
             @Nullable PackageSignatures initiatingPackageSignatures) {
         if (initiatingPackageName == null && originatingPackageName == null
@@ -115,7 +136,7 @@
         }
         return new InstallSource(initiatingPackageName, originatingPackageName,
                 installerPackageName, installerAttributionTag, isOrphaned,
-                isInitiatingPackageUninstalled, initiatingPackageSignatures
+                isInitiatingPackageUninstalled, initiatingPackageSignatures, packageSource
         );
     }
 
@@ -123,7 +144,8 @@
             @Nullable String originatingPackageName, @Nullable String installerPackageName,
             @Nullable String installerAttributionTag, boolean isOrphaned,
             boolean isInitiatingPackageUninstalled,
-            @Nullable PackageSignatures initiatingPackageSignatures) {
+            @Nullable PackageSignatures initiatingPackageSignatures,
+            int packageSource) {
         if (initiatingPackageName == null) {
             Preconditions.checkArgument(initiatingPackageSignatures == null);
             Preconditions.checkArgument(!isInitiatingPackageUninstalled);
@@ -135,6 +157,7 @@
         this.isOrphaned = isOrphaned;
         this.isInitiatingPackageUninstalled = isInitiatingPackageUninstalled;
         this.initiatingPackageSignatures = initiatingPackageSignatures;
+        this.packageSource = packageSource;
     }
 
     /**
@@ -146,9 +169,8 @@
             return this;
         }
         return createInternal(initiatingPackageName, originatingPackageName,
-                intern(installerPackageName), installerAttributionTag, isOrphaned,
-                isInitiatingPackageUninstalled, initiatingPackageSignatures
-        );
+                intern(installerPackageName), installerAttributionTag, packageSource, isOrphaned,
+                isInitiatingPackageUninstalled, initiatingPackageSignatures);
     }
 
     /**
@@ -160,7 +182,7 @@
             return this;
         }
         return createInternal(initiatingPackageName, originatingPackageName, installerPackageName,
-                installerAttributionTag, isOrphaned, isInitiatingPackageUninstalled,
+                installerAttributionTag, packageSource, isOrphaned, isInitiatingPackageUninstalled,
                 initiatingPackageSignatures);
     }
 
@@ -173,7 +195,8 @@
             return this;
         }
         return createInternal(initiatingPackageName, originatingPackageName, installerPackageName,
-                installerAttributionTag, isOrphaned, isInitiatingPackageUninstalled, signatures);
+                installerAttributionTag, packageSource, isOrphaned,
+                isInitiatingPackageUninstalled, signatures);
     }
 
     /**
@@ -215,7 +238,8 @@
         }
 
         return createInternal(initiatingPackageName, originatingPackageName, installerPackageName,
-                null, isOrphaned, isInitiatingPackageUninstalled, initiatingPackageSignatures);
+                null, packageSource, isOrphaned,
+                isInitiatingPackageUninstalled, initiatingPackageSignatures);
     }
 
     @Nullable
diff --git a/services/core/java/com/android/server/pm/MovePackageHelper.java b/services/core/java/com/android/server/pm/MovePackageHelper.java
index 652a9ae..5fc90b1 100644
--- a/services/core/java/com/android/server/pm/MovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/MovePackageHelper.java
@@ -298,7 +298,8 @@
                 new File(origin.mResolvedPath), /* flags */ 0);
         final PackageLite lite = ret.isSuccess() ? ret.getResult() : null;
         final InstallParams params = new InstallParams(origin, move, installObserver, installFlags,
-                installSource, volumeUuid, user, packageAbiOverride, lite, mPm);
+                installSource, volumeUuid, user, packageAbiOverride,
+                PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED, lite, mPm);
         params.movePackage();
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 8465248..a7d4092 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -847,7 +847,7 @@
         }
         InstallSource installSource = InstallSource.create(installerPackageName,
                 originatingPackageName, requestedInstallerPackageName,
-                installerAttributionTag);
+                installerAttributionTag, params.packageSource);
         session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this,
                 mSilentUpdatePolicy, mInstallThread.getLooper(), mStagingManager, sessionId,
                 userId, callingUid, installSource, params, createdMillis, 0L, stageDir, stageCid,
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 7152783..04a1b0d 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -232,6 +232,7 @@
     private static final String ATTR_IS_READY = "isReady";
     private static final String ATTR_IS_FAILED = "isFailed";
     private static final String ATTR_IS_APPLIED = "isApplied";
+    private static final String ATTR_PACKAGE_SOURCE = "packageSource";
     private static final String ATTR_SESSION_ERROR_CODE = "errorCode";
     private static final String ATTR_SESSION_ERROR_MESSAGE = "errorMessage";
     private static final String ATTR_MODE = "mode";
@@ -1127,6 +1128,7 @@
             info.updatedMillis = updatedMillis;
             info.requireUserAction = params.requireUserAction;
             info.installerUid = mInstallerUid;
+            info.packageSource = params.packageSource;
         }
         return info;
     }
@@ -2186,7 +2188,8 @@
             }
 
             mInstallerUid = newOwnerAppInfo.uid;
-            mInstallSource = InstallSource.create(packageName, null, packageName, null);
+            mInstallSource = InstallSource.create(packageName, null, packageName, null,
+                    params.packageSource);
         }
     }
 
@@ -4482,6 +4485,7 @@
             writeBooleanAttribute(out, ATTR_IS_READY, mSessionReady);
             writeBooleanAttribute(out, ATTR_IS_FAILED, mSessionFailed);
             writeBooleanAttribute(out, ATTR_IS_APPLIED, mSessionApplied);
+            out.attributeInt(null, ATTR_PACKAGE_SOURCE, params.packageSource);
             out.attributeInt(null, ATTR_SESSION_ERROR_CODE, mSessionErrorCode);
             writeStringAttribute(out, ATTR_SESSION_ERROR_MESSAGE, mSessionErrorMessage);
             // TODO(patb,109941548): avoid writing to xml and instead infer / validate this after
@@ -4656,6 +4660,7 @@
         params.abiOverride = readStringAttribute(in, ATTR_ABI_OVERRIDE);
         params.volumeUuid = readStringAttribute(in, ATTR_VOLUME_UUID);
         params.installReason = in.getAttributeInt(null, ATTR_INSTALL_REASON);
+        params.packageSource = in.getAttributeInt(null, ATTR_PACKAGE_SOURCE);
 
         if (in.getAttributeBoolean(null, ATTR_IS_DATALOADER, false)) {
             params.dataLoaderParams = new DataLoaderParams(
@@ -4784,7 +4789,8 @@
         }
 
         InstallSource installSource = InstallSource.create(installInitiatingPackageName,
-                installOriginatingPackageName, installerPackageName, installerAttributionTag);
+                installOriginatingPackageName, installerPackageName, installerAttributionTag,
+                params.packageSource);
         return new PackageInstallerSession(callback, context, pm, sessionProvider,
                 silentUpdatePolicy, installerThread, stagingManager, sessionId, userId,
                 installerUid, installSource, params, createdMillis, committedMillis, stageDir,
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index d4fcd06..500b4ec 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -2903,6 +2903,8 @@
         params.sessionParams = sessionParams;
         // Allowlist all permissions by default
         sessionParams.installFlags |= PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
+        // Set package source to other by default
+        sessionParams.setPackageSource(PackageInstaller.PACKAGE_SOURCE_OTHER);
 
         String opt;
         boolean replaceExisting = true;
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 13a3c5b..279de83 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -40,6 +40,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ComponentInfo;
 import android.content.pm.IntentFilterVerificationInfo;
+import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackagePartitions;
@@ -2828,6 +2829,8 @@
             serializer.attribute(null, "installerAttributionTag",
                     installSource.installerAttributionTag);
         }
+        serializer.attributeInt(null, "packageSource",
+                installSource.packageSource);
         if (installSource.isOrphaned) {
             serializer.attributeBoolean(null, "isOrphaned", true);
         }
@@ -3599,6 +3602,7 @@
         String systemStr = null;
         String installerPackageName = null;
         String installerAttributionTag = null;
+        int packageSource = PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED;
         boolean isOrphaned = false;
         String installOriginatingPackageName = null;
         String installInitiatingPackageName = null;
@@ -3640,6 +3644,8 @@
             versionCode = parser.getAttributeLong(null, "version", 0);
             installerPackageName = parser.getAttributeValue(null, "installer");
             installerAttributionTag = parser.getAttributeValue(null, "installerAttributionTag");
+            packageSource = parser.getAttributeInt(null, "packageSource",
+                    PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED);
             isOrphaned = parser.getAttributeBoolean(null, "isOrphaned", false);
             installInitiatingPackageName = parser.getAttributeValue(null, "installInitiator");
             installOriginatingPackageName = parser.getAttributeValue(null, "installOriginator");
@@ -3778,7 +3784,7 @@
         if (packageSetting != null) {
             InstallSource installSource = InstallSource.create(
                     installInitiatingPackageName, installOriginatingPackageName,
-                    installerPackageName, installerAttributionTag, isOrphaned,
+                    installerPackageName, installerAttributionTag, packageSource, isOrphaned,
                     installInitiatorUninstalled);
             packageSetting.setInstallSource(installSource)
                     .setVolumeUuid(volumeUuid)
@@ -4449,6 +4455,8 @@
                     ? ps.getInstallSource().installerPackageName : "?");
             pw.print(ps.getInstallSource().installerAttributionTag != null
                     ? "(" + ps.getInstallSource().installerAttributionTag + ")" : "");
+            pw.print(",");
+            pw.print(ps.getInstallSource().packageSource);
             pw.println();
             if (pkg != null) {
                 pw.print(checkinTag); pw.print("-"); pw.print("splt,");
@@ -4727,6 +4735,8 @@
             pw.print(prefix); pw.print("  installerAttributionTag=");
             pw.println(ps.getInstallSource().installerAttributionTag);
         }
+        pw.print(prefix); pw.print("  packageSource=");
+        pw.println(ps.getInstallSource().packageSource);
         if (ps.isLoading()) {
             pw.print(prefix); pw.println("  loadingProgress=" +
                     (int) (ps.getLoadingProgress() * 100) + "%");
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java
index 64657a9..5f48fc2 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java
@@ -724,7 +724,8 @@
         params.isStaged = true;
 
         InstallSource installSource = InstallSource.create("testInstallInitiator",
-                "testInstallOriginator", "testInstaller", "testAttributionTag");
+                "testInstallOriginator", "testInstaller", "testAttributionTag",
+                PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED);
 
         PackageInstallerSession session = new PackageInstallerSession(
                 /* callback */ null,
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilitySecurityPolicyTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilitySecurityPolicyTest.java
index b403033..4651546 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilitySecurityPolicyTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilitySecurityPolicyTest.java
@@ -47,6 +47,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.InstallSourceInfo;
 import android.content.pm.PackageInfo;
+import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.ResolveInfo;
@@ -748,7 +749,7 @@
             throws PackageManager.NameNotFoundException {
         final InstallSourceInfo installSourceInfo = new InstallSourceInfo(
                 packageName, new SigningInfo(), null,
-                packageName);
+                packageName, PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED);
         when(mMockPackageManager.getPackageInfo(packageName, 0)).thenReturn(
                 mMockSourcePackageInfo);
         mMockSourcePackageInfo.applicationInfo = mMockSourceApplicationInfo;
diff --git a/services/tests/servicestests/src/com/android/server/locales/LocaleManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/locales/LocaleManagerServiceTest.java
index ee2bb0a..ca5b0cb 100644
--- a/services/tests/servicestests/src/com/android/server/locales/LocaleManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/locales/LocaleManagerServiceTest.java
@@ -38,6 +38,7 @@
 import android.app.ActivityManagerInternal;
 import android.content.Context;
 import android.content.pm.InstallSourceInfo;
+import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.os.Binder;
@@ -69,7 +70,8 @@
     private static final InstallSourceInfo DEFAULT_INSTALL_SOURCE_INFO = new InstallSourceInfo(
             /* initiatingPackageName = */ null, /* initiatingPackageSigningInfo = */ null,
             /* originatingPackageName = */ null,
-            /* installingPackageName = */ DEFAULT_INSTALLER_PACKAGE_NAME);
+            /* installingPackageName = */ DEFAULT_INSTALLER_PACKAGE_NAME,
+            /* packageSource = */ PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED);
 
     private LocaleManagerService mLocaleManagerService;
     private LocaleManagerBackupHelper mMockBackupHelper;
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 59f2ca4..3d21b74 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
@@ -157,7 +157,8 @@
             params.isMultiPackage = true;
         }
         InstallSource installSource = InstallSource.create("testInstallInitiator",
-                "testInstallOriginator", "testInstaller", "testAttributionTag");
+                "testInstallOriginator", "testInstaller", "testAttributionTag",
+                PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED);
         return new PackageInstallerSession(
                 /* callback */ null,
                 /* context */null,