629 lines
26 KiB
Java
629 lines
26 KiB
Java
/*
|
|
* 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.activity.setup;
|
|
|
|
import android.app.Activity;
|
|
import android.app.AlertDialog;
|
|
import android.app.Dialog;
|
|
import android.app.DialogFragment;
|
|
import android.app.FragmentManager;
|
|
import android.app.LoaderManager;
|
|
import android.app.admin.DevicePolicyManager;
|
|
import android.content.Context;
|
|
import android.content.DialogInterface;
|
|
import android.content.Intent;
|
|
import android.content.Loader;
|
|
import android.content.res.Resources;
|
|
import android.net.Uri;
|
|
import android.os.AsyncTask;
|
|
import android.os.Bundle;
|
|
import android.os.Handler;
|
|
import android.text.TextUtils;
|
|
|
|
import com.android.email.DebugUtils;
|
|
import com.android.email.R;
|
|
import com.android.email.SecurityPolicy;
|
|
import com.android.emailcommon.provider.Account;
|
|
import com.android.emailcommon.provider.EmailContent;
|
|
import com.android.emailcommon.provider.HostAuth;
|
|
import com.android.emailcommon.provider.Policy;
|
|
import com.android.emailcommon.utility.IntentUtilities;
|
|
import com.android.mail.ui.MailAsyncTaskLoader;
|
|
import com.android.mail.utils.LogUtils;
|
|
|
|
/**
|
|
* Psuedo-activity (no UI) to bootstrap the user up to a higher desired security level. This
|
|
* bootstrap requires the following steps.
|
|
*
|
|
* 1. Confirm the account of interest has any security policies defined - exit early if not
|
|
* 2. If not actively administrating the device, ask Device Policy Manager to start that
|
|
* 3. When we are actively administrating, check current policies and see if they're sufficient
|
|
* 4. If not, set policies
|
|
* 5. If necessary, request for user to update device password
|
|
* 6. If necessary, request for user to activate device encryption
|
|
*/
|
|
public class AccountSecurity extends Activity {
|
|
private static final String TAG = "Email/AccountSecurity";
|
|
|
|
private static final boolean DEBUG = false; // Don't ship with this set to true
|
|
|
|
private static final String EXTRA_ACCOUNT_ID = "ACCOUNT_ID";
|
|
private static final String EXTRA_SHOW_DIALOG = "SHOW_DIALOG";
|
|
private static final String EXTRA_PASSWORD_EXPIRING = "EXPIRING";
|
|
private static final String EXTRA_PASSWORD_EXPIRED = "EXPIRED";
|
|
|
|
private static final String SAVESTATE_INITIALIZED_TAG = "initialized";
|
|
private static final String SAVESTATE_TRIED_ADD_ADMINISTRATOR_TAG = "triedAddAdministrator";
|
|
private static final String SAVESTATE_TRIED_SET_PASSWORD_TAG = "triedSetpassword";
|
|
private static final String SAVESTATE_TRIED_SET_ENCRYPTION_TAG = "triedSetEncryption";
|
|
private static final String SAVESTATE_ACCOUNT_TAG = "account";
|
|
|
|
private static final int REQUEST_ENABLE = 1;
|
|
private static final int REQUEST_PASSWORD = 2;
|
|
private static final int REQUEST_ENCRYPTION = 3;
|
|
|
|
private boolean mTriedAddAdministrator;
|
|
private boolean mTriedSetPassword;
|
|
private boolean mTriedSetEncryption;
|
|
|
|
private Account mAccount;
|
|
|
|
protected boolean mInitialized;
|
|
|
|
private Handler mHandler;
|
|
private boolean mActivityResumed;
|
|
|
|
private static final int ACCOUNT_POLICY_LOADER_ID = 0;
|
|
private AccountAndPolicyLoaderCallbacks mAPLoaderCallbacks;
|
|
private Bundle mAPLoaderArgs;
|
|
|
|
public static Uri getUpdateSecurityUri(final long accountId, final boolean showDialog) {
|
|
final Uri.Builder baseUri = Uri.parse("auth://" + EmailContent.EMAIL_PACKAGE_NAME +
|
|
".ACCOUNT_SECURITY/").buildUpon();
|
|
IntentUtilities.setAccountId(baseUri, accountId);
|
|
baseUri.appendQueryParameter(EXTRA_SHOW_DIALOG, Boolean.toString(showDialog));
|
|
return baseUri.build();
|
|
}
|
|
|
|
/**
|
|
* Used for generating intent for this activity (which is intended to be launched
|
|
* from a notification.)
|
|
*
|
|
* @param context Calling context for building the intent
|
|
* @param accountId The account of interest
|
|
* @param showDialog If true, a simple warning dialog will be shown before kicking off
|
|
* the necessary system settings. Should be true anywhere the context of the security settings
|
|
* is not clear (e.g. any time after the account has been set up).
|
|
* @return an Intent which can be used to view that account
|
|
*/
|
|
public static Intent actionUpdateSecurityIntent(Context context, long accountId,
|
|
boolean showDialog) {
|
|
Intent intent = new Intent(context, AccountSecurity.class);
|
|
intent.putExtra(EXTRA_ACCOUNT_ID, accountId);
|
|
intent.putExtra(EXTRA_SHOW_DIALOG, showDialog);
|
|
return intent;
|
|
}
|
|
|
|
/**
|
|
* Used for generating intent for this activity (which is intended to be launched
|
|
* from a notification.) This is a special mode of this activity which exists only
|
|
* to give the user a dialog (for context) about a device pin/password expiration event.
|
|
*/
|
|
public static Intent actionDevicePasswordExpirationIntent(Context context, long accountId,
|
|
boolean expired) {
|
|
Intent intent = new ForwardingIntent(context, AccountSecurity.class);
|
|
intent.putExtra(EXTRA_ACCOUNT_ID, accountId);
|
|
intent.putExtra(expired ? EXTRA_PASSWORD_EXPIRED : EXTRA_PASSWORD_EXPIRING, true);
|
|
return intent;
|
|
}
|
|
|
|
@Override
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
|
|
mHandler = new Handler();
|
|
|
|
final Intent i = getIntent();
|
|
final long accountId;
|
|
Bundle extras = i.getExtras();
|
|
if (extras == null) {
|
|
// We have been invoked via a uri. We need to get our parameters from the URI instead
|
|
// of looking in the intent extras.
|
|
extras = new Bundle();
|
|
accountId = IntentUtilities.getAccountIdFromIntent(i);
|
|
extras.putLong(EXTRA_ACCOUNT_ID, accountId);
|
|
boolean showDialog = false;
|
|
final String value = i.getData().getQueryParameter(EXTRA_SHOW_DIALOG);
|
|
if (!TextUtils.isEmpty(value)) {
|
|
showDialog = Boolean.getBoolean(value);
|
|
}
|
|
extras.putBoolean(EXTRA_SHOW_DIALOG, showDialog);
|
|
} else {
|
|
accountId = i.getLongExtra(EXTRA_ACCOUNT_ID, -1);
|
|
extras = i.getExtras();
|
|
}
|
|
|
|
final SecurityPolicy security = SecurityPolicy.getInstance(this);
|
|
security.clearNotification();
|
|
if (accountId == -1) {
|
|
finish();
|
|
return;
|
|
}
|
|
|
|
if (savedInstanceState != null) {
|
|
mInitialized = savedInstanceState.getBoolean(SAVESTATE_INITIALIZED_TAG, false);
|
|
|
|
mTriedAddAdministrator =
|
|
savedInstanceState.getBoolean(SAVESTATE_TRIED_ADD_ADMINISTRATOR_TAG, false);
|
|
mTriedSetPassword =
|
|
savedInstanceState.getBoolean(SAVESTATE_TRIED_SET_PASSWORD_TAG, false);
|
|
mTriedSetEncryption =
|
|
savedInstanceState.getBoolean(SAVESTATE_TRIED_SET_ENCRYPTION_TAG, false);
|
|
|
|
mAccount = savedInstanceState.getParcelable(SAVESTATE_ACCOUNT_TAG);
|
|
}
|
|
|
|
if (!mInitialized) {
|
|
startAccountAndPolicyLoader(extras);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void onSaveInstanceState(final Bundle outState) {
|
|
super.onSaveInstanceState(outState);
|
|
outState.putBoolean(SAVESTATE_INITIALIZED_TAG, mInitialized);
|
|
|
|
outState.putBoolean(SAVESTATE_TRIED_ADD_ADMINISTRATOR_TAG, mTriedAddAdministrator);
|
|
outState.putBoolean(SAVESTATE_TRIED_SET_PASSWORD_TAG, mTriedSetPassword);
|
|
outState.putBoolean(SAVESTATE_TRIED_SET_ENCRYPTION_TAG, mTriedSetEncryption);
|
|
|
|
outState.putParcelable(SAVESTATE_ACCOUNT_TAG, mAccount);
|
|
}
|
|
|
|
@Override
|
|
protected void onPause() {
|
|
super.onPause();
|
|
mActivityResumed = false;
|
|
}
|
|
|
|
@Override
|
|
protected void onResume() {
|
|
super.onResume();
|
|
mActivityResumed = true;
|
|
tickleAccountAndPolicyLoader();
|
|
}
|
|
|
|
protected boolean isActivityResumed() {
|
|
return mActivityResumed;
|
|
}
|
|
|
|
private void tickleAccountAndPolicyLoader() {
|
|
// If we're already initialized we don't need to tickle.
|
|
if (!mInitialized) {
|
|
getLoaderManager().initLoader(ACCOUNT_POLICY_LOADER_ID, mAPLoaderArgs,
|
|
mAPLoaderCallbacks);
|
|
}
|
|
}
|
|
|
|
private void startAccountAndPolicyLoader(final Bundle args) {
|
|
mAPLoaderArgs = args;
|
|
mAPLoaderCallbacks = new AccountAndPolicyLoaderCallbacks();
|
|
tickleAccountAndPolicyLoader();
|
|
}
|
|
|
|
private class AccountAndPolicyLoaderCallbacks
|
|
implements LoaderManager.LoaderCallbacks<Account> {
|
|
@Override
|
|
public Loader<Account> onCreateLoader(final int id, final Bundle args) {
|
|
final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);
|
|
final boolean showDialog = args.getBoolean(EXTRA_SHOW_DIALOG, false);
|
|
final boolean passwordExpiring =
|
|
args.getBoolean(EXTRA_PASSWORD_EXPIRING, false);
|
|
final boolean passwordExpired =
|
|
args.getBoolean(EXTRA_PASSWORD_EXPIRED, false);
|
|
|
|
return new AccountAndPolicyLoader(getApplicationContext(), accountId,
|
|
showDialog, passwordExpiring, passwordExpired);
|
|
}
|
|
|
|
@Override
|
|
public void onLoadFinished(final Loader<Account> loader, final Account account) {
|
|
mHandler.post(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
final AccountSecurity activity = AccountSecurity.this;
|
|
if (!activity.isActivityResumed()) {
|
|
return;
|
|
}
|
|
|
|
if (account == null || (account.mPolicyKey != 0 && account.mPolicy == null)) {
|
|
activity.finish();
|
|
LogUtils.d(TAG, "could not load account or policy in AccountSecurity");
|
|
return;
|
|
}
|
|
|
|
if (!activity.mInitialized) {
|
|
activity.mInitialized = true;
|
|
|
|
final AccountAndPolicyLoader apLoader = (AccountAndPolicyLoader) loader;
|
|
activity.completeCreate(account, apLoader.mShowDialog,
|
|
apLoader.mPasswordExpiring, apLoader.mPasswordExpired);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void onLoaderReset(Loader<Account> loader) {}
|
|
}
|
|
|
|
private static class AccountAndPolicyLoader extends MailAsyncTaskLoader<Account> {
|
|
private final long mAccountId;
|
|
public final boolean mShowDialog;
|
|
public final boolean mPasswordExpiring;
|
|
public final boolean mPasswordExpired;
|
|
|
|
private final Context mContext;
|
|
|
|
AccountAndPolicyLoader(final Context context, final long accountId,
|
|
final boolean showDialog, final boolean passwordExpiring,
|
|
final boolean passwordExpired) {
|
|
super(context);
|
|
mContext = context;
|
|
mAccountId = accountId;
|
|
mShowDialog = showDialog;
|
|
mPasswordExpiring = passwordExpiring;
|
|
mPasswordExpired = passwordExpired;
|
|
}
|
|
|
|
@Override
|
|
public Account loadInBackground() {
|
|
final Account account = Account.restoreAccountWithId(mContext, mAccountId);
|
|
if (account == null) {
|
|
return null;
|
|
}
|
|
|
|
final long policyId = account.mPolicyKey;
|
|
if (policyId != 0) {
|
|
account.mPolicy = Policy.restorePolicyWithId(mContext, policyId);
|
|
}
|
|
|
|
account.getOrCreateHostAuthRecv(mContext);
|
|
|
|
return account;
|
|
}
|
|
|
|
@Override
|
|
protected void onDiscardResult(Account result) {}
|
|
}
|
|
|
|
protected void completeCreate(final Account account, final boolean showDialog,
|
|
final boolean passwordExpiring, final boolean passwordExpired) {
|
|
mAccount = account;
|
|
|
|
// Special handling for password expiration events
|
|
if (passwordExpiring || passwordExpired) {
|
|
FragmentManager fm = getFragmentManager();
|
|
if (fm.findFragmentByTag("password_expiration") == null) {
|
|
PasswordExpirationDialog dialog =
|
|
PasswordExpirationDialog.newInstance(mAccount.getDisplayName(),
|
|
passwordExpired);
|
|
if (DebugUtils.DEBUG || DEBUG) {
|
|
LogUtils.d(TAG, "Showing password expiration dialog");
|
|
}
|
|
dialog.show(fm, "password_expiration");
|
|
}
|
|
return;
|
|
}
|
|
// Otherwise, handle normal security settings flow
|
|
if (mAccount.mPolicyKey != 0) {
|
|
// This account wants to control security
|
|
if (showDialog) {
|
|
// Show dialog first, unless already showing (e.g. after rotation)
|
|
FragmentManager fm = getFragmentManager();
|
|
if (fm.findFragmentByTag("security_needed") == null) {
|
|
SecurityNeededDialog dialog =
|
|
SecurityNeededDialog.newInstance(mAccount.getDisplayName());
|
|
if (DebugUtils.DEBUG || DEBUG) {
|
|
LogUtils.d(TAG, "Showing security needed dialog");
|
|
}
|
|
dialog.show(fm, "security_needed");
|
|
}
|
|
} else {
|
|
// Go directly to security settings
|
|
tryAdvanceSecurity(mAccount);
|
|
}
|
|
return;
|
|
}
|
|
finish();
|
|
}
|
|
|
|
/**
|
|
* After any of the activities return, try to advance to the "next step"
|
|
*/
|
|
@Override
|
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
tryAdvanceSecurity(mAccount);
|
|
super.onActivityResult(requestCode, resultCode, data);
|
|
}
|
|
|
|
/**
|
|
* Walk the user through the required steps to become an active administrator and with
|
|
* the requisite security settings for the given account.
|
|
*
|
|
* These steps will be repeated each time we return from a given attempt (e.g. asking the
|
|
* user to choose a device pin/password). In a typical activation, we may repeat these
|
|
* steps a few times. It may go as far as step 5 (password) or step 6 (encryption), but it
|
|
* will terminate when step 2 (isActive()) succeeds.
|
|
*
|
|
* If at any point we do not advance beyond a given user step, (e.g. the user cancels
|
|
* instead of setting a password) we simply repost the security notification, and exit.
|
|
* We never want to loop here.
|
|
*/
|
|
private void tryAdvanceSecurity(Account account) {
|
|
SecurityPolicy security = SecurityPolicy.getInstance(this);
|
|
// Step 1. Check if we are an active device administrator, and stop here to activate
|
|
if (!security.isActiveAdmin()) {
|
|
if (mTriedAddAdministrator) {
|
|
if (DebugUtils.DEBUG || DEBUG) {
|
|
LogUtils.d(TAG, "Not active admin: repost notification");
|
|
}
|
|
repostNotification(account, security);
|
|
finish();
|
|
} else {
|
|
mTriedAddAdministrator = true;
|
|
// retrieve name of server for the format string
|
|
final HostAuth hostAuth = account.mHostAuthRecv;
|
|
if (hostAuth == null) {
|
|
if (DebugUtils.DEBUG || DEBUG) {
|
|
LogUtils.d(TAG, "No HostAuth: repost notification");
|
|
}
|
|
repostNotification(account, security);
|
|
finish();
|
|
} else {
|
|
if (DebugUtils.DEBUG || DEBUG) {
|
|
LogUtils.d(TAG, "Not active admin: post initial notification");
|
|
}
|
|
// try to become active - must happen here in activity, to get result
|
|
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
|
|
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
|
|
security.getAdminComponent());
|
|
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
|
|
this.getString(R.string.account_security_policy_explanation_fmt,
|
|
hostAuth.mAddress));
|
|
startActivityForResult(intent, REQUEST_ENABLE);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Step 2. Check if the current aggregate security policy is being satisfied by the
|
|
// DevicePolicyManager (the current system security level).
|
|
if (security.isActive(null)) {
|
|
if (DebugUtils.DEBUG || DEBUG) {
|
|
LogUtils.d(TAG, "Security active; clear holds");
|
|
}
|
|
Account.clearSecurityHoldOnAllAccounts(this);
|
|
security.syncAccount(account);
|
|
security.clearNotification();
|
|
finish();
|
|
return;
|
|
}
|
|
|
|
// Step 3. Try to assert the current aggregate security requirements with the system.
|
|
security.setActivePolicies();
|
|
|
|
// Step 4. Recheck the security policy, and determine what changes are needed (if any)
|
|
// to satisfy the requirements.
|
|
int inactiveReasons = security.getInactiveReasons(null);
|
|
|
|
// Step 5. If password is needed, try to have the user set it
|
|
if ((inactiveReasons & SecurityPolicy.INACTIVE_NEED_PASSWORD) != 0) {
|
|
if (mTriedSetPassword) {
|
|
if (DebugUtils.DEBUG || DEBUG) {
|
|
LogUtils.d(TAG, "Password needed; repost notification");
|
|
}
|
|
repostNotification(account, security);
|
|
finish();
|
|
} else {
|
|
if (DebugUtils.DEBUG || DEBUG) {
|
|
LogUtils.d(TAG, "Password needed; request it via DPM");
|
|
}
|
|
mTriedSetPassword = true;
|
|
// launch the activity to have the user set a new password.
|
|
Intent intent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
|
|
startActivityForResult(intent, REQUEST_PASSWORD);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Step 6. If encryption is needed, try to have the user set it
|
|
if ((inactiveReasons & SecurityPolicy.INACTIVE_NEED_ENCRYPTION) != 0) {
|
|
if (mTriedSetEncryption) {
|
|
if (DebugUtils.DEBUG || DEBUG) {
|
|
LogUtils.d(TAG, "Encryption needed; repost notification");
|
|
}
|
|
repostNotification(account, security);
|
|
finish();
|
|
} else {
|
|
if (DebugUtils.DEBUG || DEBUG) {
|
|
LogUtils.d(TAG, "Encryption needed; request it via DPM");
|
|
}
|
|
mTriedSetEncryption = true;
|
|
// launch the activity to start up encryption.
|
|
Intent intent = new Intent(DevicePolicyManager.ACTION_START_ENCRYPTION);
|
|
startActivityForResult(intent, REQUEST_ENCRYPTION);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Step 7. No problems were found, so clear holds and exit
|
|
if (DebugUtils.DEBUG || DEBUG) {
|
|
LogUtils.d(TAG, "Policies enforced; clear holds");
|
|
}
|
|
Account.clearSecurityHoldOnAllAccounts(this);
|
|
security.syncAccount(account);
|
|
security.clearNotification();
|
|
finish();
|
|
}
|
|
|
|
/**
|
|
* Mark an account as not-ready-for-sync and post a notification to bring the user back here
|
|
* eventually.
|
|
*/
|
|
private static void repostNotification(final Account account, final SecurityPolicy security) {
|
|
if (account == null) return;
|
|
new AsyncTask<Void, Void, Void>() {
|
|
@Override
|
|
protected Void doInBackground(Void... params) {
|
|
security.policiesRequired(account.mId);
|
|
return null;
|
|
}
|
|
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
}
|
|
|
|
/**
|
|
* Dialog briefly shown in some cases, to indicate the user that a security update is needed.
|
|
* If the user clicks OK, we proceed into the "tryAdvanceSecurity" flow. If the user cancels,
|
|
* we repost the notification and finish() the activity.
|
|
*/
|
|
public static class SecurityNeededDialog extends DialogFragment
|
|
implements DialogInterface.OnClickListener {
|
|
private static final String BUNDLE_KEY_ACCOUNT_NAME = "account_name";
|
|
|
|
// Public no-args constructor needed for fragment re-instantiation
|
|
public SecurityNeededDialog() {}
|
|
|
|
/**
|
|
* Create a new dialog.
|
|
*/
|
|
public static SecurityNeededDialog newInstance(String accountName) {
|
|
final SecurityNeededDialog dialog = new SecurityNeededDialog();
|
|
Bundle b = new Bundle();
|
|
b.putString(BUNDLE_KEY_ACCOUNT_NAME, accountName);
|
|
dialog.setArguments(b);
|
|
return dialog;
|
|
}
|
|
|
|
@Override
|
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
|
final String accountName = getArguments().getString(BUNDLE_KEY_ACCOUNT_NAME);
|
|
|
|
final Context context = getActivity();
|
|
final Resources res = context.getResources();
|
|
final AlertDialog.Builder b = new AlertDialog.Builder(context);
|
|
b.setTitle(R.string.account_security_dialog_title);
|
|
b.setIconAttribute(android.R.attr.alertDialogIcon);
|
|
b.setMessage(res.getString(R.string.account_security_dialog_content_fmt, accountName));
|
|
b.setPositiveButton(android.R.string.ok, this);
|
|
b.setNegativeButton(android.R.string.cancel, this);
|
|
if (DebugUtils.DEBUG || DEBUG) {
|
|
LogUtils.d(TAG, "Posting security needed dialog");
|
|
}
|
|
return b.create();
|
|
}
|
|
|
|
@Override
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
dismiss();
|
|
AccountSecurity activity = (AccountSecurity) getActivity();
|
|
if (activity.mAccount == null) {
|
|
// Clicked before activity fully restored - probably just monkey - exit quickly
|
|
activity.finish();
|
|
return;
|
|
}
|
|
switch (which) {
|
|
case DialogInterface.BUTTON_POSITIVE:
|
|
if (DebugUtils.DEBUG || DEBUG) {
|
|
LogUtils.d(TAG, "User accepts; advance to next step");
|
|
}
|
|
activity.tryAdvanceSecurity(activity.mAccount);
|
|
break;
|
|
case DialogInterface.BUTTON_NEGATIVE:
|
|
if (DebugUtils.DEBUG || DEBUG) {
|
|
LogUtils.d(TAG, "User declines; repost notification");
|
|
}
|
|
AccountSecurity.repostNotification(
|
|
activity.mAccount, SecurityPolicy.getInstance(activity));
|
|
activity.finish();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Dialog briefly shown in some cases, to indicate the user that the PIN/Password is expiring
|
|
* or has expired. If the user clicks OK, we launch the password settings screen.
|
|
*/
|
|
public static class PasswordExpirationDialog extends DialogFragment
|
|
implements DialogInterface.OnClickListener {
|
|
private static final String BUNDLE_KEY_ACCOUNT_NAME = "account_name";
|
|
private static final String BUNDLE_KEY_EXPIRED = "expired";
|
|
|
|
/**
|
|
* Create a new dialog.
|
|
*/
|
|
public static PasswordExpirationDialog newInstance(String accountName, boolean expired) {
|
|
final PasswordExpirationDialog dialog = new PasswordExpirationDialog();
|
|
Bundle b = new Bundle();
|
|
b.putString(BUNDLE_KEY_ACCOUNT_NAME, accountName);
|
|
b.putBoolean(BUNDLE_KEY_EXPIRED, expired);
|
|
dialog.setArguments(b);
|
|
return dialog;
|
|
}
|
|
|
|
// Public no-args constructor needed for fragment re-instantiation
|
|
public PasswordExpirationDialog() {}
|
|
|
|
/**
|
|
* Note, this actually creates two slightly different dialogs (for expiring vs. expired)
|
|
*/
|
|
@Override
|
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
|
final String accountName = getArguments().getString(BUNDLE_KEY_ACCOUNT_NAME);
|
|
final boolean expired = getArguments().getBoolean(BUNDLE_KEY_EXPIRED);
|
|
final int titleId = expired
|
|
? R.string.password_expired_dialog_title
|
|
: R.string.password_expire_warning_dialog_title;
|
|
final int contentId = expired
|
|
? R.string.password_expired_dialog_content_fmt
|
|
: R.string.password_expire_warning_dialog_content_fmt;
|
|
|
|
final Context context = getActivity();
|
|
final Resources res = context.getResources();
|
|
return new AlertDialog.Builder(context)
|
|
.setTitle(titleId)
|
|
.setIconAttribute(android.R.attr.alertDialogIcon)
|
|
.setMessage(res.getString(contentId, accountName))
|
|
.setPositiveButton(android.R.string.ok, this)
|
|
.setNegativeButton(android.R.string.cancel, this)
|
|
.create();
|
|
}
|
|
|
|
@Override
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
dismiss();
|
|
AccountSecurity activity = (AccountSecurity) getActivity();
|
|
if (which == DialogInterface.BUTTON_POSITIVE) {
|
|
Intent intent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
|
|
activity.startActivity(intent);
|
|
}
|
|
activity.finish();
|
|
}
|
|
}
|
|
}
|