content: /*
   * 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 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
       */
      PackageVerificationState(int requiredVerifierUid, InstallParams params) {
          mRequiredVerifierUid = requiredVerifierUid;
          mParams = params;
          mSufficientVerifierUids = new SparseBooleanArray();
          mExtendedTimeout = false;
      }
  
      InstallParams getInstallParams() {
          return mParams;
      }
  
      /**
       * 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;
      }
  }
  