blob: ea7af9031bd0f034c9f7a499a186e181e65f0bde [file] [log] [blame]
/*
* 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 android.content.pm.PackageManager;
import android.util.SparseBooleanArray;
import com.android.server.pm.PackageManagerService.InstallParams;
/**
* 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 InstallParams mParams;
private final SparseBooleanArray mSufficientVerifierUids;
private int mRequiredVerifierUid;
private boolean mSufficientVerificationComplete;
private boolean mSufficientVerificationPassed;
private boolean mRequiredVerificationComplete;
private boolean mRequiredVerificationPassed;
private boolean mExtendedTimeout;
private boolean mIntegrityVerificationComplete;
/**
* Create a new package verification state where {@code requiredVerifierUid} is the user ID for
* the package that must reply affirmative before things can continue.
*/
PackageVerificationState(InstallParams params) {
mParams = params;
mSufficientVerifierUids = new SparseBooleanArray();
mExtendedTimeout = false;
}
InstallParams getInstallParams() {
return mParams;
}
/** Sets the user ID of the required package verifier. */
void setRequiredVerifierUid(int uid) {
mRequiredVerifierUid = uid;
}
/**
* Add a verifier which is added to our sufficient list.
*
* @param uid user ID of sufficient verifier
*/
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
*/
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
*/
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
*/
boolean isInstallAllowed() {
if (!mRequiredVerificationPassed) {
return false;
}
if (mSufficientVerificationComplete) {
return mSufficientVerificationPassed;
}
return true;
}
/** Extend the timeout for this Package to be verified. */
void extendTimeout() {
if (!mExtendedTimeout) {
mExtendedTimeout = true;
}
}
/**
* Returns whether the timeout was extended for verification.
*
* @return {@code true} if a timeout was already extended.
*/
boolean timeoutExtended() {
return mExtendedTimeout;
}
void setIntegrityVerificationResult(int code) {
mIntegrityVerificationComplete = true;
}
boolean isIntegrityVerificationComplete() {
return mIntegrityVerificationComplete;
}
boolean areAllVerificationsComplete() {
return mIntegrityVerificationComplete && isVerificationComplete();
}
}