/**
   * Compute the aggregate policy for all accounts that require it, and record it.
   *
   * <p>The business logic is as follows: min password length take the max password mode take the
   * max (strongest mode) max password fails take the min max screen lock time take the min require
   * remote wipe take the max (logical or) password history take the max (strongest mode) password
   * expiration take the min (strongest mode) password complex chars take the max (strongest mode)
   * encryption take the max (logical or)
   *
   * @return a policy representing the strongest aggregate. If no policy sets are defined, a
   *     lightweight "nothing required" policy will be returned. Never null.
   */
  @VisibleForTesting
  Policy computeAggregatePolicy() {
    boolean policiesFound = false;
    Policy aggregate = new Policy();
    aggregate.mPasswordMinLength = Integer.MIN_VALUE;
    aggregate.mPasswordMode = Integer.MIN_VALUE;
    aggregate.mPasswordMaxFails = Integer.MAX_VALUE;
    aggregate.mPasswordHistory = Integer.MIN_VALUE;
    aggregate.mPasswordExpirationDays = Integer.MAX_VALUE;
    aggregate.mPasswordComplexChars = Integer.MIN_VALUE;
    aggregate.mMaxScreenLockTime = Integer.MAX_VALUE;
    aggregate.mRequireRemoteWipe = false;
    aggregate.mRequireEncryption = false;

    // This can never be supported at this time. It exists only for historic reasons where
    // this was able to be supported prior to the introduction of proper removable storage
    // support for external storage.
    aggregate.mRequireEncryptionExternal = false;

    Cursor c =
        mContext
            .getContentResolver()
            .query(Policy.CONTENT_URI, Policy.CONTENT_PROJECTION, null, null, null);
    Policy policy = new Policy();
    try {
      while (c.moveToNext()) {
        policy.restore(c);
        if (DebugUtils.DEBUG) {
          LogUtils.d(TAG, "Aggregate from: " + policy);
        }
        aggregate.mPasswordMinLength =
            Math.max(policy.mPasswordMinLength, aggregate.mPasswordMinLength);
        aggregate.mPasswordMode = Math.max(policy.mPasswordMode, aggregate.mPasswordMode);
        if (policy.mPasswordMaxFails > 0) {
          aggregate.mPasswordMaxFails =
              Math.min(policy.mPasswordMaxFails, aggregate.mPasswordMaxFails);
        }
        if (policy.mMaxScreenLockTime > 0) {
          aggregate.mMaxScreenLockTime =
              Math.min(policy.mMaxScreenLockTime, aggregate.mMaxScreenLockTime);
        }
        if (policy.mPasswordHistory > 0) {
          aggregate.mPasswordHistory =
              Math.max(policy.mPasswordHistory, aggregate.mPasswordHistory);
        }
        if (policy.mPasswordExpirationDays > 0) {
          aggregate.mPasswordExpirationDays =
              Math.min(policy.mPasswordExpirationDays, aggregate.mPasswordExpirationDays);
        }
        if (policy.mPasswordComplexChars > 0) {
          aggregate.mPasswordComplexChars =
              Math.max(policy.mPasswordComplexChars, aggregate.mPasswordComplexChars);
        }
        aggregate.mRequireRemoteWipe |= policy.mRequireRemoteWipe;
        aggregate.mRequireEncryption |= policy.mRequireEncryption;
        aggregate.mDontAllowCamera |= policy.mDontAllowCamera;
        policiesFound = true;
      }
    } finally {
      c.close();
    }
    if (policiesFound) {
      // final cleanup pass converts any untouched min/max values to zero (not specified)
      if (aggregate.mPasswordMinLength == Integer.MIN_VALUE) aggregate.mPasswordMinLength = 0;
      if (aggregate.mPasswordMode == Integer.MIN_VALUE) aggregate.mPasswordMode = 0;
      if (aggregate.mPasswordMaxFails == Integer.MAX_VALUE) aggregate.mPasswordMaxFails = 0;
      if (aggregate.mMaxScreenLockTime == Integer.MAX_VALUE) aggregate.mMaxScreenLockTime = 0;
      if (aggregate.mPasswordHistory == Integer.MIN_VALUE) aggregate.mPasswordHistory = 0;
      if (aggregate.mPasswordExpirationDays == Integer.MAX_VALUE)
        aggregate.mPasswordExpirationDays = 0;
      if (aggregate.mPasswordComplexChars == Integer.MIN_VALUE) aggregate.mPasswordComplexChars = 0;
      if (DebugUtils.DEBUG) {
        LogUtils.d(TAG, "Calculated Aggregate: " + aggregate);
      }
      return aggregate;
    }
    if (DebugUtils.DEBUG) {
      LogUtils.d(TAG, "Calculated Aggregate: no policy");
    }
    return Policy.NO_POLICY;
  }