/*
 * Copyright (C) 2010 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.email;

import android.app.admin.DeviceAdminInfo;
import android.app.admin.DeviceAdminReceiver;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;

import com.android.email.NotificationController;
import com.android.email.NotificationControllerCreatorHolder;
import com.android.email.provider.AccountReconciler;
import com.android.email.provider.EmailProvider;
import com.android.email.service.EmailBroadcastProcessorService;
import com.android.email.service.EmailServiceUtils;
import com.android.emailcommon.Logging;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.AccountColumns;
import com.android.emailcommon.provider.EmailContent.PolicyColumns;
import com.android.emailcommon.provider.Policy;
import com.android.emailcommon.utility.TextUtilities;
import com.android.emailcommon.utility.Utility;
import com.android.mail.utils.LogUtils;
import com.google.common.annotations.VisibleForTesting;

import java.util.ArrayList;

/**
 * Utility functions to support reading and writing security policies, and handshaking the device
 * into and out of various security states.
 */
public class SecurityPolicy {
    private static final String TAG = "Email";
    private static SecurityPolicy sInstance = null;
    private Context mContext;
    private DevicePolicyManager mDPM;
    private final ComponentName mAdminName;
    private Policy mAggregatePolicy;

    // Messages used for DevicePolicyManager callbacks
    private static final int DEVICE_ADMIN_MESSAGE_ENABLED = 1;
    private static final int DEVICE_ADMIN_MESSAGE_DISABLED = 2;
    private static final int DEVICE_ADMIN_MESSAGE_PASSWORD_CHANGED = 3;
    private static final int DEVICE_ADMIN_MESSAGE_PASSWORD_EXPIRING = 4;

    private static final String HAS_PASSWORD_EXPIRATION =
        PolicyColumns.PASSWORD_EXPIRATION_DAYS + ">0";

    /**
     * Get the security policy instance
     */
    public synchronized static SecurityPolicy getInstance(Context context) {
        if (sInstance == null) {
            sInstance = new SecurityPolicy(context.getApplicationContext());
        }
        return sInstance;
    }

    /**
     * Private constructor (one time only)
     */
    private SecurityPolicy(Context context) {
        mContext = context.getApplicationContext();
        mDPM = null;
        mAdminName = new ComponentName(context, PolicyAdmin.class);
        mAggregatePolicy = null;
    }

    /**
     * For testing only: Inject context into already-created instance
     */
    /* package */ void setContext(Context context) {
        mContext = context;
    }

    /**
     * Compute the aggregate policy for all accounts that require it, and record it.
     *
     * 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;
    }

    /**
     * Return updated aggregate policy, from cached value if possible
     */
    public synchronized Policy getAggregatePolicy() {
        if (mAggregatePolicy == null) {
            mAggregatePolicy = computeAggregatePolicy();
        }
        return mAggregatePolicy;
    }

    /**
     * Get the dpm.  This mainly allows us to make some utility calls without it, for testing.
     */
    /* package */ synchronized DevicePolicyManager getDPM() {
        if (mDPM == null) {
            mDPM = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
        }
        return mDPM;
    }

    /**
     * API: Report that policies may have been updated due to rewriting values in an Account; we
     * clear the aggregate policy (so it can be recomputed) and set the policies in the DPM
     */
    public synchronized void policiesUpdated() {
        mAggregatePolicy = null;
        setActivePolicies();
    }

    /**
     * API: Report that policies may have been updated *and* the caller vouches that the
     * change is a reduction in policies.  This forces an immediate change to device state.
     * Typically used when deleting accounts, although we may use it for server-side policy
     * rollbacks.
     */
    public void reducePolicies() {
        if (DebugUtils.DEBUG) {
            LogUtils.d(TAG, "reducePolicies");
        }
        policiesUpdated();
    }

    /**
     * API: Query used to determine if a given policy is "active" (the device is operating at
     * the required security level).
     *
     * @param policy the policies requested, or null to check aggregate stored policies
     * @return true if the requested policies are active, false if not.
     */
    public boolean isActive(Policy policy) {
        int reasons = getInactiveReasons(policy);
        if (DebugUtils.DEBUG && (reasons != 0)) {
            StringBuilder sb = new StringBuilder("isActive for " + policy + ": ");
            sb.append("FALSE -> ");
            if ((reasons & INACTIVE_NEED_ACTIVATION) != 0) {
                sb.append("no_admin ");
            }
            if ((reasons & INACTIVE_NEED_CONFIGURATION) != 0) {
                sb.append("config ");
            }
            if ((reasons & INACTIVE_NEED_PASSWORD) != 0) {
                sb.append("password ");
            }
            if ((reasons & INACTIVE_NEED_ENCRYPTION) != 0) {
                sb.append("encryption ");
            }
            if ((reasons & INACTIVE_PROTOCOL_POLICIES) != 0) {
                sb.append("protocol ");
            }
            LogUtils.d(TAG, sb.toString());
        }
        return reasons == 0;
    }

