/** * 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; }