diff options
7 files changed, 76 insertions, 29 deletions
diff --git a/core/proto/android/service/package.proto b/core/proto/android/service/package.proto index d010c8ff8ad9..004b096496db 100644 --- a/core/proto/android/service/package.proto +++ b/core/proto/android/service/package.proto @@ -119,6 +119,9 @@ message PackageProto { // The package that requested the installation of this one. optional string initiating_package_name = 1; + + // The package on behalf of which the initiiating package requested the install. + optional string originating_package_name = 2; } // Name of package. e.g. "com.android.providers.telephony". diff --git a/services/core/java/com/android/server/pm/InstallSource.java b/services/core/java/com/android/server/pm/InstallSource.java index 990eba15234e..c7b502636d77 100644 --- a/services/core/java/com/android/server/pm/InstallSource.java +++ b/services/core/java/com/android/server/pm/InstallSource.java @@ -18,8 +18,6 @@ package com.android.server.pm; import android.annotation.Nullable; -import com.android.internal.util.IndentingPrintWriter; - import java.util.Objects; /** @@ -31,13 +29,22 @@ final class InstallSource { * 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); + static final InstallSource EMPTY = new InstallSource(null, null, null, false); /** The package that requested the installation, if known. */ @Nullable final String initiatingPackageName; /** + * The package on behalf of which the initiating package requested the installation, if any. + * For example if a downloaded APK is installed via the Package Installer this could be the + * app that performed the download. This value is provided by the initiating package and not + * verified by the framework. + */ + @Nullable + final String originatingPackageName; + + /** * Package name of the app that installed this package (the installer of record). Note that * this may be modified. */ @@ -48,47 +55,49 @@ final class InstallSource { final boolean isOrphaned; static InstallSource create(@Nullable String initiatingPackageName, - @Nullable String installerPackageName) { - return create(initiatingPackageName, installerPackageName, false); - } + @Nullable String originatingPackageName, @Nullable String installerPackageName, + boolean isOrphaned) { - static InstallSource create(@Nullable String initiatingPackageName, - @Nullable String installerPackageName, boolean isOrphaned) { - if (initiatingPackageName == null && installerPackageName == null && !isOrphaned) { + if (initiatingPackageName == null && originatingPackageName == null + && installerPackageName == null && !isOrphaned) { return EMPTY; } return new InstallSource( initiatingPackageName == null ? null : initiatingPackageName.intern(), + originatingPackageName == null ? null : originatingPackageName.intern(), installerPackageName == null ? null : installerPackageName.intern(), isOrphaned); } private InstallSource(@Nullable String initiatingPackageName, - @Nullable String installerPackageName, boolean isOrphaned) { + @Nullable String originatingPackageName, @Nullable String installerPackageName, + boolean isOrphaned) { this.initiatingPackageName = initiatingPackageName; - this.isOrphaned = isOrphaned; + this.originatingPackageName = originatingPackageName; this.installerPackageName = installerPackageName; - } - - void dump(IndentingPrintWriter pw) { - pw.printPair("installerPackageName", installerPackageName); - pw.printPair("installInitiatingPackageName", initiatingPackageName); + this.isOrphaned = isOrphaned; } /** * 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); + if (Objects.equals(installerPackageName, this.installerPackageName)) { + return this; + } + return create(initiatingPackageName, originatingPackageName, 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); + if (isOrphaned == this.isOrphaned) { + return this; + } + return create(initiatingPackageName, originatingPackageName, installerPackageName, + isOrphaned); } /** @@ -102,6 +111,7 @@ final class InstallSource { boolean modified = false; String initiatingPackageName = this.initiatingPackageName; + String originatingPackageName = this.originatingPackageName; String installerPackageName = this.installerPackageName; boolean isOrphaned = this.isOrphaned; @@ -109,14 +119,20 @@ final class InstallSource { initiatingPackageName = null; modified = true; } + if (packageName.equals(originatingPackageName)) { + originatingPackageName = null; + modified = true; + } if (packageName.equals(installerPackageName)) { installerPackageName = null; isOrphaned = true; modified = true; } - return modified - ? create(initiatingPackageName, installerPackageName, isOrphaned) - : this; + if (!modified) { + return this; + } + return create(initiatingPackageName, originatingPackageName, installerPackageName, + isOrphaned); } } diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index ed2bb3d53649..6564e71936eb 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -512,6 +512,16 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements } } + String originatingPackageName = null; + if (params.originatingUid != SessionParams.UID_UNKNOWN + && params.originatingUid != callingUid) { + String[] packages = mPm.getPackagesForUid(params.originatingUid); + if (packages != null && packages.length > 0) { + // Choose an arbitrary representative package in the case of a shared UID. + originatingPackageName = packages[0]; + } + } + if (Build.IS_DEBUGGABLE || isDowngradeAllowedForCaller(callingUid)) { params.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE; } else { @@ -624,7 +634,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements } } InstallSource installSource = InstallSource.create(installerPackageName, - requestedInstallerPackageName); + originatingPackageName, requestedInstallerPackageName, false); session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this, mInstallThread.getLooper(), mStagingManager, sessionId, userId, callingUid, installSource, params, createdMillis, diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index feb1271d8c79..631df0ff9845 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -148,6 +148,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { private static final String ATTR_INSTALLER_UID = "installerUid"; private static final String ATTR_INITIATING_PACKAGE_NAME = "installInitiatingPackageName"; + private static final String ATTR_ORIGINATING_PACKAGE_NAME = + "installOriginatingPackageName"; private static final String ATTR_CREATED_MILLIS = "createdMillis"; private static final String ATTR_UPDATED_MILLIS = "updatedMillis"; private static final String ATTR_SESSION_STAGE_DIR = "sessionStageDir"; @@ -1227,7 +1229,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } mInstallerUid = newOwnerAppInfo.uid; - mInstallSource = InstallSource.create(packageName, packageName); + mInstallSource = InstallSource.create(packageName, null, packageName, false); } // Persist the fact that we've sealed ourselves to prevent @@ -2336,7 +2338,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { pw.printPair("userId", userId); pw.printPair("mOriginalInstallerUid", mOriginalInstallerUid); - mInstallSource.dump(pw); + pw.printPair("installerPackageName", mInstallSource.installerPackageName); + pw.printPair("installInitiatingPackageName", mInstallSource.initiatingPackageName); + pw.printPair("installOriginatingPackageName", mInstallSource.originatingPackageName); pw.printPair("mInstallerUid", mInstallerUid); pw.printPair("createdMillis", createdMillis); pw.printPair("updatedMillis", updatedMillis); @@ -2420,6 +2424,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { writeIntAttribute(out, ATTR_INSTALLER_UID, mInstallerUid); writeStringAttribute(out, ATTR_INITIATING_PACKAGE_NAME, mInstallSource.initiatingPackageName); + writeStringAttribute(out, ATTR_ORIGINATING_PACKAGE_NAME, + mInstallSource.originatingPackageName); writeLongAttribute(out, ATTR_CREATED_MILLIS, createdMillis); writeLongAttribute(out, ATTR_UPDATED_MILLIS, updatedMillis); if (stageDir != null) { @@ -2527,6 +2533,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { installerPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, userId)); final String installInitiatingPackageName = readStringAttribute(in, ATTR_INITIATING_PACKAGE_NAME); + final String installOriginatingPackageName = + readStringAttribute(in, ATTR_ORIGINATING_PACKAGE_NAME); final long createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS); long updatedMillis = readLongAttribute(in, ATTR_UPDATED_MILLIS); final String stageDirRaw = readStringAttribute(in, ATTR_SESSION_STAGE_DIR); @@ -2619,7 +2627,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } InstallSource installSource = InstallSource.create(installInitiatingPackageName, - installerPackageName); + installOriginatingPackageName, installerPackageName, false); return new PackageInstallerSession(callback, context, pm, sessionProvider, installerThread, stagingManager, sessionId, userId, installerUid, installSource, params, createdMillis, stageDir, stageCid, diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java index 4fca91a83724..12548918bfcc 100644 --- a/services/core/java/com/android/server/pm/PackageSetting.java +++ b/services/core/java/com/android/server/pm/PackageSetting.java @@ -209,6 +209,8 @@ public final class PackageSetting extends PackageSettingBase { long sourceToken = proto.start(PackageProto.INSTALL_SOURCE); proto.write(PackageProto.InstallSourceProto.INITIATING_PACKAGE_NAME, installSource.initiatingPackageName); + proto.write(PackageProto.InstallSourceProto.ORIGINATING_PACKAGE_NAME, + installSource.originatingPackageName); proto.end(sourceToken); } writeUsersInfoToProto(proto, PackageProto.USERS); diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 66c77f583c57..5f3650c21b8e 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -2848,6 +2848,9 @@ public final class Settings { if (installSource.initiatingPackageName != null) { serializer.attribute(null, "installInitiator", installSource.initiatingPackageName); } + if (installSource.originatingPackageName != null) { + serializer.attribute(null, "installOriginator", installSource.originatingPackageName); + } if (pkg.volumeUuid != null) { serializer.attribute(null, "volumeUuid", pkg.volumeUuid); } @@ -3605,6 +3608,7 @@ public final class Settings { String systemStr = null; String installerPackageName = null; String isOrphaned = null; + String installOriginatingPackageName = null; String installInitiatingPackageName = null; String volumeUuid = null; String categoryHintString = null; @@ -3653,6 +3657,7 @@ public final class Settings { installerPackageName = parser.getAttributeValue(null, "installer"); isOrphaned = parser.getAttributeValue(null, "isOrphaned"); installInitiatingPackageName = parser.getAttributeValue(null, "installInitiator"); + installOriginatingPackageName = parser.getAttributeValue(null, "installOriginator"); volumeUuid = parser.getAttributeValue(null, "volumeUuid"); categoryHintString = parser.getAttributeValue(null, "categoryHint"); if (categoryHintString != null) { @@ -3808,7 +3813,8 @@ public final class Settings { if (packageSetting != null) { packageSetting.uidError = "true".equals(uidError); packageSetting.installSource = InstallSource.create( - installInitiatingPackageName, installerPackageName, "true".equals(isOrphaned)); + installInitiatingPackageName, installOriginatingPackageName, + installerPackageName, "true".equals(isOrphaned)); packageSetting.volumeUuid = volumeUuid; packageSetting.categoryHint = categoryHint; packageSetting.legacyNativeLibraryPathString = legacyNativeLibraryPathStr; 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 3c1044728fcc..b751308a4bb4 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java @@ -156,6 +156,8 @@ public class PackageInstallerSessionTest { if (isMultiPackage) { params.isMultiPackage = true; } + InstallSource installSource = InstallSource.create("testInstaller", null, "testInstaller", + false); return new PackageInstallerSession( /* callback */ null, /* context */null, @@ -166,7 +168,7 @@ public class PackageInstallerSessionTest { /* sessionId */ sessionId, /* userId */ 456, /* installerUid */ -1, - /* installSource */ InstallSource.create("testInstaller", "testInstaller"), + /* installSource */ installSource, /* sessionParams */ params, /* createdMillis */ 0L, /* stageDir */ mTmpDir, |