    /**
     * Return bits from isActive:  Device Policy Manager has not been activated
     */
    public final static int INACTIVE_NEED_ACTIVATION = 1;

    /**
     * Return bits from isActive:  Some required configuration is not correct (no user action).
     */
    public final static int INACTIVE_NEED_CONFIGURATION = 2;

    /**
     * Return bits from isActive:  Password needs to be set or updated
     */
    public final static int INACTIVE_NEED_PASSWORD = 4;

    /**
     * Return bits from isActive:  Encryption has not be enabled
     */
    public final static int INACTIVE_NEED_ENCRYPTION = 8;

    /**
     * Return bits from isActive:  Protocol-specific policies cannot be enforced
     */
    public final static int INACTIVE_PROTOCOL_POLICIES = 16;

    /**
     * API: Query used to determine if a given policy is "active" (the device is operating at
     * the required security level).
     *
     * This can be used when syncing a specific account, by passing a specific set of policies
     * for that account.  Or, it can be used at any time to compare the device
     * state against the aggregate set of device policies stored in all accounts.
     *
     * This method is for queries only, and does not trigger any change in device state.
     *
     * NOTE:  If there are multiple accounts with password expiration policies, the device
     * password will be set to expire in the shortest required interval (most secure).  This method
     * will return 'false' as soon as the password expires - irrespective of which account caused
     * the expiration.  In other words, all accounts (that require expiration) will run/stop
     * based on the requirements of the account with the shortest interval.
     *
     * @param policy the policies requested, or null to check aggregate stored policies
     * @return zero if the requested policies are active, non-zero bits indicates that more work
     * is needed (typically, by the user) before the required security polices are fully active.
     */
    public int getInactiveReasons(Policy policy) {
        // select aggregate set if needed
        if (policy == null) {
            policy = getAggregatePolicy();
        }
        // quick check for the "empty set" of no policies
        if (policy == Policy.NO_POLICY) {
            return 0;
        }
        int reasons = 0;
        DevicePolicyManager dpm = getDPM();
        if (isActiveAdmin()) {
            // check each policy explicitly
            if (policy.mPasswordMinLength > 0) {
                if (dpm.getPasswordMinimumLength(mAdminName) < policy.mPasswordMinLength) {
                    reasons |= INACTIVE_NEED_PASSWORD;
                }
            }
            if (policy.mPasswordMode > 0) {
                if (dpm.getPasswordQuality(mAdminName) < policy.getDPManagerPasswordQuality()) {
                    reasons |= INACTIVE_NEED_PASSWORD;
                }
                if (!dpm.isActivePasswordSufficient()) {
                    reasons |= INACTIVE_NEED_PASSWORD;
                }
            }
            if (policy.mMaxScreenLockTime > 0) {
                // Note, we use seconds, dpm uses milliseconds
                if (dpm.getMaximumTimeToLock(mAdminName) > policy.mMaxScreenLockTime * 1000) {
                    reasons |= INACTIVE_NEED_CONFIGURATION;
                }
            }
            if (policy.mPasswordExpirationDays > 0) {
                // confirm that expirations are currently set
                long currentTimeout = dpm.getPasswordExpirationTimeout(mAdminName);
                if (currentTimeout == 0
                        || currentTimeout > policy.getDPManagerPasswordExpirationTimeout()) {
                    reasons |= INACTIVE_NEED_PASSWORD;
                }
                // confirm that the current password hasn't expired
                long expirationDate = dpm.getPasswordExpiration(mAdminName);
                long timeUntilExpiration = expirationDate - System.currentTimeMillis();
                boolean expired = timeUntilExpiration < 0;
                if (expired) {
                    reasons |= INACTIVE_NEED_PASSWORD;
                }
            }
            if (policy.mPasswordHistory > 0) {
                if (dpm.getPasswordHistoryLength(mAdminName) < policy.mPasswordHistory) {
                    // There's no user action for changes here; this is just a configuration change
                    reasons |= INACTIVE_NEED_CONFIGURATION;
                }
            }
            if (policy.mPasswordComplexChars > 0) {
                if (dpm.getPasswordMinimumNonLetter(mAdminName) < policy.mPasswordComplexChars) {
                    reasons |= INACTIVE_NEED_PASSWORD;
                }
            }
            if (policy.mRequireEncryption) {
                int encryptionStatus = getDPM().getStorageEncryptionStatus();
                if (encryptionStatus != DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE) {
                    reasons |= INACTIVE_NEED_ENCRYPTION;
                }
            }
            if (policy.mDontAllowCamera && !dpm.getCameraDisabled(mAdminName)) {
                reasons |= INACTIVE_NEED_CONFIGURATION;
            }
            // password failures are counted locally - no test required here
            // no check required for remote wipe (it's supported, if we're the admin)

            if (policy.mProtocolPoliciesUnsupported != null) {
                reasons |= INACTIVE_PROTOCOL_POLICIES;
            }

            // If we made it all the way, reasons == 0 here.  Otherwise it's a list of grievances.
            return reasons;
        }
        // return false, not active
        return INACTIVE_NEED_ACTIVATION;
    }

