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

Commit 041a4ee8 authored by JW Wang's avatar JW Wang
Browse files

Move the code about APK verification (4/n)

Bug: 161121612
Test: atest CtsAtomicInstallTestCases
Test: atest CtsPackageInstallTestCases
Test: atest CtsStagedInstallHostTestCases
Test: atest CtsInstallHostTestCases
Change-Id: I3d31cdef94e1b6ff634c9da03bd7a62a840e497a
parent fe3fd370
Loading
Loading
Loading
Loading
+29 −96
Original line number Diff line number Diff line
@@ -2524,34 +2524,25 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {

    private void verifyNonStaged()
            throws PackageManagerException {
        final VerificationParams verifyingSession = prepareForVerification();
        if (isMultiPackage()) {
            final List<PackageInstallerSession> childSessions = getChildSessions();
            List<VerificationParams> verifyingChildSessions =
                    new ArrayList<>(childSessions.size());
            boolean success = true;
            PackageManagerException failure = null;
            for (int i = 0; i < childSessions.size(); ++i) {
                final PackageInstallerSession session = childSessions.get(i);
                try {
                    final VerificationParams verifyingChildSession =
                            session.prepareForVerification();
                    verifyingChildSessions.add(verifyingChildSession);
                } catch (PackageManagerException e) {
                    failure = e;
                    success = false;
                }
        synchronized (mLock) {
            if (mDestroyed) {
                throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
                        "Session destroyed");
            }
            if (!success) {
                sendOnPackageInstalled(mContext, getRemoteStatusReceiver(), sessionId,
                        isInstallerDeviceOwnerOrAffiliatedProfileOwner(), userId, null,
                        failure.error, failure.getLocalizedMessage(), null);
                return;
            // TODO(b/161121612): merge mRelinquished and mInPreRebootVerification as they serve
            //   the same purpose to prevent staging files from being deleted while verification
            //   is in progress.
            mRelinquished = true;
        }
            verifyingSession.verifyStage(verifyingChildSessions);
        mSessionProvider.getSessionVerifier().verifyNonStaged(this, (error, msg) -> {
            mHandler.post(() -> {
                if (error == INSTALL_SUCCEEDED) {
                    onVerificationComplete();
                } else {
            verifyingSession.verifyStage();
                    onSessionVerificationFailure(error, msg);
                }
            });
        });
    }

    private void install() {
@@ -2600,32 +2591,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
        }
    }

    /**
     * Stages this session for verification and returns a
     * {@link VerificationParams} representing this new staged state or null
     * in case permissions need to be requested before verification can proceed.
     */
    @NonNull
    private VerificationParams prepareForVerification() throws PackageManagerException {
        assertNotLocked("makeSessionActive");

        synchronized (mLock) {
            if (mRelinquished) {
                throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
                        "Session relinquished");
            }
            if (mDestroyed) {
                throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
                        "Session destroyed");
            }
            if (!mSealed) {
                throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
                        "Session not sealed");
            }
            return makeVerificationParamsLocked();
        }
    }

    private void sendPendingUserActionIntent() {
        // User needs to confirm installation;
        // give installer an intent they can use to involve
@@ -2641,50 +2606,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
        closeInternal(false);
    }

    @GuardedBy("mLock")
    @Nullable
    /**
     * Returns a {@link com.android.server.pm.VerificationParams}
     */
    private VerificationParams makeVerificationParamsLocked() {
        final IPackageInstallObserver2 localObserver;
        if (!hasParentSessionId()) {
            // Avoid attaching this observer to child session since they won't use it.
            localObserver = new IPackageInstallObserver2.Stub() {
                @Override
                public void onUserActionRequired(Intent intent) {
                    throw new IllegalStateException();
                }

                @Override
                public void onPackageInstalled(String basePackageName, int returnCode, String msg,
                        Bundle extras) {
                    mHandler.post(() -> {
                        if (returnCode == INSTALL_SUCCEEDED) {
                            onVerificationComplete();
                        } else {
                            onSessionVerificationFailure(returnCode, msg);
                        }
                    });
                }
            };
        } else {
            localObserver = null;
        }

        final UserHandle user;
        if ((params.installFlags & PackageManager.INSTALL_ALL_USERS) != 0) {
            user = UserHandle.ALL;
        } else {
            user = new UserHandle(userId);
        }

        mRelinquished = true;

        return new VerificationParams(user, stageDir, localObserver, params,
                mInstallSource, mInstallerUid, mSigningDetails, sessionId, mPackageLite, mPm);
    }

    @WorkerThread
    private void onVerificationComplete() {
        // APK verification is done. Continue the installation depending on whether it is a
@@ -3610,6 +3531,18 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
        }
    }

    SigningDetails getSigningDetails() {
        synchronized (mLock) {
            return mSigningDetails;
        }
    }

    PackageLite getPackageLite() {
        synchronized (mLock) {
            return mPackageLite;
        }
    }

    private static String getRelativePath(File file, File base) throws IOException {
        final String pathStr = file.getAbsolutePath();
        final String baseStr = base.getAbsolutePath();
+60 −0
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ import android.apex.ApexInfoList;
import android.apex.ApexSessionInfo;
import android.apex.ApexSessionParams;
import android.content.Context;
import android.content.Intent;
import android.content.pm.IPackageInstallObserver2;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageManager;
@@ -31,9 +33,11 @@ import android.content.pm.parsing.result.ParseResult;
import android.content.pm.parsing.result.ParseTypeImpl;
import android.content.rollback.RollbackInfo;
import android.content.rollback.RollbackManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.IntArray;
import android.util.Slog;
import android.util.apk.ApkSignatureVerifier;
@@ -76,6 +80,62 @@ final class PackageSessionVerifier {
        mHandler = new Handler(looper);
    }

    /**
     * Runs verifications that are common to both staged and non-staged sessions.
     */
    public void verifyNonStaged(PackageInstallerSession session, Callback callback) {
        mHandler.post(() -> {
            try {
                verifyAPK(session, callback);
            } catch (PackageManagerException e) {
                callback.onResult(e.error, e.getMessage());
            }
        });
    }

    /**
     * Runs verifications particular to APK. This includes APEX sessions since an APEX can also
     * be treated as APK.
     */
    private void verifyAPK(PackageInstallerSession session, Callback callback)
            throws PackageManagerException {
        final IPackageInstallObserver2 observer = new IPackageInstallObserver2.Stub() {
            @Override
            public void onUserActionRequired(Intent intent) {
                throw new IllegalStateException();
            }
            @Override
            public void onPackageInstalled(String basePackageName, int returnCode, String msg,
                    Bundle extras) {
                callback.onResult(returnCode, msg);
            }
        };
        final VerificationParams verifyingSession = makeVerificationParams(session, observer);
        if (session.isMultiPackage()) {
            final List<PackageInstallerSession> childSessions = session.getChildSessions();
            List<VerificationParams> verifyingChildSessions = new ArrayList<>(childSessions.size());
            for (PackageInstallerSession child : childSessions) {
                verifyingChildSessions.add(makeVerificationParams(child, null));
            }
            verifyingSession.verifyStage(verifyingChildSessions);
        } else {
            verifyingSession.verifyStage();
        }
    }

    private VerificationParams makeVerificationParams(
            PackageInstallerSession session, IPackageInstallObserver2 observer) {
        final UserHandle user;
        if ((session.params.installFlags & PackageManager.INSTALL_ALL_USERS) != 0) {
            user = UserHandle.ALL;
        } else {
            user = new UserHandle(session.userId);
        }
        return new VerificationParams(user, session.stageDir, observer, session.params,
                session.getInstallSource(), session.getInstallerUid(), session.getSigningDetails(),
                session.sessionId, session.getPackageLite(), mPm);
    }

    /**
     * Starts pre-reboot verification for the staged-session. This operation is broken into the
     * following phases: