/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.pm; import com.android.server.pm.PackageManagerService.InstallArgs; import android.content.pm.PackageManager; import android.util.SparseBooleanArray; /** * Tracks the package verification state for a particular package. Each package * verification has a required verifier and zero or more sufficient verifiers. * Only one of the sufficient verifier list must return affirmative to allow the * package to be considered verified. If there are zero sufficient verifiers, * then package verification is considered complete. */ class PackageVerificationState { private final InstallArgs mArgs; private final SparseBooleanArray mSufficientVerifierUids; private final int mRequiredVerifierUid; private boolean mSufficientVerificationComplete; private boolean mSufficientVerificationPassed; private boolean mRequiredVerificationComplete; private boolean mRequiredVerificationPassed; private boolean mExtendedTimeout; /** * Create a new package verification state where {@code requiredVerifierUid} * is the user ID for the package that must reply affirmative before things * can continue. * * @param requiredVerifierUid user ID of required package verifier * @param args */ public PackageVerificationState(int requiredVerifierUid, InstallArgs args) { mRequiredVerifierUid = requiredVerifierUid; mArgs = args; mSufficientVerifierUids = new SparseBooleanArray(); mExtendedTimeout = false; } public InstallArgs getInstallArgs() { return mArgs; } /** * Add a verifier which is added to our sufficient list. * * @param uid user ID of sufficient verifier */ public void addSufficientVerifier(int uid) { mSufficientVerifierUids.put(uid, true); } /** * Should be called when a verification is received from an agent so the * state of the package verification can be tracked. * * @param uid user ID of the verifying agent * @return {@code true} if the verifying agent actually exists in our list */ public boolean setVerifierResponse(int uid, int code) { if (uid == mRequiredVerifierUid) { mRequiredVerificationComplete = true; switch (code) { case PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT: mSufficientVerifierUids.clear(); // fall through case PackageManager.VERIFICATION_ALLOW: mRequiredVerificationPassed = true; break; default: mRequiredVerificationPassed = false; } return true; } else { if (mSufficientVerifierUids.get(uid)) { if (code == PackageManager.VERIFICATION_ALLOW) { mSufficientVerificationComplete = true; mSufficientVerificationPassed = true; } mSufficientVerifierUids.delete(uid); if (mSufficientVerifierUids.size() == 0) { mSufficientVerificationComplete = true; } return true; } } return false; } /** * Returns whether verification is considered complete. This means that the * required verifier and at least one of the sufficient verifiers has * returned a positive verification. * * @return {@code true} when verification is considered complete */ public boolean isVerificationComplete() { if (!mRequiredVerificationComplete) { return false; } if (mSufficientVerifierUids.size() == 0) { return true; } return mSufficientVerificationComplete; } /** * Returns whether installation should be allowed. This should only be * called after {@link #isVerificationComplete()} returns {@code true}. * * @return {@code true} if installation should be allowed */ public boolean isInstallAllowed() { if (!mRequiredVerificationPassed) { return false; } if (mSufficientVerificationComplete) { return mSufficientVerificationPassed; } return true; } /** * Extend the timeout for this Package to be verified. */ public void extendTimeout() { if (!mExtendedTimeout) { mExtendedTimeout = true; } } /** * Returns whether the timeout was extended for verification. * * @return {@code true} if a timeout was already extended. */ public boolean timeoutExtended() { return mExtendedTimeout; } }