/*
 * 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.settings;

import android.app.Activity;
import android.app.StatusBarManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources.NotFoundException;
import android.media.AudioManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.storage.IStorageManager;
import android.os.storage.StorageManager;
import android.provider.Settings;
import android.sysprop.VoldProperties;
import android.telecom.TelecomManager;
import android.telephony.TelephonyManager;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.android.internal.telephony.PhoneConstants;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternView;
import com.android.internal.widget.LockPatternView.Cell;
import com.android.internal.widget.LockPatternView.DisplayMode;
import com.android.settings.widget.ImeAwareEditText;

import java.util.List;

/**
 * Settings screens to show the UI flows for encrypting/decrypting the device.
 *
 * This may be started via adb for debugging the UI layout, without having to go through
 * encryption flows everytime. It should be noted that starting the activity in this manner
 * is only useful for verifying UI-correctness - the behavior will not be identical.
 * <pre>
 * $ adb shell pm enable com.android.settings/.CryptKeeper
 * $ adb shell am start \
 *     -e "com.android.settings.CryptKeeper.DEBUG_FORCE_VIEW" "progress" \
 *     -n com.android.settings/.CryptKeeper
 * </pre>
 */
public class CryptKeeper extends Activity implements TextView.OnEditorActionListener,
        OnKeyListener, OnTouchListener, TextWatcher {
    private static final String TAG = "CryptKeeper";

    private static final String DECRYPT_STATE = "trigger_restart_framework";

    /** Message sent to us to indicate encryption update progress. */
    private static final int MESSAGE_UPDATE_PROGRESS = 1;
    /** Message sent to us to indicate alerting the user that we are waiting for password entry */
    private static final int MESSAGE_NOTIFY = 2;

    // Constants used to control policy.
    private static final int MAX_FAILED_ATTEMPTS = 30;
    private static final int COOL_DOWN_ATTEMPTS = 10;

    // Intent action for launching the Emergency Dialer activity.
    static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL";

    // Debug Intent extras so that this Activity may be started via adb for debugging UI layouts
    private static final String EXTRA_FORCE_VIEW =
            "com.android.settings.CryptKeeper.DEBUG_FORCE_VIEW";
    private static final String FORCE_VIEW_PROGRESS = "progress";
    private static final String FORCE_VIEW_ERROR = "error";
    private static final String FORCE_VIEW_PASSWORD = "password";

    private static final String STATE_COOLDOWN = "cooldown";

    /** When encryption is detected, this flag indicates whether or not we've checked for errors. */
    private boolean mValidationComplete;
    private boolean mValidationRequested;
    /** A flag to indicate that the volume is in a bad state (e.g. partially encrypted). */
    private boolean mEncryptionGoneBad;
    /** If gone bad, should we show encryption failed (false) or corrupt (true)*/
    private boolean mCorrupt;
    /** A flag to indicate when the back event should be ignored */
    /** When set, blocks unlocking. Set every COOL_DOWN_ATTEMPTS attempts, only cleared
        by power cycling phone. */
    private boolean mCooldown = false;

    PowerManager.WakeLock mWakeLock;
    private ImeAwareEditText mPasswordEntry;
    private LockPatternView mLockPatternView;
    /** Number of calls to {@link #notifyUser()} to ignore before notifying. */
    private int mNotificationCountdown = 0;
    /** Number of calls to {@link #notifyUser()} before we release the wakelock */
    private int mReleaseWakeLockCountdown = 0;
    private int mStatusString = R.string.enter_password;

    // how long we wait to clear a wrong pattern
    private static final int WRONG_PATTERN_CLEAR_TIMEOUT_MS = 1500;

    // how long we wait to clear a right pattern
    private static final int RIGHT_PATTERN_CLEAR_TIMEOUT_MS = 500;

    // When the user enters a short pin/password, run this to show an error,
    // but don't count it against attempts.
    private final Runnable mFakeUnlockAttemptRunnable = new Runnable() {
        @Override
        public void run() {
            handleBadAttempt(1 /* failedAttempt */);
        }
    };

    // TODO: this should be tuned to match minimum decryption timeout
    private static final int FAKE_ATTEMPT_DELAY = 1000;

    private final Runnable mClearPatternRunnable = new Runnable() {
        @Override
        public void run() {
            mLockPatternView.clearPattern();
        }
    };

    /**
     * Used to propagate state through configuration changes (e.g. screen rotation)
     */
    private static class NonConfigurationInstanceState {
        final PowerManager.WakeLock wakelock;

        NonConfigurationInstanceState(PowerManager.WakeLock _wakelock) {
            wakelock = _wakelock;
        }
    }

    private class DecryptTask extends AsyncTask<String, Void, Integer> {
        private void hide(int id) {
            View view = findViewById(id);
            if (view != null) {
                view.setVisibility(View.GONE);
            }
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            beginAttempt();
        }

        @Override
        protected Integer doInBackground(String... params) {
            final IStorageManager service = getStorageManager();
            try {
                return service.decryptStorage(params[0]);
            } catch (Exception e) {
                Log.e(TAG, "Error while decrypting...", e);
                return -1;
            }
        }

        @Override
        protected void onPostExecute(Integer failedAttempts) {
            if (failedAttempts == 0) {
                // The password was entered successfully. Simply do nothing
                // and wait for the service restart to switch to surfacefligner
                if (mLockPatternView != null) {
                    mLockPatternView.removeCallbacks(mClearPatternRunnable);
                    mLockPatternView.postDelayed(mClearPatternRunnable, RIGHT_PATTERN_CLEAR_TIMEOUT_MS);
                }
                final TextView status = (TextView) findViewById(R.id.status);
                status.setText(R.string.starting_android);
                hide(R.id.passwordEntry);
                hide(R.id.switch_ime_button);
                hide(R.id.lockPattern);
                hide(R.id.owner_info);
                hide(R.id.emergencyCallButton);
            } else if (failedAttempts == MAX_FAILED_ATTEMPTS) {
                // Factory reset the device.
                Intent intent = new Intent(Intent.ACTION_FACTORY_RESET);
                intent.setPackage("android");
                intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
                intent.putExtra(Intent.EXTRA_REASON, "CryptKeeper.MAX_FAILED_ATTEMPTS");
                sendBroadcast(intent);
            } else if (failedAttempts == -1) {
                // Right password, but decryption failed. Tell user bad news ...
                setContentView(R.layout.crypt_keeper_progress);
                showFactoryReset(true);
                return;
            } else {
                handleBadAttempt(failedAttempts);
            }
        }
    }

    private void beginAttempt() {
        final TextView status = (TextView) findViewById(R.id.status);
        status.setText(R.string.checking_decryption);
    }

    private void handleBadAttempt(Integer failedAttempts) {
        // Wrong entry. Handle pattern case.
        if (mLockPatternView != null) {
            mLockPatternView.setDisplayMode(DisplayMode.Wrong);
            mLockPatternView.removeCallbacks(mClearPatternRunnable);
            mLockPatternView.postDelayed(mClearPatternRunnable, WRONG_PATTERN_CLEAR_TIMEOUT_MS);
        }
        if ((failedAttempts % COOL_DOWN_ATTEMPTS) == 0) {
            mCooldown = true;
            // No need to setBackFunctionality(false) - it's already done
            // at this point.
            cooldown();
        } else {
            final TextView status = (TextView) findViewById(R.id.status);

            int remainingAttempts = MAX_FAILED_ATTEMPTS - failedAttempts;
            if (remainingAttempts < COOL_DOWN_ATTEMPTS) {
                CharSequence warningTemplate = getText(R.string.crypt_keeper_warn_wipe);
                CharSequence warning = TextUtils.expandTemplate(warningTemplate,
                        Integer.toString(remainingAttempts));
                status.setText(warning);
            } else {
                int passwordType = StorageManager.CRYPT_TYPE_PASSWORD;
                try {
                    final IStorageManager service = getStorageManager();
                    passwordType = service.getPasswordType();
                } catch (Exception e) {
                    Log.e(TAG, "Error calling mount service " + e);
                }

                if (passwordType == StorageManager.CRYPT_TYPE_PIN) {
                    status.setText(R.string.cryptkeeper_wrong_pin);
                } else if (passwordType == StorageManager.CRYPT_TYPE_PATTERN) {
                    status.setText(R.string.cryptkeeper_wrong_pattern);
                } else {
                    status.setText(R.string.cryptkeeper_wrong_password);
                }
            }

            if (mLockPatternView != null) {
                mLockPatternView.setDisplayMode(DisplayMode.Wrong);
                mLockPatternView.setEnabled(true);
            }

            // Reenable the password entry
            if (mPasswordEntry != null) {
                mPasswordEntry.setEnabled(true);
                mPasswordEntry.scheduleShowSoftInput();
                setBackFunctionality(true);
            }
        }
    }

    private class ValidationTask extends AsyncTask<Void, Void, Boolean> {
        int state;

        @Override
        protected Boolean doInBackground(Void... params) {
            final IStorageManager service = getStorageManager();
            try {
                Log.d(TAG, "Validating encryption state.");
                state = service.getEncryptionState();
                if (state == StorageManager.ENCRYPTION_STATE_NONE) {
                    Log.w(TAG, "Unexpectedly in CryptKeeper even though there is no encryption.");
                    return true; // Unexpected, but fine, I guess...
                }
                return state == StorageManager.ENCRYPTION_STATE_OK;
            } catch (RemoteException e) {
                Log.w(TAG, "Unable to get encryption state properly");
                return true;
            }
        }

        @Override
        protected void onPostExecute(Boolean result) {
            mValidationComplete = true;
            if (Boolean.FALSE.equals(result)) {
                Log.w(TAG, "Incomplete, or corrupted encryption detected. Prompting user to wipe.");
                mEncryptionGoneBad = true;
                mCorrupt = state == StorageManager.ENCRYPTION_STATE_ERROR_CORRUPT;
            } else {
                Log.d(TAG, "Encryption state validated. Proceeding to configure UI");
            }
            setupUi();
        }
    }

    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MESSAGE_UPDATE_PROGRESS:
                updateProgress();
                break;

            case MESSAGE_NOTIFY:
                notifyUser();
                break;
            }
        }
    };

    private AudioManager mAudioManager;
    /** The status bar where back/home/recent buttons are shown. */
    private StatusBarManager mStatusBar;

    /** All the widgets to disable in the status bar */
    final private static int sWidgetsToDisable = StatusBarManager.DISABLE_EXPAND
            | StatusBarManager.DISABLE_NOTIFICATION_ICONS
            | StatusBarManager.DISABLE_NOTIFICATION_ALERTS
            | StatusBarManager.DISABLE_HOME
            | StatusBarManager.DISABLE_SEARCH
            | StatusBarManager.DISABLE_RECENT;

    protected static final int MIN_LENGTH_BEFORE_REPORT = LockPatternUtils.MIN_LOCK_PATTERN_SIZE;

    /** @return whether or not this Activity was started for debugging the UI only. */
    private boolean isDebugView() {
        return getIntent().hasExtra(EXTRA_FORCE_VIEW);
    }

    /** @return whether or not this Activity was started for debugging the specific UI view only. */
    private boolean isDebugView(String viewType /* non-nullable */) {
        return viewType.equals(getIntent().getStringExtra(EXTRA_FORCE_VIEW));
    }

    /**
     * Notify the user that we are awaiting input. Currently this sends an audio alert.
     */
    private void notifyUser() {
        if (mNotificationCountdown > 0) {
            --mNotificationCountdown;
        } else if (mAudioManager != null) {
            try {
                // Play the standard keypress sound at full volume. This should be available on
                // every device. We cannot play a ringtone here because media services aren't
                // available yet. A DTMF-style tone is too soft to be noticed, and might not exist
                // on tablet devices. The idea is to alert the user that something is needed: this
                // does not have to be pleasing.
                mAudioManager.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD, 100);
            } catch (Exception e) {
                Log.w(TAG, "notifyUser: Exception while playing sound: " + e);
            }
        }
        // Notify the user again in 5 seconds.
        mHandler.removeMessages(MESSAGE_NOTIFY);
        mHandler.sendEmptyMessageDelayed(MESSAGE_NOTIFY, 5 * 1000);

        if (mWakeLock.isHeld()) {
            if (mReleaseWakeLockCountdown > 0) {
                --mReleaseWakeLockCountdown;
            } else {
                mWakeLock.release();
            }
        }
    }

    /**
     * Ignore back events from this activity always - there's nowhere to go back
     * to
     */
    @Override
    public void onBackPressed() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // If we are not encrypted or encrypting, get out quickly.
        final String state = VoldProperties.decrypt().orElse("");
        if (!isDebugView() && ("".equals(state) || DECRYPT_STATE.equals(state))) {
            disableCryptKeeperComponent(this);
            // Typically CryptKeeper is launched as the home app.  We didn't
            // want to be running, so need to finish this activity.  We can count
            // on the activity manager re-launching the new home app upon finishing
            // this one, since this will leave the activity stack empty.
            // NOTE: This is really grungy.  I think it would be better for the
            // activity manager to explicitly launch the crypt keeper instead of
            // home in the situation where we need to decrypt the device
            finish();
            return;
        }

        try {
            if (getResources().getBoolean(R.bool.crypt_keeper_allow_rotation)) {
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
            }
        } catch (NotFoundException e) {
        }

        // Disable the status bar, but do NOT disable back because the user needs a way to go
        // from keyboard settings and back to the password screen.
        mStatusBar = (StatusBarManager) getSystemService(Context.STATUS_BAR_SERVICE);
        mStatusBar.disable(sWidgetsToDisable);

        if (savedInstanceState != null) {
            mCooldown = savedInstanceState.getBoolean(STATE_COOLDOWN);
        }

        setAirplaneModeIfNecessary();
        mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        // Check for (and recover) retained instance data
        final Object lastInstance = getLastNonConfigurationInstance();
        if (lastInstance instanceof NonConfigurationInstanceState) {
            NonConfigurationInstanceState retained = (NonConfigurationInstanceState) lastInstance;
            mWakeLock = retained.wakelock;
            Log.d(TAG, "Restoring wakelock from NonConfigurationInstanceState");
        }
    }

    @Override
    public void  onSaveInstanceState(Bundle savedInstanceState) {
        savedInstanceState.putBoolean(STATE_COOLDOWN, mCooldown);
    }

    /**
     * Note, we defer the state check and screen setup to onStart() because this will be
     * re-run if the user clicks the power button (sleeping/waking the screen), and this is
     * especially important if we were to lose the wakelock for any reason.
     */
    @Override
    public void onStart() {
        super.onStart();
        setupUi();
    }

    /**
     * Initializes the UI based on the current state of encryption.
     * This is idempotent - calling repeatedly will simply re-initialize the UI.
     */
    private void setupUi() {
        if (mEncryptionGoneBad || isDebugView(FORCE_VIEW_ERROR)) {
            setContentView(R.layout.crypt_keeper_progress);
            showFactoryReset(mCorrupt);
            return;
        }

        final String progress = VoldProperties.encrypt_progress().orElse("");
        if (!"".equals(progress) || isDebugView(FORCE_VIEW_PROGRESS)) {
            setContentView(R.layout.crypt_keeper_progress);
            encryptionProgressInit();
        } else if (mValidationComplete || isDebugView(FORCE_VIEW_PASSWORD)) {
            new AsyncTask<Void, Void, Void>() {
                int passwordType = StorageManager.CRYPT_TYPE_PASSWORD;
                String owner_info;
                boolean pattern_visible;
                boolean password_visible;

                @Override
                public Void doInBackground(Void... v) {
                    try {
                        final IStorageManager service = getStorageManager();
                        passwordType = service.getPasswordType();
                        owner_info = service.getField(StorageManager.OWNER_INFO_KEY);
                        pattern_visible = !("0".equals(service.getField(StorageManager.PATTERN_VISIBLE_KEY)));
                        password_visible = !("0".equals(service.getField(StorageManager.PASSWORD_VISIBLE_KEY)));
                    } catch (Exception e) {
                        Log.e(TAG, "Error calling mount service " + e);
                    }

                    return null;
                }

                @Override
                public void onPostExecute(java.lang.Void v) {
                    Settings.System.putInt(getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD,
                                  password_visible ? 1 : 0);

                    if (passwordType == StorageManager.CRYPT_TYPE_PIN) {
                        setContentView(R.layout.crypt_keeper_pin_entry);
                        mStatusString = R.string.enter_pin;
                    } else if (passwordType == StorageManager.CRYPT_TYPE_PATTERN) {
                        setContentView(R.layout.crypt_keeper_pattern_entry);
                        setBackFunctionality(false);
                        mStatusString = R.string.enter_pattern;
                    } else {
                        setContentView(R.layout.crypt_keeper_password_entry);
                        mStatusString = R.string.enter_password;
                    }
                    final TextView status = (TextView) findViewById(R.id.status);
                    status.setText(mStatusString);

                    final TextView ownerInfo = (TextView) findViewById(R.id.owner_info);
                    ownerInfo.setText(owner_info);
                    ownerInfo.setSelected(true); // Required for marquee'ing to work

                    passwordEntryInit();

                    findViewById(android.R.id.content).setSystemUiVisibility(View.STATUS_BAR_DISABLE_BACK);

                    if (mLockPatternView != null) {
                        mLockPatternView.setInStealthMode(!pattern_visible);
                    }
                    if (mCooldown) {
                        // in case we are cooling down and coming back from emergency dialler
                        setBackFunctionality(false);
                        cooldown();
                    }

                }
            }.execute();
        } else if (!mValidationRequested) {
            // We're supposed to be encrypted, but no validation has been done.
            new ValidationTask().execute((Void[]) null);
            mValidationRequested = true;
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        mHandler.removeMessages(MESSAGE_UPDATE_PROGRESS);
        mHandler.removeMessages(MESSAGE_NOTIFY);
    }

    /**
     * Reconfiguring, so propagate the wakelock to the next instance.  This runs between onStop()
     * and onDestroy() and only if we are changing configuration (e.g. rotation).  Also clears
     * mWakeLock so the subsequent call to onDestroy does not release it.
     */
    @Override
    public Object onRetainNonConfigurationInstance() {
        NonConfigurationInstanceState state = new NonConfigurationInstanceState(mWakeLock);
        Log.d(TAG, "Handing wakelock off to NonConfigurationInstanceState");
        mWakeLock = null;
        return state;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        if (mWakeLock != null) {
            Log.d(TAG, "Releasing and destroying wakelock");
            mWakeLock.release();
            mWakeLock = null;
        }
    }

    /**
     * Start encrypting the device.
     */
    private void encryptionProgressInit() {
        // Accquire a partial wakelock to prevent the device from sleeping. Note
        // we never release this wakelock as we will be restarted after the device
        // is encrypted.
        Log.d(TAG, "Encryption progress screen initializing.");
        if (mWakeLock == null) {
            Log.d(TAG, "Acquiring wakelock.");
            PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
            mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
            mWakeLock.acquire();
        }

        ((ProgressBar) findViewById(R.id.progress_bar)).setIndeterminate(true);
        // Ignore all back presses from now, both hard and soft keys.
        setBackFunctionality(false);
        // Start the first run of progress manually. This method sets up messages to occur at
        // repeated intervals.
        updateProgress();
    }

    /**
     * Show factory reset screen allowing the user to reset their phone when
     * there is nothing else we can do
     * @param corrupt true if userdata is corrupt, false if encryption failed
     *        partway through
     */
    private void showFactoryReset(final boolean corrupt) {
        // Hide the encryption-bot to make room for the "factory reset" button
        findViewById(R.id.encroid).setVisibility(View.GONE);

        // Show the reset button, failure text, and a divider
        final Button button = (Button) findViewById(R.id.factory_reset);
        button.setVisibility(View.VISIBLE);
        button.setOnClickListener(new OnClickListener() {
                @Override
            public void onClick(View v) {
                // Factory reset the device.
                Intent intent = new Intent(Intent.ACTION_FACTORY_RESET);
                intent.setPackage("android");
                intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
                intent.putExtra(Intent.EXTRA_REASON,
                        "CryptKeeper.showFactoryReset() corrupt=" + corrupt);
                sendBroadcast(intent);
            }
        });

        // Alert the user of the failure.
        if (corrupt) {
            ((TextView) findViewById(R.id.title)).setText(R.string.crypt_keeper_data_corrupt_title);
            ((TextView) findViewById(R.id.status)).setText(R.string.crypt_keeper_data_corrupt_summary);
        } else {
            ((TextView) findViewById(R.id.title)).setText(R.string.crypt_keeper_failed_title);
            ((TextView) findViewById(R.id.status)).setText(R.string.crypt_keeper_failed_summary);
        }

        final View view = findViewById(R.id.bottom_divider);
        // TODO(viki): Why would the bottom divider be missing in certain layouts? Investigate.
        if (view != null) {
            view.setVisibility(View.VISIBLE);
        }
    }

    private void updateProgress() {
        final String state = VoldProperties.encrypt_progress().orElse("");

        if ("error_partially_encrypted".equals(state)) {
            showFactoryReset(false);
            return;
        }

        // Get status as percentage first
        CharSequence status = getText(R.string.crypt_keeper_setup_description);
        int percent = 0;
        try {
            // Force a 50% progress state when debugging the view.
            percent = isDebugView() ? 50 : Integer.parseInt(state);
        } catch (Exception e) {
            Log.w(TAG, "Error parsing progress: " + e.toString());
        }
        String progress = Integer.toString(percent);

        // Now try to get status as time remaining and replace as appropriate
        Log.v(TAG, "Encryption progress: " + progress);
        try {
            int time = VoldProperties.encrypt_time_remaining().get();
            if (time >= 0) {
                // Round up to multiple of 10 - this way display is less jerky
                time = (time + 9) / 10 * 10;
                progress = DateUtils.formatElapsedTime(time);
                status = getText(R.string.crypt_keeper_setup_time_remaining);
            }
        } catch (Exception e) {
            // Will happen if no time etc - show percentage
        }

        final TextView tv = (TextView) findViewById(R.id.status);
        if (tv != null) {
            tv.setText(TextUtils.expandTemplate(status, progress));
        }

        // Check the progress every 1 seconds
        mHandler.removeMessages(MESSAGE_UPDATE_PROGRESS);
        mHandler.sendEmptyMessageDelayed(MESSAGE_UPDATE_PROGRESS, 1000);
    }

    /** Insist on a power cycle to force the user to waste time between retries.
     *
     * Call setBackFunctionality(false) before calling this. */
    private void cooldown() {
        // Disable the password entry.
        if (mPasswordEntry != null) {
            mPasswordEntry.setEnabled(false);
        }
        if (mLockPatternView != null) {
            mLockPatternView.setEnabled(false);
        }

        final TextView status = (TextView) findViewById(R.id.status);
        status.setText(R.string.crypt_keeper_force_power_cycle);
    }

    /**
     * Sets the back status: enabled or disabled according to the parameter.
     * @param isEnabled true if back is enabled, false otherwise.
     */
    private final void setBackFunctionality(boolean isEnabled) {
        if (isEnabled) {
            mStatusBar.disable(sWidgetsToDisable);
        } else {
            mStatusBar.disable(sWidgetsToDisable | StatusBarManager.DISABLE_BACK);
        }
    }

    private void fakeUnlockAttempt(View postingView) {
        beginAttempt();
        postingView.postDelayed(mFakeUnlockAttemptRunnable, FAKE_ATTEMPT_DELAY);
    }

    protected LockPatternView.OnPatternListener mChooseNewLockPatternListener =
        new LockPatternView.OnPatternListener() {

        @Override
        public void onPatternStart() {
            mLockPatternView.removeCallbacks(mClearPatternRunnable);
        }

        @Override
        public void onPatternCleared() {
        }

        @Override
        public void onPatternDetected(List<LockPatternView.Cell> pattern) {
            mLockPatternView.setEnabled(false);
            if (pattern.size() >= MIN_LENGTH_BEFORE_REPORT) {
                new DecryptTask().execute(LockPatternUtils.patternToString(pattern));
            } else {
                // Allow user to make as many of these as they want.
                fakeUnlockAttempt(mLockPatternView);
            }
        }

        @Override
        public void onPatternCellAdded(List<Cell> pattern) {
        }
     };

     private void passwordEntryInit() {
        // Password/pin case
        mPasswordEntry = (ImeAwareEditText) findViewById(R.id.passwordEntry);
        if (mPasswordEntry != null){
            mPasswordEntry.setOnEditorActionListener(this);
            mPasswordEntry.requestFocus();
            // Become quiet when the user interacts with the Edit text screen.
            mPasswordEntry.setOnKeyListener(this);
            mPasswordEntry.setOnTouchListener(this);
            mPasswordEntry.addTextChangedListener(this);
        }

        // Pattern case
        mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern);
        if (mLockPatternView != null) {
            mLockPatternView.setOnPatternListener(mChooseNewLockPatternListener);
        }

        // Disable the Emergency call button if the device has no voice telephone capability
        if (!getTelephonyManager().isVoiceCapable()) {
            final View emergencyCall = findViewById(R.id.emergencyCallButton);
            if (emergencyCall != null) {
                Log.d(TAG, "Removing the emergency Call button");
                emergencyCall.setVisibility(View.GONE);
            }
        }

        final View imeSwitcher = findViewById(R.id.switch_ime_button);
        final InputMethodManager imm = (InputMethodManager) getSystemService(
                Context.INPUT_METHOD_SERVICE);
        if (imeSwitcher != null && hasMultipleEnabledIMEsOrSubtypes(imm, false)) {
            imeSwitcher.setVisibility(View.VISIBLE);
            imeSwitcher.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    imm.showInputMethodPickerFromSystem(false /* showAuxiliarySubtypes */,
                            v.getDisplay().getDisplayId());
                }
            });
        }

        // We want to keep the screen on while waiting for input. In minimal boot mode, the device
        // is completely non-functional, and we want the user to notice the device and enter a
        // password.
        if (mWakeLock == null) {
            Log.d(TAG, "Acquiring wakelock.");
            final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
            if (pm != null) {
                mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, TAG);
                mWakeLock.acquire();
                // Keep awake for 10 minutes - if the user hasn't been alerted by then
                // best not to just drain their battery
                mReleaseWakeLockCountdown = 96; // 96 * 5 secs per click + 120 secs before we show this = 600
            }
        }

        // Make sure that the IME is shown when everything becomes ready.
        if (mLockPatternView == null && !mCooldown) {
            getWindow().setSoftInputMode(
                                WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
            if (mPasswordEntry != null) {
                mPasswordEntry.scheduleShowSoftInput();
            }
        }

        updateEmergencyCallButtonState();
        // Notify the user in 120 seconds that we are waiting for him to enter the password.
        mHandler.removeMessages(MESSAGE_NOTIFY);
        mHandler.sendEmptyMessageDelayed(MESSAGE_NOTIFY, 120 * 1000);

        // Dismiss secure & non-secure keyguards while this screen is showing.
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
                | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
    }

    /**
     * Method adapted from com.android.inputmethod.latin.Utils
     *
     * @param imm The input method manager
     * @param shouldIncludeAuxiliarySubtypes
     * @return true if we have multiple IMEs to choose from
     */
    private boolean hasMultipleEnabledIMEsOrSubtypes(InputMethodManager imm,
            final boolean shouldIncludeAuxiliarySubtypes) {
        final List<InputMethodInfo> enabledImis = imm.getEnabledInputMethodList();

        // Number of the filtered IMEs
        int filteredImisCount = 0;

        for (InputMethodInfo imi : enabledImis) {
            // We can return true immediately after we find two or more filtered IMEs.
            if (filteredImisCount > 1) return true;
            final List<InputMethodSubtype> subtypes =
                    imm.getEnabledInputMethodSubtypeList(imi, true);
            // IMEs that have no subtypes should be counted.
            if (subtypes.isEmpty()) {
                ++filteredImisCount;
                continue;
            }

            int auxCount = 0;
            for (InputMethodSubtype subtype : subtypes) {
                if (subtype.isAuxiliary()) {
                    ++auxCount;
                }
            }
            final int nonAuxCount = subtypes.size() - auxCount;

            // IMEs that have one or more non-auxiliary subtypes should be counted.
            // If shouldIncludeAuxiliarySubtypes is true, IMEs that have two or more auxiliary
            // subtypes should be counted as well.
            if (nonAuxCount > 0 || (shouldIncludeAuxiliarySubtypes && auxCount > 1)) {
                ++filteredImisCount;
                continue;
            }
        }

        return filteredImisCount > 1
        // imm.getEnabledInputMethodSubtypeList(null, false) will return the current IME's enabled
        // input method subtype (The current IME should be LatinIME.)
                || imm.getEnabledInputMethodSubtypeList(null, false).size() > 1;
    }

    private IStorageManager getStorageManager() {
        final IBinder service = ServiceManager.getService("mount");
        if (service != null) {
            return IStorageManager.Stub.asInterface(service);
        }
        return null;
    }

    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        if (actionId == EditorInfo.IME_NULL || actionId == EditorInfo.IME_ACTION_DONE) {
            // Get the password
            final String password = v.getText().toString();

            if (TextUtils.isEmpty(password)) {
                return true;
            }

            // Now that we have the password clear the password field.
            v.setText(null);

            // Disable the password entry and back keypress while checking the password. These
            // we either be re-enabled if the password was wrong or after the cooldown period.
            mPasswordEntry.setEnabled(false);
            setBackFunctionality(false);

            if (password.length() >= LockPatternUtils.MIN_LOCK_PASSWORD_SIZE) {
                new DecryptTask().execute(password);
            } else {
                // Allow user to make as many of these as they want.
                fakeUnlockAttempt(mPasswordEntry);
            }

            return true;
        }
        return false;
    }

    /**
     * Set airplane mode on the device if it isn't an LTE device.
     * Full story: In minimal boot mode, we cannot save any state. In particular, we cannot save
     * any incoming SMS's. So SMSs that are received here will be silently dropped to the floor.
     * That is bad. Also, we cannot receive any telephone calls in this state. So to avoid
     * both these problems, we turn the radio off. However, on certain networks turning on and
     * off the radio takes a long time. In such cases, we are better off leaving the radio
     * running so the latency of an E911 call is short.
     * The behavior after this is:
     * 1. Emergency dialing: the emergency dialer has logic to force the device out of
     *    airplane mode and restart the radio.
     * 2. Full boot: we read the persistent settings from the previous boot and restore the
     *    radio to whatever it was before it restarted. This also happens when rebooting a
     *    phone that has no encryption.
     */
    private final void setAirplaneModeIfNecessary() {
        final boolean isLteDevice =
                getTelephonyManager().getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE;
        if (!isLteDevice) {
            Log.d(TAG, "Going into airplane mode.");
            Settings.Global.putInt(getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
            final Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
            intent.putExtra("state", true);
            sendBroadcastAsUser(intent, UserHandle.ALL);
        }
    }

    /**
     * Code to update the state of, and handle clicks from, the "Emergency call" button.
     *
     * This code is mostly duplicated from the corresponding code in
     * LockPatternUtils and LockPatternKeyguardView under frameworks/base.
     */
    private void updateEmergencyCallButtonState() {
        final Button emergencyCall = (Button) findViewById(R.id.emergencyCallButton);
        // The button isn't present at all in some configurations.
        if (emergencyCall == null)
            return;

        if (isEmergencyCallCapable()) {
            emergencyCall.setVisibility(View.VISIBLE);
            emergencyCall.setOnClickListener(new View.OnClickListener() {
                    @Override

                    public void onClick(View v) {
                        takeEmergencyCallAction();
                    }
                });
        } else {
            emergencyCall.setVisibility(View.GONE);
            return;
        }

        int textId;
        if (getTelecomManager().isInCall()) {
            // Show "return to call"
            textId = R.string.cryptkeeper_return_to_call;
        } else {
            textId = R.string.cryptkeeper_emergency_call;
        }
        emergencyCall.setText(textId);
    }

    private boolean isEmergencyCallCapable() {
        return getResources().getBoolean(com.android.internal.R.bool.config_voice_capable);
    }

    private void takeEmergencyCallAction() {
        TelecomManager telecomManager = getTelecomManager();
        if (telecomManager.isInCall()) {
            telecomManager.showInCallScreen(false /* showDialpad */);
        } else {
            launchEmergencyDialer();
        }
    }


    private void launchEmergencyDialer() {
        final Intent intent = new Intent(ACTION_EMERGENCY_DIAL);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
        setBackFunctionality(true);
        startActivity(intent);
    }

    private TelephonyManager getTelephonyManager() {
        return (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
    }

    private TelecomManager getTelecomManager() {
        return (TelecomManager) getSystemService(Context.TELECOM_SERVICE);
    }

    /**
     * Listen to key events so we can disable sounds when we get a keyinput in EditText.
     */
    private void delayAudioNotification() {
        mNotificationCountdown = 20;
    }

    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        delayAudioNotification();
        return false;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        delayAudioNotification();
        return false;
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        return;
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        delayAudioNotification();
    }

    @Override
    public void afterTextChanged(Editable s) {
        return;
    }

    private static void disableCryptKeeperComponent(Context context) {
        PackageManager pm = context.getPackageManager();
        ComponentName name = new ComponentName(context, CryptKeeper.class);
        Log.d(TAG, "Disabling component " + name);
        pm.setComponentEnabledSetting(name, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                PackageManager.DONT_KILL_APP);
    }
}