    /**
     * Set the requested security level based on the aggregate set of requests.
     * If the set is empty, we release our device administration.  If the set is non-empty,
     * we only proceed if we are already active as an admin.
     */
    public void setActivePolicies() {
        DevicePolicyManager dpm = getDPM();
        // compute aggregate set of policies
        Policy aggregatePolicy = getAggregatePolicy();
        // if empty set, detach from policy manager
        if (aggregatePolicy == Policy.NO_POLICY) {
            if (DebugUtils.DEBUG) {
                LogUtils.d(TAG, "setActivePolicies: none, remove admin");
            }
            dpm.removeActiveAdmin(mAdminName);
        } else if (isActiveAdmin()) {
            if (DebugUtils.DEBUG) {
                LogUtils.d(TAG, "setActivePolicies: " + aggregatePolicy);
            }
            // set each policy in the policy manager
            // password mode & length
            dpm.setPasswordQuality(mAdminName, aggregatePolicy.getDPManagerPasswordQuality());
            dpm.setPasswordMinimumLength(mAdminName, aggregatePolicy.mPasswordMinLength);
            // screen lock time
            dpm.setMaximumTimeToLock(mAdminName, aggregatePolicy.mMaxScreenLockTime * 1000);
            // local wipe (failed passwords limit)
            dpm.setMaximumFailedPasswordsForWipe(mAdminName, aggregatePolicy.mPasswordMaxFails);
            // password expiration (days until a password expires).  API takes mSec.
            dpm.setPasswordExpirationTimeout(mAdminName,
                    aggregatePolicy.getDPManagerPasswordExpirationTimeout());
            // password history length (number of previous passwords that may not be reused)
            dpm.setPasswordHistoryLength(mAdminName, aggregatePolicy.mPasswordHistory);
            // password minimum complex characters.
            // Note, in Exchange, "complex chars" simply means "non alpha", but in the DPM,
            // setting the quality to complex also defaults min symbols=1 and min numeric=1.
            // We always / safely clear minSymbols & minNumeric to zero (there is no policy
            // configuration in which we explicitly require a minimum number of digits or symbols.)
            dpm.setPasswordMinimumSymbols(mAdminName, 0);
            dpm.setPasswordMinimumNumeric(mAdminName, 0);
            dpm.setPasswordMinimumNonLetter(mAdminName, aggregatePolicy.mPasswordComplexChars);
            // Device capabilities
            try {
                // If we are running in a managed policy, it is a securityException to even
                // call setCameraDisabled(), if is disabled is false. We have to swallow
                // the exception here.
                dpm.setCameraDisabled(mAdminName, aggregatePolicy.mDontAllowCamera);
            } catch (SecurityException e) {
                LogUtils.d(TAG, "SecurityException in setCameraDisabled, nothing changed");
            }

            // encryption required
            dpm.setStorageEncryption(mAdminName, aggregatePolicy.mRequireEncryption);
        }
    }

