Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5835b591 authored by Alan Stokes's avatar Alan Stokes Committed by Android (Google) Code Review
Browse files

Merge "Preserve install initiatior package on uninstall."

parents 8a299f1f 72b7e673
Loading
Loading
Loading
Loading
+80 −22
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.server.pm;

import android.annotation.Nullable;

import com.android.internal.util.Preconditions;

import java.util.Objects;

/**
@@ -29,15 +31,26 @@ 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, null, false);
    static final InstallSource EMPTY = new InstallSource(null, null, null, false, false, null);

    /** 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, true);
    private static final InstallSource EMPTY_ORPHANED = new InstallSource(
            null, null, null, true, false, null);

    /** The package that requested the installation, if known. */
    /**
     * The package that requested the installation, if known. May not correspond to a currently
     * installed package if {@link #isInitiatingPackageUninstalled} is true.
     */
    @Nullable
    final String initiatingPackageName;

    /**
     * The signing details of the initiating package, if known. Always null if
     * {@link #initiatingPackageName} is null.
     */
    @Nullable
    final PackageSignatures initiatingPackageSignatures;

    /**
     * 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
@@ -57,77 +70,121 @@ final class InstallSource {
    /** Indicates if the package that was the installerPackageName has been uninstalled. */
    final boolean isOrphaned;

    /**
     * Indicates if the package in initiatingPackageName has been uninstalled. Always false if
     * {@link #initiatingPackageName} is null.
     */
    final boolean isInitiatingPackageUninstalled;

    static InstallSource create(@Nullable String initiatingPackageName,
            @Nullable String originatingPackageName, @Nullable String installerPackageName) {
        return create(initiatingPackageName, originatingPackageName, installerPackageName,
                false, false);
    }

    static InstallSource create(@Nullable String initiatingPackageName,
            @Nullable String originatingPackageName, @Nullable String installerPackageName,
            boolean isOrphaned) {
            boolean isOrphaned, boolean isInitiatingPackageUninstalled) {
        return createInternal(
                intern(initiatingPackageName),
                intern(originatingPackageName),
                intern(installerPackageName),
                isOrphaned);
                isOrphaned, isInitiatingPackageUninstalled, null);
    }

    private static InstallSource createInternal(@Nullable String initiatingPackageName,
            @Nullable String originatingPackageName, @Nullable String installerPackageName,
            boolean isOrphaned) {
            boolean isOrphaned, boolean isInitiatingPackageUninstalled,
            @Nullable PackageSignatures initiatingPackageSignatures) {
        if (initiatingPackageName == null && originatingPackageName == null
                && installerPackageName == null) {
                && installerPackageName == null && initiatingPackageSignatures == null
                && !isInitiatingPackageUninstalled) {
            return isOrphaned ? EMPTY_ORPHANED : EMPTY;
        }
        return new InstallSource(initiatingPackageName, originatingPackageName,
                installerPackageName, isOrphaned);
                installerPackageName, isOrphaned, isInitiatingPackageUninstalled,
                initiatingPackageSignatures
        );
    }

    private InstallSource(@Nullable String initiatingPackageName,
            @Nullable String originatingPackageName, @Nullable String installerPackageName,
            boolean isOrphaned) {
            boolean isOrphaned, boolean isInitiatingPackageUninstalled,
            @Nullable PackageSignatures initiatingPackageSignatures) {
        if (initiatingPackageName == null) {
            Preconditions.checkArgument(initiatingPackageSignatures == null);
            Preconditions.checkArgument(!isInitiatingPackageUninstalled);
        }
        this.initiatingPackageName = initiatingPackageName;
        this.originatingPackageName = originatingPackageName;
        this.installerPackageName = installerPackageName;
        this.isOrphaned = isOrphaned;
        this.isInitiatingPackageUninstalled = isInitiatingPackageUninstalled;
        this.initiatingPackageSignatures = initiatingPackageSignatures;
    }

    /**
     * Return an InstallSource the same as this one except with the specified installerPackageName.
     * Return an InstallSource the same as this one except with the specified
     * {@link #installerPackageName}.
     */
    InstallSource setInstallerPackage(String installerPackageName) {
    InstallSource setInstallerPackage(@Nullable String installerPackageName) {
        if (Objects.equals(installerPackageName, this.installerPackageName)) {
            return this;
        }
        return createInternal(initiatingPackageName, originatingPackageName,
                intern(installerPackageName), isOrphaned);
                intern(installerPackageName), isOrphaned, isInitiatingPackageUninstalled,
                initiatingPackageSignatures
        );
    }

    /**
     * Return an InstallSource the same as this one except with the specified value for isOrphaned.
     * Return an InstallSource the same as this one except with the specified value for
     * {@link #isOrphaned}.
     */
    InstallSource setIsOrphaned(boolean isOrphaned) {
        if (isOrphaned == this.isOrphaned) {
            return this;
        }
        return createInternal(initiatingPackageName, originatingPackageName, installerPackageName,
                isOrphaned);
                isOrphaned, isInitiatingPackageUninstalled, initiatingPackageSignatures);
    }

    /**
     * Return an InstallSource the same as this one except it does not refer to the specified
     * installer package name (which is being uninstalled).
     * Return an InstallSource the same as this one except with the specified
     * {@link #initiatingPackageSignatures}.
     */
    InstallSource removeInstallerPackage(String packageName) {
    InstallSource setInitiatingPackageSignatures(@Nullable PackageSignatures signatures) {
        if (signatures == initiatingPackageSignatures) {
            return this;
        }
        return createInternal(initiatingPackageName, originatingPackageName, installerPackageName,
                isOrphaned, isInitiatingPackageUninstalled, signatures);
    }

    /**
     * Return an InstallSource the same as this one updated to reflect that the specified installer
     * package name has been uninstalled.
     */
    InstallSource removeInstallerPackage(@Nullable String packageName) {
        if (packageName == null) {
            return this;
        }

        boolean modified = false;
        String initiatingPackageName = this.initiatingPackageName;
        boolean isInitiatingPackageUninstalled = this.isInitiatingPackageUninstalled;
        String originatingPackageName = this.originatingPackageName;
        String installerPackageName = this.installerPackageName;
        boolean isOrphaned = this.isOrphaned;

        if (packageName.equals(initiatingPackageName)) {
            initiatingPackageName = null;
        if (packageName.equals(this.initiatingPackageName)) {
            if (!isInitiatingPackageUninstalled) {
                // In this case we deliberately do not clear the package name (and signatures).
                // We allow an app to retrieve details of its own install initiator even after
                // it has been uninstalled.
                isInitiatingPackageUninstalled = true;
                modified = true;
            }
        }
        if (packageName.equals(originatingPackageName)) {
            originatingPackageName = null;
            modified = true;
@@ -141,8 +198,9 @@ final class InstallSource {
        if (!modified) {
            return this;
        }

        return createInternal(initiatingPackageName, originatingPackageName, installerPackageName,
                isOrphaned);
                isOrphaned, isInitiatingPackageUninstalled, initiatingPackageSignatures);
    }

    @Nullable
+1 −1
Original line number Diff line number Diff line
@@ -635,7 +635,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
            }
        }
        InstallSource installSource = InstallSource.create(installerPackageName,
                originatingPackageName, requestedInstallerPackageName, false);
                originatingPackageName, requestedInstallerPackageName);
        session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this,
                mInstallThread.getLooper(), mStagingManager, sessionId, userId, callingUid,
                installSource, params, createdMillis,
