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

Commit e980804d authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Bring install and install-multiple into parity.

This ensures that both are using (almost) identical logic when
deciding what installs to proceed with.  Installs from "pm" for all
users now run as OWNER, and rely solely on INSTALL_ALL_USERS to
express intent.  This keeps install session notifications simple.

Since installer UID can vary from installer package name, start
persisting the UID.  Also parse some missing flags for install
sessions.

Bug: 17469392
Change-Id: I6d89b1a787aa2024cc4bebf6b9c29317c358e147
parent d6adcef9
Loading
Loading
Loading
Loading
+22 −16
Original line number Diff line number Diff line
@@ -865,7 +865,7 @@ public final class Pm {
    }

    private void runInstall() {
        int installFlags = PackageManager.INSTALL_ALL_USERS;
        int installFlags = 0;
        int userId = UserHandle.USER_ALL;
        String installerPackageName = null;

@@ -912,17 +912,17 @@ public final class Pm {
                abi = checkAbiArgument(nextOptionData());
            } else if (opt.equals("--user")) {
                userId = Integer.parseInt(nextOptionData());
                if (userId == UserHandle.USER_ALL) {
                    installFlags |= PackageManager.INSTALL_ALL_USERS;
                } else {
                    installFlags &= ~PackageManager.INSTALL_ALL_USERS;
                }
            } else {
                System.err.println("Error: Unknown option: " + opt);
                return;
            }
        }

        if (userId == UserHandle.USER_ALL) {
            userId = UserHandle.USER_OWNER;
            installFlags |= PackageManager.INSTALL_ALL_USERS;
        }

        final Uri verificationURI;
        final Uri originatingURI;
        final Uri referrerURI;