    /**
     * Convenience method; see javadoc below
     */
    public static void setAccountHoldFlag(Context context, long accountId, boolean newState) {
        Account account = Account.restoreAccountWithId(context, accountId);
        if (account != null) {
            setAccountHoldFlag(context, account, newState);
            if (newState) {
                // Make sure there's a notification up
                final NotificationController nc =
                        NotificationControllerCreatorHolder.getInstance(context);
                nc.showSecurityNeededNotification(account);
            }
        }
    }

    /**
     * API: Set/Clear the "hold" flag in any account.  This flag serves a dual purpose:
     * Setting it gives us an indication that it was blocked, and clearing it gives EAS a
     * signal to try syncing again.
     * @param context context
     * @param account the account whose hold flag is to be set/cleared
     * @param newState true = security hold, false = free to sync
     */
    public static void setAccountHoldFlag(Context context, Account account, boolean newState) {
        if (newState) {
            account.mFlags |= Account.FLAGS_SECURITY_HOLD;
        } else {
            account.mFlags &= ~Account.FLAGS_SECURITY_HOLD;
        }
        ContentValues cv = new ContentValues();
        cv.put(AccountColumns.FLAGS, account.mFlags);
        account.update(context, cv);
    }

    /**
     * API: Sync service should call this any time a sync fails due to isActive() returning false.
     * This will kick off the notify-acquire-admin-state process and/or increase the security level.
     * The caller needs to write the required policies into this account before making this call.
     * Should not be called from UI thread - uses DB lookups to prepare new notifications
     *
     * @param accountId the account for which sync cannot proceed
     */
    public void policiesRequired(long accountId) {
        Account account = Account.restoreAccountWithId(mContext, accountId);
        // In case the account has been deleted, just return
        if (account == null) return;
        if (account.mPolicyKey == 0) return;
        Policy policy = Policy.restorePolicyWithId(mContext, account.mPolicyKey);
        if (policy == null) return;
        if (DebugUtils.DEBUG) {
            LogUtils.d(TAG, "policiesRequired for " + account.mDisplayName + ": " + policy);
        }

        // Mark the account as "on hold".
        setAccountHoldFlag(mContext, account, true);

        // Put up an appropriate notification
        final NotificationController nc =
                NotificationControllerCreatorHolder.getInstance(mContext);
        if (policy.mProtocolPoliciesUnsupported == null) {
            nc.showSecurityNeededNotification(account);
        } else {
            nc.showSecurityUnsupportedNotification(account);
        }
    }

    public static void clearAccountPolicy(Context context, Account account) {
        setAccountPolicy(context, account, null, null);
    }

    /**
     * Set the policy for an account atomically; this also removes any other policy associated with
     * the account and sets the policy key for the account.  If policy is null, the policyKey is
     * set to 0 and the securitySyncKey to null.  Also, update the account object to reflect the
     * current policyKey and securitySyncKey
     * @param context the caller's context
     * @param account the account whose policy is to be set
     * @param policy the policy to set, or null if we're clearing the policy
     * @param securitySyncKey the security sync key for this account (ignored if policy is null)
     */
    public static void setAccountPolicy(Context context, Account account, Policy policy,
            String securitySyncKey) {
        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();

        // Make sure this is a valid policy set
        if (policy != null) {
            policy.normalize();
            // Add the new policy (no account will yet reference this)
            ops.add(ContentProviderOperation.newInsert(
                    Policy.CONTENT_URI).withValues(policy.toContentValues()).build());
            // Make the policyKey of the account our newly created policy, and set the sync key
            ops.add(ContentProviderOperation.newUpdate(
                    ContentUris.withAppendedId(Account.CONTENT_URI, account.mId))
                    .withValueBackReference(AccountColumns.POLICY_KEY, 0)
                    .withValue(AccountColumns.SECURITY_SYNC_KEY, securitySyncKey)
                    .build());
        } else {
            ops.add(ContentProviderOperation.newUpdate(
                    ContentUris.withAppendedId(Account.CONTENT_URI, account.mId))
                    .withValue(AccountColumns.SECURITY_SYNC_KEY, null)
                    .withValue(AccountColumns.POLICY_KEY, 0)
                    .build());
        }

        // Delete the previous policy associated with this account, if any
        if (account.mPolicyKey > 0) {
            ops.add(ContentProviderOperation.newDelete(
                    ContentUris.withAppendedId(
                            Policy.CONTENT_URI, account.mPolicyKey)).build());
        }

        try {
            context.getContentResolver().applyBatch(EmailContent.AUTHORITY, ops);
            account.refresh(context);
            syncAccount(context, account);
        } catch (RemoteException e) {
           // This is fatal to a remote process
            throw new IllegalStateException("Exception setting account policy.");
        } catch (OperationApplicationException e) {
            // Can't happen; our provider doesn't throw this exception
        }
    }