+2 −2
Original line number Diff line number Diff line
@@ -1475,7 +1475,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
                }

                mInstallerUid = uid;
                mInstallSource = InstallSource.create(packageName, null, packageName, false);
                mInstallSource = InstallSource.create(packageName, null, packageName);
            }
        } catch (PackageManager.NameNotFoundException e) {
            onSessionTransferStatus(statusReceiver, packageName,
@@ -3138,7 +3138,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
        }

        InstallSource installSource = InstallSource.create(installInitiatingPackageName,
                installOriginatingPackageName, installerPackageName, false);
                installOriginatingPackageName, installerPackageName);
        return new PackageInstallerSession(callback, context, pm, sessionProvider,
                installerThread, stagingManager, sessionId, userId, installerUid,
                installSource, params, createdMillis, stageDir, stageCid, fileInfosArray,
+26 −12
Original line number Diff line number Diff line
@@ -15158,10 +15158,10 @@ public class PackageManagerService extends IPackageManager.Stub
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings");
        final String pkgName = pkg.getPackageName();
        final InstallSource installSource = installArgs.installSource;
        final String installerPackageName = installSource.installerPackageName;
        final int[] installedForUsers = res.origUsers;
        final int installReason = installArgs.installReason;
        InstallSource installSource = installArgs.installSource;
        final String installerPackageName = installSource.installerPackageName;
        if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + pkg.getCodePath());
        synchronized (mLock) {
@@ -15207,6 +15207,14 @@ public class PackageManagerService extends IPackageManager.Stub
                    ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, userId, installerPackageName);
                }
                if (installSource.initiatingPackageName != null) {
                    final PackageSetting ips = mSettings.mPackages.get(
                            installSource.initiatingPackageName);
                    if (ips != null) {
                        installSource = installSource.setInitiatingPackageSignatures(
                                ips.signatures);
                    }
                }
                ps.setInstallSource(installSource);
                mSettings.addInstallerPackageNames(installSource);
