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

Commit 57f15314 authored by Patrick Baumann's avatar Patrick Baumann
Browse files

Allow system installer to deny update ownership

This change introduces a means for system installers with the
INSTALL_PACKAGES or INSTALL_PACKAGE_UPDATES permissions to provide a
list of packages that are opted out of update ownership. The list may be
updated via updates to the package that provides it. Packages that
provide such a list will be unable to request update ownership of any
packages.

Bug: 293210067
Test: Manual; tested various scenarios per b/293210067
Change-Id: I544f23dcfa9a7eefc49f1d72fb612a11ebea98bc
parent bc28899e
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -233,6 +233,24 @@ public abstract class PackageManager {
    public static final String PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT =
            "android.camera.PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT";

    /**
     * Application level {@link android.content.pm.PackageManager.Property PackageManager
     * .Property} for a privileged system installer to define a list of up to 500 packages that
     * should not have their updates owned by any installer. The list must be provided via a default
     * XML resource with the following format:
     *
     * <pre>
     * &lt;deny-ownership&gt;PACKAGE_NAME&lt;/deny-ownership&gt;
     * &lt;deny-ownership&gt;PACKAGE_NAME&lt;/deny-ownership&gt;
     * </pre>
     *
     * <b>NOTE:</b> Installers that provide this property will not granted update ownership for any
     * packages that they request update ownership of.
     * @hide
     */
    public static final String PROPERTY_LEGACY_UPDATE_OWNERSHIP_DENYLIST =
            "android.app.PROPERTY_LEGACY_UPDATE_OWNERSHIP_DENYLIST";

    /**
     * A property value set within the manifest.
     * <p>
+26 −2
Original line number Diff line number Diff line
@@ -166,6 +166,7 @@ import com.android.internal.util.CollectionUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.EventLogTags;
import com.android.server.LocalManagerRegistry;
import com.android.server.SystemConfig;
import com.android.server.art.model.DexoptParams;
import com.android.server.art.model.DexoptResult;
import com.android.server.pm.Installer.LegacyDexoptDisabledException;
@@ -230,6 +231,7 @@ final class InstallPackageHelper {
    private final ViewCompiler mViewCompiler;
    private final SharedLibrariesImpl mSharedLibraries;
    private final PackageManagerServiceInjector mInjector;
    private final UpdateOwnershipHelper mUpdateOwnershipHelper;

    // TODO(b/198166813): remove PMS dependency
    InstallPackageHelper(PackageManagerService pm, AppDataHelper appDataHelper) {
@@ -247,6 +249,7 @@ final class InstallPackageHelper {
        mPackageAbiHelper = pm.mInjector.getAbiHelper();
        mViewCompiler = pm.mInjector.getViewCompiler();
        mSharedLibraries = pm.mInjector.getSharedLibrariesImpl();
        mUpdateOwnershipHelper = pm.mInjector.getUpdateOwnershipHelper();
    }

    InstallPackageHelper(PackageManagerService pm) {
@@ -332,6 +335,8 @@ final class InstallPackageHelper {
        final String updateOwnerFromSysconfig = isApex || !pkgSetting.isSystem() ? null
                : mPm.mInjector.getSystemConfig().getSystemAppUpdateOwnerPackageName(
                        parsedPackage.getPackageName());
        final boolean isUpdateOwnershipDenylisted =
                mUpdateOwnershipHelper.isUpdateOwnershipDenylisted(parsedPackage.getPackageName());
        final boolean isUpdateOwnershipEnabled = oldUpdateOwner != null;

        // For standard install (install via session), the installSource isn't null.
@@ -367,6 +372,9 @@ final class InstallPackageHelper {
                        & PackageManager.INSTALL_REQUEST_UPDATE_OWNERSHIP) != 0;
                final boolean isSameUpdateOwner =
                        TextUtils.equals(oldUpdateOwner, installSource.mInstallerPackageName);
                final boolean isInstallerUpdateOwnerDenylistProvider =
                        mUpdateOwnershipHelper.isUpdateOwnershipDenyListProvider(
                                installSource.mUpdateOwnerPackageName);

                // Here we handle the update owner for the package, and the rules are:
                // -. Only enabling update ownership enforcement on initial installation if the
@@ -374,13 +382,16 @@ final class InstallPackageHelper {
                // -. Once the installer changes and users agree to proceed, clear the update
                //    owner (package state in other users are taken into account as well).
                if (!isUpdate) {
                    if (!isRequestUpdateOwnership) {
                    if (!isRequestUpdateOwnership
                            || isUpdateOwnershipDenylisted
                            || isInstallerUpdateOwnerDenylistProvider) {
                        installSource = installSource.setUpdateOwnerPackageName(null);
                    } else if ((!isUpdateOwnershipEnabled && pkgAlreadyExists)
                            || (isUpdateOwnershipEnabled && !isSameUpdateOwner)) {
                        installSource = installSource.setUpdateOwnerPackageName(null);
                    }
                } else if (!isSameUpdateOwner || !isUpdateOwnershipEnabled) {
                } else if (!isSameUpdateOwner
                        || !isUpdateOwnershipEnabled) {
                    installSource = installSource.setUpdateOwnerPackageName(null);
                }
            }
@@ -473,6 +484,19 @@ final class InstallPackageHelper {
            pkgSetting.setLoadingProgress(1f);
        }

        ArraySet<String> listItems = mUpdateOwnershipHelper.readUpdateOwnerDenyList(pkgSetting);
        if (listItems != null && !listItems.isEmpty()) {
            mUpdateOwnershipHelper.addToUpdateOwnerDenyList(pkgSetting.getPackageName(), listItems);
            for (String unownedPackage : listItems) {
                PackageSetting unownedSetting = mPm.mSettings.getPackageLPr(unownedPackage);
                SystemConfig config = SystemConfig.getInstance();
                if (unownedSetting != null
                        && config.getSystemAppUpdateOwnerPackageName(unownedPackage) == null) {
                    unownedSetting.setUpdateOwnerPackage(null);
                }
            }
        }

        return pkg;
    }

+2 −1
Original line number Diff line number Diff line
@@ -1607,7 +1607,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService
                (i, pm) -> new SharedLibrariesImpl(pm, i),
                (i, pm) -> new CrossProfileIntentFilterHelper(i.getSettings(),
                        i.getUserManagerService(), i.getLock(), i.getUserManagerInternal(),
                        context));
                        context),
                (i, pm) -> new UpdateOwnershipHelper());

        if (Build.VERSION.SDK_INT <= 0) {
            Slog.w(TAG, "**** ro.build.version.sdk not set!");
+9 −1
Original line number Diff line number Diff line
@@ -144,6 +144,7 @@ public class PackageManagerServiceInjector {
    private final Singleton<IBackupManager> mIBackupManager;
    private final Singleton<SharedLibrariesImpl> mSharedLibrariesProducer;
    private final Singleton<CrossProfileIntentFilterHelper> mCrossProfileIntentFilterHelperProducer;
    private final Singleton<UpdateOwnershipHelper> mUpdateOwnershipHelperProducer;

    PackageManagerServiceInjector(Context context, PackageManagerTracedLock lock,
            Installer installer, Object installLock, PackageAbiHelper abiHelper,
@@ -183,7 +184,8 @@ public class PackageManagerServiceInjector {
            Producer<BackgroundDexOptService> backgroundDexOptService,
            Producer<IBackupManager> iBackupManager,
            Producer<SharedLibrariesImpl> sharedLibrariesProducer,
            Producer<CrossProfileIntentFilterHelper> crossProfileIntentFilterHelperProducer) {
            Producer<CrossProfileIntentFilterHelper> crossProfileIntentFilterHelperProducer,
            Producer<UpdateOwnershipHelper> updateOwnershipHelperProducer) {
        mContext = context;
        mLock = lock;
        mInstaller = installer;
@@ -238,6 +240,7 @@ public class PackageManagerServiceInjector {
        mSharedLibrariesProducer = new Singleton<>(sharedLibrariesProducer);
        mCrossProfileIntentFilterHelperProducer = new Singleton<>(
                crossProfileIntentFilterHelperProducer);
        mUpdateOwnershipHelperProducer = new Singleton<>(updateOwnershipHelperProducer);
    }

    /**
@@ -423,6 +426,11 @@ public class PackageManagerServiceInjector {
        return mSharedLibrariesProducer.get(this, mPackageManager);
    }

    public UpdateOwnershipHelper getUpdateOwnershipHelper() {
        return mUpdateOwnershipHelperProducer.get(this, mPackageManager);
    }


    /** Provides an abstraction to static access to system state. */
    public interface SystemWrapper {
        void disablePackageCaches();
+1 −0
Original line number Diff line number Diff line
@@ -312,6 +312,7 @@ final class RemovePackageHelper {
            synchronized (mPm.mLock) {
                mPm.mDomainVerificationManager.clearPackage(deletedPs.getPackageName());
                mPm.mSettings.getKeySetManagerService().removeAppKeySetDataLPw(packageName);
                mPm.mInjector.getUpdateOwnershipHelper().removeUpdateOwnerDenyList(packageName);
                final Computer snapshot = mPm.snapshotComputer();
                mPm.mAppsFilter.removePackage(snapshot,
                        snapshot.getPackageStateInternal(packageName));
Loading