    private static void syncAccount(final Context context, final Account account) {
        final EmailServiceUtils.EmailServiceInfo info =
                EmailServiceUtils.getServiceInfo(context, account.getProtocol(context));
        final android.accounts.Account amAccount =
                new android.accounts.Account(account.mEmailAddress, info.accountType);
        final Bundle extras = new Bundle(3);
        extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
        extras.putBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, true);
        extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
        ContentResolver.requestSync(amAccount, EmailContent.AUTHORITY, extras);
        LogUtils.i(TAG, "requestSync SecurityPolicy syncAccount %s, %s", account.toString(),
                extras.toString());
    }

    public void syncAccount(final Account account) {
        syncAccount(mContext, account);
    }

    public void setAccountPolicy(long accountId, Policy policy, String securityKey,
            boolean notify) {
        Account account = Account.restoreAccountWithId(mContext, accountId);
        // In case the account has been deleted, just return
        if (account == null) {
            return;
        }
        Policy oldPolicy = null;
        if (account.mPolicyKey > 0) {
            oldPolicy = Policy.restorePolicyWithId(mContext, account.mPolicyKey);
        }

        // If attachment policies have changed, fix up any affected attachment records
        if (oldPolicy != null && securityKey != null) {
            if ((oldPolicy.mDontAllowAttachments != policy.mDontAllowAttachments) ||
                    (oldPolicy.mMaxAttachmentSize != policy.mMaxAttachmentSize)) {
                Policy.setAttachmentFlagsForNewPolicy(mContext, account, policy);
            }
        }

        boolean policyChanged = (oldPolicy == null) || !oldPolicy.equals(policy);
        if (!policyChanged && (TextUtilities.stringOrNullEquals(securityKey,
                account.mSecuritySyncKey))) {
            LogUtils.d(Logging.LOG_TAG, "setAccountPolicy; policy unchanged");
        } else {
            setAccountPolicy(mContext, account, policy, securityKey);
            policiesUpdated();
        }

        boolean setHold = false;
        final NotificationController nc =
                NotificationControllerCreatorHolder.getInstance(mContext);
        if (policy.mProtocolPoliciesUnsupported != null) {
            // We can't support this, reasons in unsupportedRemotePolicies
            LogUtils.d(Logging.LOG_TAG,
                    "Notify policies for " + account.mDisplayName + " not supported.");
            setHold = true;
            if (notify) {
                nc.showSecurityUnsupportedNotification(account);
            }
            // Erase data
            Uri uri = EmailProvider.uiUri("uiaccountdata", accountId);
            mContext.getContentResolver().delete(uri, null, null);
        } else if (isActive(policy)) {
            if (policyChanged) {
                LogUtils.d(Logging.LOG_TAG, "Notify policies for " + account.mDisplayName
                        + " changed.");
                if (notify) {
                    // Notify that policies changed
                    nc.showSecurityChangedNotification(account);
                }
            } else {
                LogUtils.d(Logging.LOG_TAG, "Policy is active and unchanged; do not notify.");
            }
        } else {
            setHold = true;
            LogUtils.d(Logging.LOG_TAG, "Notify policies for " + account.mDisplayName +
                    " are not being enforced.");
            if (notify) {
                // Put up a notification
                nc.showSecurityNeededNotification(account);
            }
        }
        // Set/clear the account hold.
        setAccountHoldFlag(mContext, account, setHold);
    }

    /**
     * Called from the notification's intent receiver to register that the notification can be
     * cleared now.
     */
    public void clearNotification() {
        final NotificationController nc =
                NotificationControllerCreatorHolder.getInstance(mContext);

        nc.cancelSecurityNeededNotification();
    }

    /**
     * API: Remote wipe (from server).  This is final, there is no confirmation.  It will only
     * return to the caller if there is an unexpected failure.  The wipe includes external storage.
     */
    public void remoteWipe() {
        DevicePolicyManager dpm = getDPM();
        if (dpm.isAdminActive(mAdminName)) {
            dpm.wipeData(DevicePolicyManager.WIPE_EXTERNAL_STORAGE);
        } else {
            LogUtils.d(Logging.LOG_TAG, "Could not remote wipe because not device admin.");
        }
    }
    /**
     * If we are not the active device admin, try to become so.
     *
     * Also checks for any policies that we have added during the lifetime of this app.
     * This catches the case where the user granted an earlier (smaller) set of policies
     * but an app upgrade requires that new policies be granted.
     *
     * @return true if we are already active, false if we are not
     */
    public boolean isActiveAdmin() {
        DevicePolicyManager dpm = getDPM();
        return dpm.isAdminActive(mAdminName)
                && dpm.hasGrantedPolicy(mAdminName, DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)
                && dpm.hasGrantedPolicy(mAdminName, DeviceAdminInfo.USES_ENCRYPTED_STORAGE)
                && dpm.hasGrantedPolicy(mAdminName, DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA);
    }

    /**
     * Report admin component name - for making calls into device policy manager
     */
    public ComponentName getAdminComponent() {
        return mAdminName;
    }

    /**
     * Delete all accounts whose security flags aren't zero (i.e. they have security enabled).
     * This method is synchronous, so it should normally be called within a worker thread (the
     * exception being for unit tests)
     *
     * @param context the caller's context
     */
    /*package*/ void deleteSecuredAccounts(Context context) {
        ContentResolver cr = context.getContentResolver();
        // Find all accounts with security and delete them
        Cursor c = cr.query(Account.CONTENT_URI, EmailContent.ID_PROJECTION,
                Account.SECURITY_NONZERO_SELECTION, null, null);
        try {
            LogUtils.w(TAG, "Email administration disabled; deleting " + c.getCount() +
                    " secured account(s)");
            while (c.moveToNext()) {
                long accountId = c.getLong(EmailContent.ID_PROJECTION_COLUMN);
                Uri uri = EmailProvider.uiUri("uiaccount", accountId);
                cr.delete(uri, null, null);
            }
        } finally {
            c.close();
        }
        policiesUpdated();
        AccountReconciler.reconcileAccounts(context);
    }

    /**
     * Internal handler for enabled->disabled transitions.  Deletes all secured accounts.
     * Must call from worker thread, not on UI thread.
     */
    /*package*/ void onAdminEnabled(boolean isEnabled) {
        if (!isEnabled) {
            deleteSecuredAccounts(mContext);
        }
    }

    /**
     * Handle password expiration - if any accounts appear to have triggered this, put up
     * warnings, or even shut them down.
     *
     * NOTE:  If there are multiple accounts with password expiration policies, the device
     * password will be set to expire in the shortest required interval (most secure).  The logic
     * in this method operates based on the aggregate setting - irrespective of which account caused
     * the expiration.  In other words, all accounts (that require expiration) will run/stop
     * based on the requirements of the account with the shortest interval.
     */
    private void onPasswordExpiring(Context context) {
        // 1.  Do we have any accounts that matter here?
        long nextExpiringAccountId = findShortestExpiration(context);

        // 2.  If not, exit immediately
        if (nextExpiringAccountId == -1) {
            return;
        }

        // 3.  If yes, are we warning or expired?
        long expirationDate = getDPM().getPasswordExpiration(mAdminName);
        long timeUntilExpiration = expirationDate - System.currentTimeMillis();
        boolean expired = timeUntilExpiration < 0;
        final NotificationController nc =
                NotificationControllerCreatorHolder.getInstance(context);
        if (!expired) {
            // 4.  If warning, simply put up a generic notification and report that it came from
            // the shortest-expiring account.
            nc.showPasswordExpiringNotificationSynchronous(nextExpiringAccountId);
        } else {
            // 5.  Actually expired - find all accounts that expire passwords, and wipe them
            boolean wiped = wipeExpiredAccounts(context);
            if (wiped) {
                nc.showPasswordExpiredNotificationSynchronous(nextExpiringAccountId);
            }
        }
    }

    /**
     * Find the account with the shortest expiration time.  This is always assumed to be
     * the account that forces the password to be refreshed.
     * @return -1 if no expirations, or accountId if one is found
     */
    @VisibleForTesting
    /*package*/ static long findShortestExpiration(Context context) {
        long policyId = Utility.getFirstRowLong(context, Policy.CONTENT_URI, Policy.ID_PROJECTION,
                HAS_PASSWORD_EXPIRATION, null, PolicyColumns.PASSWORD_EXPIRATION_DAYS + " ASC",
                EmailContent.ID_PROJECTION_COLUMN, -1L);
        if (policyId < 0) return -1L;
        return Policy.getAccountIdWithPolicyKey(context, policyId);
    }

    /**
     * For all accounts that require password expiration, put them in security hold and wipe
     * their data.
     * @param context context
     * @return true if one or more accounts were wiped
     */
    @VisibleForTesting
    /*package*/ static boolean wipeExpiredAccounts(Context context) {
        boolean result = false;
        Cursor c = context.getContentResolver().query(Policy.CONTENT_URI,
                Policy.ID_PROJECTION, HAS_PASSWORD_EXPIRATION, null, null);
        if (c == null) {
            return false;
        }
        try {
            while (c.moveToNext()) {
                long policyId = c.getLong(Policy.ID_PROJECTION_COLUMN);
                long accountId = Policy.getAccountIdWithPolicyKey(context, policyId);
                if (accountId < 0) continue;
                Account account = Account.restoreAccountWithId(context, accountId);
                if (account != null) {
                    // Mark the account as "on hold".
                    setAccountHoldFlag(context, account, true);
                    // Erase data
                    Uri uri = EmailProvider.uiUri("uiaccountdata", accountId);
                    context.getContentResolver().delete(uri, null, null);
                    // Report one or more were found
                    result = true;
                }
            }
        } finally {
            c.close();
        }
        return result;
    }

    /**
     * Callback from EmailBroadcastProcessorService.  This provides the workers for the
     * DeviceAdminReceiver calls.  These should perform the work directly and not use async
     * threads for completion.
     */
    public static void onDeviceAdminReceiverMessage(Context context, int message) {
        SecurityPolicy instance = SecurityPolicy.getInstance(context);
        switch (message) {
            case DEVICE_ADMIN_MESSAGE_ENABLED:
                instance.onAdminEnabled(true);
                break;
            case DEVICE_ADMIN_MESSAGE_DISABLED:
                instance.onAdminEnabled(false);
                break;
            case DEVICE_ADMIN_MESSAGE_PASSWORD_CHANGED:
                // TODO make a small helper for this
                // Clear security holds (if any)
                Account.clearSecurityHoldOnAllAccounts(context);
                // Cancel any active notifications (if any are posted)
                final NotificationController nc =
                        NotificationControllerCreatorHolder.getInstance(context);

                nc.cancelPasswordExpirationNotifications();
                break;
            case DEVICE_ADMIN_MESSAGE_PASSWORD_EXPIRING:
                instance.onPasswordExpiring(instance.mContext);
                break;
        }
    }

    /**
     * Device Policy administrator.  This is primarily a listener for device state changes.
     * Note:  This is instantiated by incoming messages.
     * Note:  This is actually a BroadcastReceiver and must remain within the guidelines required
     *        for proper behavior, including avoidance of ANRs.
     * Note:  We do not implement onPasswordFailed() because the default behavior of the
     *        DevicePolicyManager - complete local wipe after 'n' failures - is sufficient.
     */
    public static class PolicyAdmin extends DeviceAdminReceiver {

        /**
         * Called after the administrator is first enabled.
         */
        @Override
        public void onEnabled(Context context, Intent intent) {
            EmailBroadcastProcessorService.processDevicePolicyMessage(context,
                    DEVICE_ADMIN_MESSAGE_ENABLED);
        }

        /**
         * Called prior to the administrator being disabled.
         */
        @Override
        public void onDisabled(Context context, Intent intent) {
            EmailBroadcastProcessorService.processDevicePolicyMessage(context,
                    DEVICE_ADMIN_MESSAGE_DISABLED);
        }

        /**
         * Called when the user asks to disable administration; we return a warning string that
         * will be presented to the user
         */
        @Override
        public CharSequence onDisableRequested(Context context, Intent intent) {
            return context.getString(R.string.disable_admin_warning);
        }

        /**
         * Called after the user has changed their password.
         */
        @Override
        public void onPasswordChanged(Context context, Intent intent) {
            EmailBroadcastProcessorService.processDevicePolicyMessage(context,
                    DEVICE_ADMIN_MESSAGE_PASSWORD_CHANGED);
        }

        /**
         * Called when device password is expiring
         */
        @Override
        public void onPasswordExpiring(Context context, Intent intent) {
            EmailBroadcastProcessorService.processDevicePolicyMessage(context,
                    DEVICE_ADMIN_MESSAGE_PASSWORD_EXPIRING);
        }
    }
}