@@ -19976,6 +19984,11 @@ public class PackageManagerService extends IPackageManager.Stub
                }
            }
            if (installSource.isInitiatingPackageUninstalled) {
                // TODO(b/146555198) Allow the app itself to see the info
                // (at least for non-instant apps)
                initiatingPackageName = null;
            } else {
                // All installSource strings are interned, so == is ok here
                if (installSource.initiatingPackageName == installSource.installerPackageName) {
                    // The installer and initiator will often be the same, and when they are
@@ -19987,8 +20000,9 @@ public class PackageManagerService extends IPackageManager.Stub
                    if (ps == null || shouldFilterApplicationLocked(ps, callingUid, userId)) {
                        initiatingPackageName = null;
                    }
                }
            }
            originatingPackageName = installSource.originatingPackageName;
            if (originatingPackageName != null) {
                final PackageSetting ps = mSettings.mPackages.get(originatingPackageName);
+18 −1
Original line number Diff line number Diff line
@@ -2819,6 +2819,9 @@ public final class Settings {
        if (installSource.initiatingPackageName != null) {
            serializer.attribute(null, "installInitiator", installSource.initiatingPackageName);
        }
        if (installSource.isInitiatingPackageUninstalled) {
            serializer.attribute(null, "installInitiatorUninstalled", "true");
        }
        if (installSource.originatingPackageName != null) {
            serializer.attribute(null, "installOriginator", installSource.originatingPackageName);
        }
@@ -2836,6 +2839,11 @@ public final class Settings {

        pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);

        if (installSource.initiatingPackageSignatures != null) {
            installSource.initiatingPackageSignatures.writeXml(
                    serializer, "install-initiator-sigs", mPastSignatures);
        }

        writePermissionsLPr(serializer, pkg.getPermissionsState().getInstallPermissionStates());

        writeSigningKeySetLPr(serializer, pkg.keySetData);
@@ -3571,6 +3579,7 @@ public final class Settings {
        String isOrphaned = null;
        String installOriginatingPackageName = null;
        String installInitiatingPackageName = null;
        String installInitiatorUninstalled = null;
        String volumeUuid = null;
        String categoryHintString = null;
        String updateAvailable = null;
@@ -3616,6 +3625,8 @@ public final class Settings {
            isOrphaned = parser.getAttributeValue(null, "isOrphaned");
            installInitiatingPackageName = parser.getAttributeValue(null, "installInitiator");
            installOriginatingPackageName = parser.getAttributeValue(null, "installOriginator");
            installInitiatorUninstalled = parser.getAttributeValue(null,
                    "installInitiatorUninstalled");
            volumeUuid = parser.getAttributeValue(null, "volumeUuid");
            categoryHintString = parser.getAttributeValue(null, "categoryHint");
            if (categoryHintString != null) {
@@ -3772,7 +3783,8 @@ public final class Settings {
            packageSetting.uidError = "true".equals(uidError);
            InstallSource installSource = InstallSource.create(
                    installInitiatingPackageName, installOriginatingPackageName,
                    installerPackageName, "true".equals(isOrphaned));
                    installerPackageName, "true".equals(isOrphaned),
                    "true".equals(installInitiatorUninstalled));
            packageSetting.installSource = installSource;
            packageSetting.volumeUuid = volumeUuid;
            packageSetting.categoryHint = categoryHint;
@@ -3849,6 +3861,11 @@ public final class Settings {
                        mKeySetRefs.put(id, 1);
                    }
                    packageSetting.keySetData.addDefinedKeySet(id, alias);
                } else if (tagName.equals("install-initiator-sigs")) {
                    final PackageSignatures signatures = new PackageSignatures();
                    signatures.readXml(parser, mPastSignatures);
                    packageSetting.installSource =
                            packageSetting.installSource.setInitiatingPackageSignatures(signatures);
                } else if (tagName.equals(TAG_DOMAIN_VERIFICATION)) {
                    readDomainVerificationLPw(parser, packageSetting);
                } else {
Loading