@@ -961,8 +961,8 @@ public final class Pm {
            VerificationParams verificationParams = new VerificationParams(verificationURI,
                    originatingURI, referrerURI, VerificationParams.NO_UID, null);

            mPm.installPackageAsUser(apkFilePath, obs.getBinder(), installFlags, installerPackageName,
                    verificationParams, abi, userId);
            mPm.installPackageAsUser(apkFilePath, obs.getBinder(), installFlags,
                    installerPackageName, verificationParams, abi, userId);

            synchronized (obs) {
                while (!obs.finished) {
@@ -986,10 +986,10 @@ public final class Pm {
    }

    private void runInstallCreate() throws RemoteException {
        int userId = UserHandle.USER_ALL;
        String installerPackageName = null;

        final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
        params.installFlags = PackageManager.INSTALL_ALL_USERS;

        String opt;
        while ((opt = nextOption()) != null) {
@@ -1010,6 +1010,10 @@ public final class Pm {
                params.installFlags |= PackageManager.INSTALL_INTERNAL;
            } else if (opt.equals("-d")) {
                params.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
            } else if (opt.equals("--originating-uri")) {
                params.originatingUri = Uri.parse(nextOptionData());
            } else if (opt.equals("--referrer")) {
                params.referrerUri = Uri.parse(nextOptionData());
            } else if (opt.equals("-p")) {
                params.mode = SessionParams.MODE_INHERIT_EXISTING;
                params.appPackageName = nextOptionData();
@@ -1020,13 +1024,19 @@ public final class Pm {
                params.setSize(Long.parseLong(nextOptionData()));
            } else if (opt.equals("--abi")) {
                params.abiOverride = checkAbiArgument(nextOptionData());
            } else if (opt.equals("--user")) {
                userId = Integer.parseInt(nextOptionData());
            } else {
                throw new IllegalArgumentException("Unknown option " + opt);
            }
        }

        final int sessionId = mInstaller.createSession(params, installerPackageName,
                UserHandle.USER_OWNER);
        if (userId == UserHandle.USER_ALL) {
            userId = UserHandle.USER_OWNER;
            params.installFlags |= PackageManager.INSTALL_ALL_USERS;
        }

        final int sessionId = mInstaller.createSession(params, installerPackageName, userId);

        // NOTE: adb depends on parsing this string
        System.out.println("Success: created install session [" + sessionId + "]");
@@ -1692,11 +1702,7 @@ public final class Pm {
        }

        public Intent getResult() {
            try {
                return mResult.poll(30, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            return mResult.poll();
        }
    }

+16 −20
Original line number Diff line number Diff line
@@ -16,9 +16,6 @@

package com.android.server.pm;

import static android.content.pm.PackageManager.INSTALL_ALL_USERS;
import static android.content.pm.PackageManager.INSTALL_FROM_ADB;
import static android.content.pm.PackageManager.INSTALL_REPLACE_EXISTING;
import static com.android.internal.util.XmlUtils.readBitmapAttribute;
import static com.android.internal.util.XmlUtils.readBooleanAttribute;
import static com.android.internal.util.XmlUtils.readIntAttribute;
@@ -105,7 +102,7 @@ import java.util.Random;

public class PackageInstallerService extends IPackageInstaller.Stub {
    private static final String TAG = "PackageInstaller";
    private static final boolean LOGD = true;
    private static final boolean LOGD = false;

    // TODO: remove outstanding sessions when installer package goes away
    // TODO: notify listeners in other users when package has been installed there
@@ -117,6 +114,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
    private static final String ATTR_SESSION_ID = "sessionId";
    private static final String ATTR_USER_ID = "userId";
    private static final String ATTR_INSTALLER_PACKAGE_NAME = "installerPackageName";
    private static final String ATTR_INSTALLER_UID = "installerUid";
    private static final String ATTR_CREATED_MILLIS = "createdMillis";
    private static final String ATTR_SESSION_STAGE_DIR = "sessionStageDir";
    private static final String ATTR_SESSION_STAGE_CID = "sessionStageCid";
@@ -336,6 +334,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
        final int sessionId = readIntAttribute(in, ATTR_SESSION_ID);
        final int userId = readIntAttribute(in, ATTR_USER_ID);
        final String installerPackageName = readStringAttribute(in, ATTR_INSTALLER_PACKAGE_NAME);
        final int installerUid = readIntAttribute(in, ATTR_INSTALLER_UID,
                mPm.getPackageUid(installerPackageName, userId));
        final long createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
        final String stageDirRaw = readStringAttribute(in, ATTR_SESSION_STAGE_DIR);
        final File stageDir = (stageDirRaw != null) ? new File(stageDirRaw) : null;
@@ -357,8 +357,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
        params.abiOverride = readStringAttribute(in, ATTR_ABI_OVERRIDE);

        return new PackageInstallerSession(mInternalCallback, mContext, mPm,
                mInstallThread.getLooper(), sessionId, userId, installerPackageName, params,
                createdMillis, stageDir, stageCid, prepared, sealed);
                mInstallThread.getLooper(), sessionId, userId, installerPackageName, installerUid,
                params, createdMillis, stageDir, stageCid, prepared, sealed);
    }

    private void writeSessionsLocked() {
@@ -398,6 +398,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
        writeIntAttribute(out, ATTR_USER_ID, session.userId);
        writeStringAttribute(out, ATTR_INSTALLER_PACKAGE_NAME,
                session.installerPackageName);
        writeIntAttribute(out, ATTR_INSTALLER_UID, session.installerUid);
        writeLongAttribute(out, ATTR_CREATED_MILLIS, session.createdMillis);
        if (session.stageDir != null) {
            writeStringAttribute(out, ATTR_SESSION_STAGE_DIR,
@@ -446,26 +447,21 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
    private int createSessionInternal(SessionParams params, String installerPackageName, int userId)
            throws IOException {
        final int callingUid = Binder.getCallingUid();
        mPm.enforceCrossUserPermission(callingUid, userId, true, false, "createSession");
        mPm.enforceCrossUserPermission(callingUid, userId, true, true, "createSession");

        if (mPm.isUserRestricted(UserHandle.getUserId(callingUid),
                UserManager.DISALLOW_INSTALL_APPS)) {
        if (mPm.isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
            throw new SecurityException("User restriction prevents installing");
        }

        // TODO: double check all possible install flags

        if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) {
            installerPackageName = "com.android.shell";

            params.installFlags |= INSTALL_FROM_ADB;
            params.installFlags |= PackageManager.INSTALL_FROM_ADB;

        } else {
            mAppOps.checkPackage(callingUid, installerPackageName);

            params.installFlags &= ~INSTALL_FROM_ADB;
            params.installFlags &= ~INSTALL_ALL_USERS;
            params.installFlags |= INSTALL_REPLACE_EXISTING;
            params.installFlags &= ~PackageManager.INSTALL_FROM_ADB;
            params.installFlags &= ~PackageManager.INSTALL_ALL_USERS;
            params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
        }

        // Defensively resize giant app icons
@@ -532,8 +528,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
            }

            session = new PackageInstallerSession(mInternalCallback, mContext, mPm,
                    mInstallThread.getLooper(), sessionId, userId, installerPackageName, params,
                    createdMillis, stageDir, stageCid, false, false);
                    mInstallThread.getLooper(), sessionId, userId, installerPackageName, callingUid,
                    params, createdMillis, stageDir, stageCid, false, false);
            mSessions.put(sessionId, session);
        }

@@ -688,7 +684,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub {

    @Override
    public void uninstall(String packageName, int flags, IntentSender statusReceiver, int userId) {
        mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "uninstall");
        mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, true, "uninstall");

        final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext,
                statusReceiver, packageName);
+14 −13
Original line number Diff line number Diff line
@@ -96,6 +96,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
    final int sessionId;
    final int userId;
    final String installerPackageName;
    final int installerUid;
    final SessionParams params;
    final long createdMillis;

@@ -103,9 +104,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
    final File stageDir;
    final String stageCid;

    /** Note that UID is not persisted; it's always derived at runtime. */
    final int installerUid;

    private final AtomicInteger mActiveCount = new AtomicInteger();

    private final Object mLock = new Object();
@@ -186,7 +184,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {

    public PackageInstallerSession(PackageInstallerService.InternalCallback callback,
            Context context, PackageManagerService pm, Looper looper, int sessionId, int userId,
            String installerPackageName, SessionParams params, long createdMillis,
            String installerPackageName, int installerUid, SessionParams params, long createdMillis,
            File stageDir, String stageCid, boolean prepared, boolean sealed) {
        mCallback = callback;
        mContext = context;
@@ -196,6 +194,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
        this.sessionId = sessionId;
        this.userId = userId;
        this.installerPackageName = installerPackageName;
        this.installerUid = installerUid;
        this.params = params;
        this.createdMillis = createdMillis;
        this.stageDir = stageDir;
@@ -209,11 +208,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
        mPrepared = prepared;
        mSealed = sealed;

        // Always derived at runtime
        installerUid = mPm.getPackageUid(installerPackageName, userId);

        if (mPm.checkPermission(android.Manifest.permission.INSTALL_PACKAGES,
                installerPackageName) == PackageManager.PERMISSION_GRANTED) {
        if ((mPm.checkUidPermission(android.Manifest.permission.INSTALL_PACKAGES, installerUid)
                == PackageManager.PERMISSION_GRANTED) || (installerUid == Process.ROOT_UID)) {
            mPermissionsAccepted = true;
        } else {
            mPermissionsAccepted = false;
@@ -537,8 +533,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
            }
        };

        mPm.installStage(mPackageName, stageDir, stageCid, localObserver,
                params, installerPackageName, installerUid, new UserHandle(userId));
        final UserHandle user;
        if ((params.installFlags & PackageManager.INSTALL_ALL_USERS) != 0) {
            user = UserHandle.ALL;
        } else {
            user = new UserHandle(userId);
        }

        mPm.installStage(mPackageName, stageDir, stageCid, localObserver, params,
                installerPackageName, installerUid, user);
    }

    /**
@@ -764,8 +767,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {

    private static void extractNativeLibraries(File packageDir, String abiOverride)
            throws PackageManagerException {
        if (LOGD) Slog.v(TAG, "extractNativeLibraries()");

        // Always start from a clean slate
        final File libDir = new File(packageDir, NativeLibraryHelper.LIB_DIR_NAME);
        NativeLibraryHelper.removeNativeBinariesFromDirLI(libDir, true);
+18 −21
Original line number Diff line number Diff line
@@ -7668,16 +7668,11 @@ public class PackageManagerService extends IPackageManager.Stub {
    public void installPackageAsUser(String originPath, IPackageInstallObserver2 observer,
            int installFlags, String installerPackageName, VerificationParams verificationParams,
            String packageAbiOverride, int userId) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
                null);
        if (UserHandle.getCallingUserId() != userId) {
            mContext.enforceCallingOrSelfPermission(
                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
                    "installPackage " + userId);
        }
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);
        final int callingUid = Binder.getCallingUid();
        enforceCrossUserPermission(callingUid, userId, true, true, "installPackageAsUser");
        final File originFile = new File(originPath);
        final int uid = Binder.getCallingUid();
        if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
            try {
                if (observer != null) {
@@ -7688,6 +7683,17 @@ public class PackageManagerService extends IPackageManager.Stub {
            return;
        }
        if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) {
            installFlags |= PackageManager.INSTALL_FROM_ADB;
        } else {
            // Caller holds INSTALL_PACKAGES permission, so we're less strict
            // about installerPackageName.
            installFlags &= ~PackageManager.INSTALL_FROM_ADB;
            installFlags &= ~PackageManager.INSTALL_ALL_USERS;
        }
        UserHandle user;
        if ((installFlags & PackageManager.INSTALL_ALL_USERS) != 0) {
            user = UserHandle.ALL;
@@ -7695,22 +7701,13 @@ public class PackageManagerService extends IPackageManager.Stub {
            user = new UserHandle(userId);
        }
        final int filteredInstallFlags;
        if (uid == Process.SHELL_UID || uid == 0) {
            if (DEBUG_INSTALL) {
                Slog.v(TAG, "Install from ADB");
            }
            filteredInstallFlags = installFlags | PackageManager.INSTALL_FROM_ADB;
        } else {
            filteredInstallFlags = installFlags & ~PackageManager.INSTALL_FROM_ADB;
        }
        verificationParams.setInstallerUid(uid);
        verificationParams.setInstallerUid(callingUid);
        final File originFile = new File(originPath);
        final OriginInfo origin = OriginInfo.fromUntrustedFile(originFile);
        final Message msg = mHandler.obtainMessage(INIT_COPY);
        msg.obj = new InstallParams(origin, observer, filteredInstallFlags,
        msg.obj = new InstallParams(origin, observer, installFlags,
                installerPackageName, verificationParams, user, packageAbiOverride);
        mHandler.sendMessage(msg);
    }