Home | History | Annotate | Download | only in app
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.example.android.apis.app;
     18 
     19 import com.example.android.apis.R;
     20 
     21 import android.app.ActivityManager;
     22 import android.app.AlertDialog;
     23 import android.app.admin.DeviceAdminReceiver;
     24 import android.app.admin.DevicePolicyManager;
     25 import android.content.ComponentName;
     26 import android.content.Context;
     27 import android.content.DialogInterface;
     28 import android.content.Intent;
     29 import android.content.SharedPreferences;
     30 import android.os.Bundle;
     31 import android.os.PersistableBundle;
     32 import android.preference.CheckBoxPreference;
     33 import android.preference.EditTextPreference;
     34 import android.preference.ListPreference;
     35 import android.preference.Preference;
     36 import android.preference.Preference.OnPreferenceChangeListener;
     37 import android.preference.Preference.OnPreferenceClickListener;
     38 import android.preference.PreferenceActivity;
     39 import android.preference.PreferenceCategory;
     40 import android.preference.PreferenceFragment;
     41 import android.preference.PreferenceScreen;
     42 import android.text.TextUtils;
     43 import android.util.Log;
     44 import android.widget.Toast;
     45 
     46 import java.util.ArrayList;
     47 import java.util.Arrays;
     48 import java.util.List;
     49 
     50 /**
     51  * This activity provides a comprehensive UI for exploring and operating the DevicePolicyManager
     52  * api.  It consists of two primary modules:
     53  *
     54  * 1:  A device policy controller, implemented here as a series of preference fragments.  Each
     55  *     one contains code to monitor and control a particular subset of device policies.
     56  *
     57  * 2:  A DeviceAdminReceiver, to receive updates from the DevicePolicyManager when certain aspects
     58  *     of the device security status have changed.
     59  */
     60 public class DeviceAdminSample extends PreferenceActivity {
     61 
     62     // Miscellaneous utilities and definitions
     63     private static final String TAG = "DeviceAdminSample";
     64 
     65     private static final int REQUEST_CODE_ENABLE_ADMIN = 1;
     66     private static final int REQUEST_CODE_START_ENCRYPTION = 2;
     67 
     68     private static final long MS_PER_MINUTE = 60 * 1000;
     69     private static final long MS_PER_HOUR = 60 * MS_PER_MINUTE;
     70     private static final long MS_PER_DAY = 24 * MS_PER_HOUR;
     71 
     72     // The following keys are used to find each preference item
     73     private static final String KEY_ENABLE_ADMIN = "key_enable_admin";
     74     private static final String KEY_DISABLE_CAMERA = "key_disable_camera";
     75     private static final String KEY_DISABLE_NOTIFICATIONS = "key_disable_notifications";
     76     private static final String KEY_DISABLE_UNREDACTED = "key_disable_unredacted";
     77     private static final String KEY_DISABLE_TRUST_AGENTS = "key_disable_trust_agents";
     78     private static final String KEY_TRUST_AGENT_COMPONENT = "key_trust_agent_component";
     79     private static final String KEY_TRUST_AGENT_FEATURES = "key_trust_agent_features";
     80     private static final String KEY_DISABLE_KEYGUARD_WIDGETS = "key_disable_keyguard_widgets";
     81     private static final String KEY_DISABLE_KEYGUARD_SECURE_CAMERA
     82             = "key_disable_keyguard_secure_camera";
     83     private static final String KEY_DISABLE_FINGERPRINT = "key_disable_fingerprint";
     84     private static final String KEY_DISABLE_REMOTE_INPUT = "key_disable_remote_input";
     85 
     86     private static final String KEY_CATEGORY_QUALITY = "key_category_quality";
     87     private static final String KEY_SET_PASSWORD = "key_set_password";
     88     private static final String KEY_RESET_PASSWORD = "key_reset_password";
     89     private static final String KEY_QUALITY = "key_quality";
     90     private static final String KEY_MIN_LENGTH = "key_minimum_length";
     91     private static final String KEY_MIN_LETTERS = "key_minimum_letters";
     92     private static final String KEY_MIN_NUMERIC = "key_minimum_numeric";
     93     private static final String KEY_MIN_LOWER_CASE = "key_minimum_lower_case";
     94     private static final String KEY_MIN_UPPER_CASE = "key_minimum_upper_case";
     95     private static final String KEY_MIN_SYMBOLS = "key_minimum_symbols";
     96     private static final String KEY_MIN_NON_LETTER = "key_minimum_non_letter";
     97 
     98     private static final String KEY_CATEGORY_EXPIRATION = "key_category_expiration";
     99     private static final String KEY_HISTORY = "key_history";
    100     private static final String KEY_EXPIRATION_TIMEOUT = "key_expiration_timeout";
    101     private static final String KEY_EXPIRATION_STATUS = "key_expiration_status";
    102 
    103     private static final String KEY_CATEGORY_LOCK_WIPE = "key_category_lock_wipe";
    104     private static final String KEY_MAX_TIME_SCREEN_LOCK = "key_max_time_screen_lock";
    105     private static final String KEY_MAX_FAILS_BEFORE_WIPE = "key_max_fails_before_wipe";
    106     private static final String KEY_LOCK_SCREEN = "key_lock_screen";
    107     private static final String KEY_WIPE_DATA = "key_wipe_data";
    108     private static final String KEY_WIP_DATA_ALL = "key_wipe_data_all";
    109 
    110     private static final String KEY_CATEGORY_ENCRYPTION = "key_category_encryption";
    111     private static final String KEY_REQUIRE_ENCRYPTION = "key_require_encryption";
    112     private static final String KEY_ACTIVATE_ENCRYPTION = "key_activate_encryption";
    113 
    114     // Interaction with the DevicePolicyManager
    115     DevicePolicyManager mDPM;
    116     ComponentName mDeviceAdminSample;
    117 
    118     @Override
    119     protected void onCreate(Bundle savedInstanceState) {
    120         super.onCreate(savedInstanceState);
    121 
    122         // Prepare to work with the DPM
    123         mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
    124         mDeviceAdminSample = new ComponentName(this, DeviceAdminSampleReceiver.class);
    125     }
    126 
    127     /**
    128      * We override this method to provide PreferenceActivity with the top-level preference headers.
    129      */
    130     @Override
    131     public void onBuildHeaders(List<Header> target) {
    132         loadHeadersFromResource(R.xml.device_admin_headers, target);
    133     }
    134 
    135     /**
    136      * Helper to determine if we are an active admin
    137      */
    138     private boolean isActiveAdmin() {
    139         return mDPM.isAdminActive(mDeviceAdminSample);
    140     }
    141 
    142     @Override
    143     protected boolean isValidFragment(String fragmentName) {
    144         return GeneralFragment.class.getName().equals(fragmentName)
    145                 || QualityFragment.class.getName().equals(fragmentName)
    146                 || ExpirationFragment.class.getName().equals(fragmentName)
    147                 || LockWipeFragment.class.getName().equals(fragmentName)
    148                 || EncryptionFragment.class.getName().equals(fragmentName);
    149     }
    150 
    151     /**
    152      * Common fragment code for DevicePolicyManager access.  Provides two shared elements:
    153      *
    154      *   1.  Provides instance variables to access activity/context, DevicePolicyManager, etc.
    155      *   2.  Provides support for the "set password" button(s) shared by multiple fragments.
    156      */
    157     public static class AdminSampleFragment extends PreferenceFragment
    158             implements OnPreferenceChangeListener, OnPreferenceClickListener{
    159 
    160         // Useful instance variables
    161         protected DeviceAdminSample mActivity;
    162         protected DevicePolicyManager mDPM;
    163         protected ComponentName mDeviceAdminSample;
    164         protected boolean mAdminActive;
    165 
    166         // Optional shared UI
    167         private PreferenceScreen mSetPassword;
    168         private EditTextPreference mResetPassword;
    169 
    170         @Override
    171         public void onActivityCreated(Bundle savedInstanceState) {
    172             super.onActivityCreated(savedInstanceState);
    173 
    174             // Retrieve the useful instance variables
    175             mActivity = (DeviceAdminSample) getActivity();
    176             mDPM = mActivity.mDPM;
    177             mDeviceAdminSample = mActivity.mDeviceAdminSample;
    178             mAdminActive = mActivity.isActiveAdmin();
    179 
    180             // Configure the shared UI elements (if they exist)
    181             mResetPassword = (EditTextPreference) findPreference(KEY_RESET_PASSWORD);
    182             mSetPassword = (PreferenceScreen) findPreference(KEY_SET_PASSWORD);
    183 
    184             if (mResetPassword != null) {
    185                 mResetPassword.setOnPreferenceChangeListener(this);
    186             }
    187             if (mSetPassword != null) {
    188                 mSetPassword.setOnPreferenceClickListener(this);
    189             }
    190         }
    191 
    192         @Override
    193         public void onResume() {
    194             super.onResume();
    195             mAdminActive = mActivity.isActiveAdmin();
    196             reloadSummaries();
    197             // Resetting the password via API is available only to active admins
    198             if (mResetPassword != null) {
    199                 mResetPassword.setEnabled(mAdminActive);
    200             }
    201         }
    202 
    203         /**
    204          * Called automatically at every onResume.  Should also call explicitly any time a
    205          * policy changes that may affect other policy values.
    206          */
    207         protected void reloadSummaries() {
    208             if (mSetPassword != null) {
    209                 if (mAdminActive) {
    210                     // Show password-sufficient status under Set Password button
    211                     boolean sufficient = mDPM.isActivePasswordSufficient();
    212                     mSetPassword.setSummary(sufficient ?
    213                             R.string.password_sufficient : R.string.password_insufficient);
    214                 } else {
    215                     mSetPassword.setSummary(null);
    216                 }
    217             }
    218         }
    219 
    220         protected void postReloadSummaries() {
    221             getView().post(new Runnable() {
    222                 @Override
    223                 public void run() {
    224                     reloadSummaries();
    225                 }
    226             });
    227         }
    228 
    229         @Override
    230         public boolean onPreferenceClick(Preference preference) {
    231             if (mSetPassword != null && preference == mSetPassword) {
    232                 Intent intent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
    233                 startActivity(intent);
    234                 return true;
    235             }
    236             return false;
    237         }
    238 
    239         @Override
    240         public boolean onPreferenceChange(Preference preference, Object newValue) {
    241             if (mResetPassword != null && preference == mResetPassword) {
    242                 doResetPassword((String)newValue);
    243                 return true;
    244             }
    245             return false;
    246         }
    247 
    248         /**
    249          * This is dangerous, so we prevent automated tests from doing it, and we
    250          * remind the user after we do it.
    251          */
    252         private void doResetPassword(String newPassword) {
    253             if (alertIfMonkey(mActivity, R.string.monkey_reset_password)) {
    254                 return;
    255             }
    256             mDPM.resetPassword(newPassword, DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY);
    257             AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
    258             String message = mActivity.getString(R.string.reset_password_warning, newPassword);
    259             builder.setMessage(message);
    260             builder.setPositiveButton(R.string.reset_password_ok, null);
    261             builder.show();
    262         }
    263 
    264         /**
    265          * Simple helper for summaries showing local & global (aggregate) policy settings
    266          */
    267         protected String localGlobalSummary(Object local, Object global) {
    268             return getString(R.string.status_local_global, local, global);
    269         }
    270     }
    271 
    272     /**
    273      * PreferenceFragment for "general" preferences.
    274      */
    275     public static class GeneralFragment extends AdminSampleFragment
    276             implements OnPreferenceChangeListener {
    277         // UI elements
    278         private CheckBoxPreference mEnableCheckbox;
    279         private CheckBoxPreference mDisableCameraCheckbox;
    280         private CheckBoxPreference mDisableKeyguardWidgetsCheckbox;
    281         private CheckBoxPreference mDisableKeyguardSecureCameraCheckbox;
    282         private CheckBoxPreference mDisableKeyguardNotificationCheckbox;
    283         private CheckBoxPreference mDisableKeyguardTrustAgentCheckbox;
    284         private CheckBoxPreference mDisableKeyguardUnredactedCheckbox;
    285         private EditTextPreference mTrustAgentComponent;
    286         private EditTextPreference mTrustAgentFeatures;
    287         private CheckBoxPreference mDisableKeyguardFingerprintCheckbox;
    288         private CheckBoxPreference mDisableKeyguardRemoteInputCheckbox;
    289 
    290         @Override
    291         public void onCreate(Bundle savedInstanceState) {
    292             super.onCreate(savedInstanceState);
    293             addPreferencesFromResource(R.xml.device_admin_general);
    294             mEnableCheckbox = (CheckBoxPreference) findPreference(KEY_ENABLE_ADMIN);
    295             mEnableCheckbox.setOnPreferenceChangeListener(this);
    296 
    297             mDisableCameraCheckbox = (CheckBoxPreference) findPreference(KEY_DISABLE_CAMERA);
    298             mDisableCameraCheckbox.setOnPreferenceChangeListener(this);
    299 
    300             mDisableKeyguardWidgetsCheckbox =
    301                 (CheckBoxPreference) findPreference(KEY_DISABLE_KEYGUARD_WIDGETS);
    302             mDisableKeyguardWidgetsCheckbox.setOnPreferenceChangeListener(this);
    303 
    304             mDisableKeyguardSecureCameraCheckbox =
    305                 (CheckBoxPreference) findPreference(KEY_DISABLE_KEYGUARD_SECURE_CAMERA);
    306             mDisableKeyguardSecureCameraCheckbox.setOnPreferenceChangeListener(this);
    307 
    308             mDisableKeyguardNotificationCheckbox =
    309                     (CheckBoxPreference) findPreference(KEY_DISABLE_NOTIFICATIONS);
    310             mDisableKeyguardNotificationCheckbox.setOnPreferenceChangeListener(this);
    311 
    312             mDisableKeyguardUnredactedCheckbox =
    313                     (CheckBoxPreference) findPreference(KEY_DISABLE_UNREDACTED);
    314             mDisableKeyguardUnredactedCheckbox.setOnPreferenceChangeListener(this);
    315 
    316             mDisableKeyguardFingerprintCheckbox =
    317                     (CheckBoxPreference) findPreference(KEY_DISABLE_FINGERPRINT);
    318             mDisableKeyguardFingerprintCheckbox.setOnPreferenceChangeListener(this);
    319 
    320             mDisableKeyguardRemoteInputCheckbox =
    321                     (CheckBoxPreference) findPreference(KEY_DISABLE_REMOTE_INPUT);
    322             mDisableKeyguardRemoteInputCheckbox.setOnPreferenceChangeListener(this);
    323 
    324             mDisableKeyguardTrustAgentCheckbox =
    325                     (CheckBoxPreference) findPreference(KEY_DISABLE_TRUST_AGENTS);
    326             mDisableKeyguardTrustAgentCheckbox.setOnPreferenceChangeListener(this);
    327 
    328             mTrustAgentComponent =
    329                     (EditTextPreference) findPreference(KEY_TRUST_AGENT_COMPONENT);
    330             mTrustAgentComponent.setOnPreferenceChangeListener(this);
    331 
    332             mTrustAgentFeatures =
    333                     (EditTextPreference) findPreference(KEY_TRUST_AGENT_FEATURES);
    334             mTrustAgentFeatures.setOnPreferenceChangeListener(this);
    335         }
    336 
    337         // At onResume time, reload UI with current values as required
    338         @Override
    339         public void onResume() {
    340             super.onResume();
    341             mEnableCheckbox.setChecked(mAdminActive);
    342             enableDeviceCapabilitiesArea(mAdminActive);
    343 
    344             if (mAdminActive) {
    345                 mDPM.setCameraDisabled(mDeviceAdminSample, mDisableCameraCheckbox.isChecked());
    346                 mDPM.setKeyguardDisabledFeatures(mDeviceAdminSample, createKeyguardDisabledFlag());
    347                 reloadSummaries();
    348             }
    349         }
    350 
    351         int createKeyguardDisabledFlag() {
    352             int flags = DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
    353             flags |= mDisableKeyguardWidgetsCheckbox.isChecked() ?
    354                     DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_ALL : 0;
    355             flags |= mDisableKeyguardSecureCameraCheckbox.isChecked() ?
    356                     DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA : 0;
    357             flags |= mDisableKeyguardNotificationCheckbox.isChecked() ?
    358                     DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS : 0;
    359             flags |= mDisableKeyguardUnredactedCheckbox.isChecked() ?
    360                     DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS : 0;
    361             flags |= mDisableKeyguardTrustAgentCheckbox.isChecked() ?
    362                     DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS : 0;
    363             flags |= mDisableKeyguardFingerprintCheckbox.isChecked() ?
    364                     DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT : 0;
    365             flags |= mDisableKeyguardRemoteInputCheckbox.isChecked() ?
    366                     DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT : 0;
    367             return flags;
    368         }
    369 
    370         @Override
    371         public boolean onPreferenceChange(Preference preference, Object newValue) {
    372             if (super.onPreferenceChange(preference, newValue)) {
    373                 return true;
    374             }
    375             if (preference == mEnableCheckbox) {
    376                 boolean value = (Boolean) newValue;
    377                 if (value != mAdminActive) {
    378                     if (value) {
    379                         // Launch the activity to have the user enable our admin.
    380                         Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
    381                         intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mDeviceAdminSample);
    382                         intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
    383                                 mActivity.getString(R.string.add_admin_extra_app_text));
    384                         startActivityForResult(intent, REQUEST_CODE_ENABLE_ADMIN);
    385                         // return false - don't update checkbox until we're really active
    386                         return false;
    387                     } else {
    388                         mDPM.removeActiveAdmin(mDeviceAdminSample);
    389                         enableDeviceCapabilitiesArea(false);
    390                         mAdminActive = false;
    391                     }
    392                 }
    393             } else if (preference == mDisableCameraCheckbox) {
    394                 boolean value = (Boolean) newValue;
    395                 mDPM.setCameraDisabled(mDeviceAdminSample, value);
    396                 // Delay update because the change is only applied after exiting this method.
    397                 postReloadSummaries();
    398             } else if (preference == mDisableKeyguardWidgetsCheckbox
    399                     || preference == mDisableKeyguardSecureCameraCheckbox
    400                     || preference == mDisableKeyguardNotificationCheckbox
    401                     || preference == mDisableKeyguardUnredactedCheckbox
    402                     || preference == mDisableKeyguardTrustAgentCheckbox
    403                     || preference == mDisableKeyguardFingerprintCheckbox
    404                     || preference == mDisableKeyguardRemoteInputCheckbox
    405                     || preference == mTrustAgentComponent
    406                     || preference == mTrustAgentFeatures) {
    407                 postUpdateDpmDisableFeatures();
    408                 postReloadSummaries();
    409             }
    410             return true;
    411         }
    412 
    413         private void postUpdateDpmDisableFeatures() {
    414             getView().post(new Runnable() {
    415                 @Override
    416                 public void run() {
    417                     mDPM.setKeyguardDisabledFeatures(mDeviceAdminSample,
    418                             createKeyguardDisabledFlag());
    419                     String component = mTrustAgentComponent.getText();
    420                     if (component != null) {
    421                         ComponentName agent = ComponentName.unflattenFromString(component);
    422                         if (agent != null) {
    423                             String featureString = mTrustAgentFeatures.getText();
    424                             if (featureString != null) {
    425                                 PersistableBundle bundle = new PersistableBundle();
    426                                 bundle.putStringArray("features", featureString.split(","));
    427                                 mDPM.setTrustAgentConfiguration(mDeviceAdminSample, agent, bundle);
    428                             }
    429                         } else {
    430                             Log.w(TAG, "Invalid component: " + component);
    431                         }
    432                     }
    433                 }
    434             });
    435         }
    436 
    437         @Override
    438         protected void reloadSummaries() {
    439             super.reloadSummaries();
    440             String cameraSummary = getString(mDPM.getCameraDisabled(mDeviceAdminSample)
    441                     ? R.string.camera_disabled : R.string.camera_enabled);
    442             mDisableCameraCheckbox.setSummary(cameraSummary);
    443 
    444             int disabled = mDPM.getKeyguardDisabledFeatures(mDeviceAdminSample);
    445 
    446             String keyguardWidgetSummary = getString(
    447                     (disabled & DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_ALL) != 0 ?
    448                             R.string.keyguard_widgets_disabled : R.string.keyguard_widgets_enabled);
    449             mDisableKeyguardWidgetsCheckbox.setSummary(keyguardWidgetSummary);
    450 
    451             String keyguardSecureCameraSummary = getString(
    452                 (disabled & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0 ?
    453                 R.string.keyguard_secure_camera_disabled : R.string.keyguard_secure_camera_enabled);
    454             mDisableKeyguardSecureCameraCheckbox.setSummary(keyguardSecureCameraSummary);
    455 
    456             String keyguardSecureNotificationsSummary = getString(
    457                     (disabled & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) != 0 ?
    458                         R.string.keyguard_secure_notifications_disabled
    459                         : R.string.keyguard_secure_notifications_enabled);
    460             mDisableKeyguardNotificationCheckbox.setSummary(keyguardSecureNotificationsSummary);
    461 
    462             String keyguardUnredactedSummary = getString(
    463                     (disabled & DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) != 0
    464                         ? R.string.keyguard_unredacted_notifications_disabled
    465                         : R.string.keyguard_unredacted_notifications_enabled);
    466             mDisableKeyguardUnredactedCheckbox.setSummary(keyguardUnredactedSummary);
    467 
    468             String keyguardEnableTrustAgentSummary = getString(
    469                     (disabled & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0 ?
    470                         R.string.keyguard_trust_agents_disabled
    471                         : R.string.keyguard_trust_agents_enabled);
    472             mDisableKeyguardTrustAgentCheckbox.setSummary(keyguardEnableTrustAgentSummary);
    473 
    474             String keyguardEnableFingerprintSummary = getString(
    475                     (disabled & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0 ?
    476                         R.string.keyguard_fingerprint_disabled
    477                         : R.string.keyguard_fingerprint_enabled);
    478             mDisableKeyguardFingerprintCheckbox.setSummary(keyguardEnableFingerprintSummary);
    479 
    480             String keyguardEnableRemoteInputSummary = getString(
    481                     (disabled & DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT) != 0 ?
    482                         R.string.keyguard_remote_input_disabled
    483                         : R.string.keyguard_remote_input_enabled);
    484             mDisableKeyguardRemoteInputCheckbox.setSummary(keyguardEnableRemoteInputSummary);
    485 
    486             final SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
    487             final boolean trustDisabled =
    488                     (disabled & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
    489             String component = prefs.getString(mTrustAgentComponent.getKey(), null);
    490             mTrustAgentComponent.setSummary(component);
    491             mTrustAgentComponent.setEnabled(trustDisabled);
    492 
    493             String features = prefs.getString(mTrustAgentFeatures.getKey(), null);
    494             mTrustAgentFeatures.setSummary(features);
    495             mTrustAgentFeatures.setEnabled(trustDisabled);
    496         }
    497 
    498         /** Updates the device capabilities area (dis/enabling) as the admin is (de)activated */
    499         private void enableDeviceCapabilitiesArea(boolean enabled) {
    500             mDisableCameraCheckbox.setEnabled(enabled);
    501             mDisableKeyguardWidgetsCheckbox.setEnabled(enabled);
    502             mDisableKeyguardSecureCameraCheckbox.setEnabled(enabled);
    503             mDisableKeyguardNotificationCheckbox.setEnabled(enabled);
    504             mDisableKeyguardUnredactedCheckbox.setEnabled(enabled);
    505             mDisableKeyguardTrustAgentCheckbox.setEnabled(enabled);
    506             mTrustAgentComponent.setEnabled(enabled);
    507             mTrustAgentFeatures.setEnabled(enabled);
    508         }
    509     }
    510 
    511     /**
    512      * PreferenceFragment for "password quality" preferences.
    513      */
    514     public static class QualityFragment extends AdminSampleFragment
    515             implements OnPreferenceChangeListener {
    516 
    517         // Password quality values
    518         // This list must match the list found in samples/ApiDemos/res/values/arrays.xml
    519         final static int[] mPasswordQualityValues = new int[] {
    520             DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
    521             DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
    522             DevicePolicyManager.PASSWORD_QUALITY_NUMERIC,
    523             DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX,
    524             DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC,
    525             DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC,
    526             DevicePolicyManager.PASSWORD_QUALITY_COMPLEX
    527         };
    528 
    529         // Password quality values (as strings, for the ListPreference entryValues)
    530         // This list must match the list found in samples/ApiDemos/res/values/arrays.xml
    531         final static String[] mPasswordQualityValueStrings = new String[] {
    532             String.valueOf(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED),
    533             String.valueOf(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING),
    534             String.valueOf(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC),
    535             String.valueOf(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX),
    536             String.valueOf(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC),
    537             String.valueOf(DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC),
    538             String.valueOf(DevicePolicyManager.PASSWORD_QUALITY_COMPLEX)
    539         };
    540 
    541         // UI elements
    542         private PreferenceCategory mQualityCategory;
    543         private ListPreference mPasswordQuality;
    544         private EditTextPreference mMinLength;
    545         private EditTextPreference mMinLetters;
    546         private EditTextPreference mMinNumeric;
    547         private EditTextPreference mMinLowerCase;
    548         private EditTextPreference mMinUpperCase;
    549         private EditTextPreference mMinSymbols;
    550         private EditTextPreference mMinNonLetter;
    551 
    552         @Override
    553         public void onCreate(Bundle savedInstanceState) {
    554             super.onCreate(savedInstanceState);
    555             addPreferencesFromResource(R.xml.device_admin_quality);
    556 
    557             mQualityCategory = (PreferenceCategory) findPreference(KEY_CATEGORY_QUALITY);
    558             mPasswordQuality = (ListPreference) findPreference(KEY_QUALITY);
    559             mMinLength = (EditTextPreference) findPreference(KEY_MIN_LENGTH);
    560             mMinLetters = (EditTextPreference) findPreference(KEY_MIN_LETTERS);
    561             mMinNumeric = (EditTextPreference) findPreference(KEY_MIN_NUMERIC);
    562             mMinLowerCase = (EditTextPreference) findPreference(KEY_MIN_LOWER_CASE);
    563             mMinUpperCase = (EditTextPreference) findPreference(KEY_MIN_UPPER_CASE);
    564             mMinSymbols = (EditTextPreference) findPreference(KEY_MIN_SYMBOLS);
    565             mMinNonLetter = (EditTextPreference) findPreference(KEY_MIN_NON_LETTER);
    566 
    567             mPasswordQuality.setOnPreferenceChangeListener(this);
    568             mMinLength.setOnPreferenceChangeListener(this);
    569             mMinLetters.setOnPreferenceChangeListener(this);
    570             mMinNumeric.setOnPreferenceChangeListener(this);
    571             mMinLowerCase.setOnPreferenceChangeListener(this);
    572             mMinUpperCase.setOnPreferenceChangeListener(this);
    573             mMinSymbols.setOnPreferenceChangeListener(this);
    574             mMinNonLetter.setOnPreferenceChangeListener(this);
    575 
    576             // Finish setup of the quality dropdown
    577             mPasswordQuality.setEntryValues(mPasswordQualityValueStrings);
    578         }
    579 
    580         @Override
    581         public void onResume() {
    582             super.onResume();
    583             mQualityCategory.setEnabled(mAdminActive);
    584         }
    585 
    586         /**
    587          * Update the summaries of each item to show the local setting and the global setting.
    588          */
    589         @Override
    590         protected void reloadSummaries() {
    591             super.reloadSummaries();
    592             // Show numeric settings for each policy API
    593             int local, global;
    594             local = mDPM.getPasswordQuality(mDeviceAdminSample);
    595             global = mDPM.getPasswordQuality(null);
    596             mPasswordQuality.setSummary(
    597                     localGlobalSummary(qualityValueToString(local), qualityValueToString(global)));
    598             local = mDPM.getPasswordMinimumLength(mDeviceAdminSample);
    599             global = mDPM.getPasswordMinimumLength(null);
    600             mMinLength.setSummary(localGlobalSummary(local, global));
    601             local = mDPM.getPasswordMinimumLetters(mDeviceAdminSample);
    602             global = mDPM.getPasswordMinimumLetters(null);
    603             mMinLetters.setSummary(localGlobalSummary(local, global));
    604             local = mDPM.getPasswordMinimumNumeric(mDeviceAdminSample);
    605             global = mDPM.getPasswordMinimumNumeric(null);
    606             mMinNumeric.setSummary(localGlobalSummary(local, global));
    607             local = mDPM.getPasswordMinimumLowerCase(mDeviceAdminSample);
    608             global = mDPM.getPasswordMinimumLowerCase(null);
    609             mMinLowerCase.setSummary(localGlobalSummary(local, global));
    610             local = mDPM.getPasswordMinimumUpperCase(mDeviceAdminSample);
    611             global = mDPM.getPasswordMinimumUpperCase(null);
    612             mMinUpperCase.setSummary(localGlobalSummary(local, global));
    613             local = mDPM.getPasswordMinimumSymbols(mDeviceAdminSample);
    614             global = mDPM.getPasswordMinimumSymbols(null);
    615             mMinSymbols.setSummary(localGlobalSummary(local, global));
    616             local = mDPM.getPasswordMinimumNonLetter(mDeviceAdminSample);
    617             global = mDPM.getPasswordMinimumNonLetter(null);
    618             mMinNonLetter.setSummary(localGlobalSummary(local, global));
    619         }
    620 
    621         @Override
    622         public boolean onPreferenceChange(Preference preference, Object newValue) {
    623             if (super.onPreferenceChange(preference, newValue)) {
    624                 return true;
    625             }
    626             String valueString = (String)newValue;
    627             if (TextUtils.isEmpty(valueString)) {
    628                 return false;
    629             }
    630             int value = 0;
    631             try {
    632                 value = Integer.parseInt(valueString);
    633             } catch (NumberFormatException nfe) {
    634                 String warning = mActivity.getString(R.string.number_format_warning, valueString);
    635                 Toast.makeText(mActivity, warning, Toast.LENGTH_SHORT).show();
    636             }
    637             if (preference == mPasswordQuality) {
    638                 mDPM.setPasswordQuality(mDeviceAdminSample, value);
    639             } else if (preference == mMinLength) {
    640                 mDPM.setPasswordMinimumLength(mDeviceAdminSample, value);
    641             } else if (preference == mMinLetters) {
    642                 mDPM.setPasswordMinimumLetters(mDeviceAdminSample, value);
    643             } else if (preference == mMinNumeric) {
    644                 mDPM.setPasswordMinimumNumeric(mDeviceAdminSample, value);
    645             } else if (preference == mMinLowerCase) {
    646                 mDPM.setPasswordMinimumLowerCase(mDeviceAdminSample, value);
    647             } else if (preference == mMinUpperCase) {
    648                 mDPM.setPasswordMinimumUpperCase(mDeviceAdminSample, value);
    649             } else if (preference == mMinSymbols) {
    650                 mDPM.setPasswordMinimumSymbols(mDeviceAdminSample, value);
    651             } else if (preference == mMinNonLetter) {
    652                 mDPM.setPasswordMinimumNonLetter(mDeviceAdminSample, value);
    653             }
    654             // Delay update because the change is only applied after exiting this method.
    655             postReloadSummaries();
    656             return true;
    657         }
    658 
    659         private String qualityValueToString(int quality) {
    660             for (int i=  0; i < mPasswordQualityValues.length; i++) {
    661                 if (mPasswordQualityValues[i] == quality) {
    662                     String[] qualities =
    663                         mActivity.getResources().getStringArray(R.array.password_qualities);
    664                     return qualities[i];
    665                 }
    666             }
    667             return "(0x" + Integer.toString(quality, 16) + ")";
    668         }
    669     }
    670 
    671     /**
    672      * PreferenceFragment for "password expiration" preferences.
    673      */
    674     public static class ExpirationFragment extends AdminSampleFragment
    675             implements OnPreferenceChangeListener, OnPreferenceClickListener {
    676         private PreferenceCategory mExpirationCategory;
    677         private EditTextPreference mHistory;
    678         private EditTextPreference mExpirationTimeout;
    679         private PreferenceScreen mExpirationStatus;
    680 
    681         @Override
    682         public void onCreate(Bundle savedInstanceState) {
    683             super.onCreate(savedInstanceState);
    684             addPreferencesFromResource(R.xml.device_admin_expiration);
    685 
    686             mExpirationCategory = (PreferenceCategory) findPreference(KEY_CATEGORY_EXPIRATION);
    687             mHistory = (EditTextPreference) findPreference(KEY_HISTORY);
    688             mExpirationTimeout = (EditTextPreference) findPreference(KEY_EXPIRATION_TIMEOUT);
    689             mExpirationStatus = (PreferenceScreen) findPreference(KEY_EXPIRATION_STATUS);
    690 
    691             mHistory.setOnPreferenceChangeListener(this);
    692             mExpirationTimeout.setOnPreferenceChangeListener(this);
    693             mExpirationStatus.setOnPreferenceClickListener(this);
    694         }
    695 
    696         @Override
    697         public void onResume() {
    698             super.onResume();
    699             mExpirationCategory.setEnabled(mAdminActive);
    700         }
    701 
    702         /**
    703          * Update the summaries of each item to show the local setting and the global setting.
    704          */
    705         @Override
    706         protected void reloadSummaries() {
    707             super.reloadSummaries();
    708 
    709             int local, global;
    710             local = mDPM.getPasswordHistoryLength(mDeviceAdminSample);
    711             global = mDPM.getPasswordHistoryLength(null);
    712             mHistory.setSummary(localGlobalSummary(local, global));
    713 
    714             long localLong, globalLong;
    715             localLong = mDPM.getPasswordExpirationTimeout(mDeviceAdminSample);
    716             globalLong = mDPM.getPasswordExpirationTimeout(null);
    717             mExpirationTimeout.setSummary(localGlobalSummary(
    718                     localLong / MS_PER_MINUTE, globalLong / MS_PER_MINUTE));
    719 
    720             String expirationStatus = getExpirationStatus();
    721             mExpirationStatus.setSummary(expirationStatus);
    722         }
    723 
    724         @Override
    725         public boolean onPreferenceChange(Preference preference, Object newValue) {
    726             if (super.onPreferenceChange(preference, newValue)) {
    727                 return true;
    728             }
    729             String valueString = (String)newValue;
    730             if (TextUtils.isEmpty(valueString)) {
    731                 return false;
    732             }
    733             int value = 0;
    734             try {
    735                 value = Integer.parseInt(valueString);
    736             } catch (NumberFormatException nfe) {
    737                 String warning = mActivity.getString(R.string.number_format_warning, valueString);
    738                 Toast.makeText(mActivity, warning, Toast.LENGTH_SHORT).show();
    739             }
    740             if (preference == mHistory) {
    741                 mDPM.setPasswordHistoryLength(mDeviceAdminSample, value);
    742             } else if (preference == mExpirationTimeout) {
    743                 mDPM.setPasswordExpirationTimeout(mDeviceAdminSample, value * MS_PER_MINUTE);
    744             }
    745             // Delay update because the change is only applied after exiting this method.
    746             postReloadSummaries();
    747             return true;
    748         }
    749 
    750         @Override
    751         public boolean onPreferenceClick(Preference preference) {
    752             if (super.onPreferenceClick(preference)) {
    753                 return true;
    754             }
    755             if (preference == mExpirationStatus) {
    756                 String expirationStatus = getExpirationStatus();
    757                 mExpirationStatus.setSummary(expirationStatus);
    758                 return true;
    759             }
    760             return false;
    761         }
    762 
    763         /**
    764          * Create a summary string describing the expiration status for the sample app,
    765          * as well as the global (aggregate) status.
    766          */
    767         private String getExpirationStatus() {
    768             // expirations are absolute;  convert to relative for display
    769             long localExpiration = mDPM.getPasswordExpiration(mDeviceAdminSample);
    770             long globalExpiration = mDPM.getPasswordExpiration(null);
    771             long now = System.currentTimeMillis();
    772 
    773             // local expiration
    774             String local;
    775             if (localExpiration == 0) {
    776                 local = mActivity.getString(R.string.expiration_status_none);
    777             } else {
    778                 localExpiration -= now;
    779                 String dms = timeToDaysMinutesSeconds(mActivity, Math.abs(localExpiration));
    780                 if (localExpiration >= 0) {
    781                     local = mActivity.getString(R.string.expiration_status_future, dms);
    782                 } else {
    783                     local = mActivity.getString(R.string.expiration_status_past, dms);
    784                 }
    785             }
    786 
    787             // global expiration
    788             String global;
    789             if (globalExpiration == 0) {
    790                 global = mActivity.getString(R.string.expiration_status_none);
    791             } else {
    792                 globalExpiration -= now;
    793                 String dms = timeToDaysMinutesSeconds(mActivity, Math.abs(globalExpiration));
    794                 if (globalExpiration >= 0) {
    795                     global = mActivity.getString(R.string.expiration_status_future, dms);
    796                 } else {
    797                     global = mActivity.getString(R.string.expiration_status_past, dms);
    798                 }
    799             }
    800             return mActivity.getString(R.string.status_local_global, local, global);
    801         }
    802     }
    803 
    804     /**
    805      * PreferenceFragment for "lock screen & wipe" preferences.
    806      */
    807     public static class LockWipeFragment extends AdminSampleFragment
    808             implements OnPreferenceChangeListener, OnPreferenceClickListener {
    809         private PreferenceCategory mLockWipeCategory;
    810         private EditTextPreference mMaxTimeScreenLock;
    811         private EditTextPreference mMaxFailures;
    812         private PreferenceScreen mLockScreen;
    813         private PreferenceScreen mWipeData;
    814         private PreferenceScreen mWipeAppData;
    815 
    816         @Override
    817         public void onCreate(Bundle savedInstanceState) {
    818             super.onCreate(savedInstanceState);
    819             addPreferencesFromResource(R.xml.device_admin_lock_wipe);
    820 
    821             mLockWipeCategory = (PreferenceCategory) findPreference(KEY_CATEGORY_LOCK_WIPE);
    822             mMaxTimeScreenLock = (EditTextPreference) findPreference(KEY_MAX_TIME_SCREEN_LOCK);
    823             mMaxFailures = (EditTextPreference) findPreference(KEY_MAX_FAILS_BEFORE_WIPE);
    824             mLockScreen = (PreferenceScreen) findPreference(KEY_LOCK_SCREEN);
    825             mWipeData = (PreferenceScreen) findPreference(KEY_WIPE_DATA);
    826             mWipeAppData = (PreferenceScreen) findPreference(KEY_WIP_DATA_ALL);
    827 
    828             mMaxTimeScreenLock.setOnPreferenceChangeListener(this);
    829             mMaxFailures.setOnPreferenceChangeListener(this);
    830             mLockScreen.setOnPreferenceClickListener(this);
    831             mWipeData.setOnPreferenceClickListener(this);
    832             mWipeAppData.setOnPreferenceClickListener(this);
    833         }
    834 
    835         @Override
    836         public void onResume() {
    837             super.onResume();
    838             mLockWipeCategory.setEnabled(mAdminActive);
    839         }
    840 
    841         /**
    842          * Update the summaries of each item to show the local setting and the global setting.
    843          */
    844         @Override
    845         protected void reloadSummaries() {
    846             super.reloadSummaries();
    847 
    848             long localLong, globalLong;
    849             localLong = mDPM.getMaximumTimeToLock(mDeviceAdminSample);
    850             globalLong = mDPM.getMaximumTimeToLock(null);
    851             mMaxTimeScreenLock.setSummary(localGlobalSummary(
    852                     localLong / MS_PER_MINUTE, globalLong / MS_PER_MINUTE));
    853 
    854             int local, global;
    855             local = mDPM.getMaximumFailedPasswordsForWipe(mDeviceAdminSample);
    856             global = mDPM.getMaximumFailedPasswordsForWipe(null);
    857             mMaxFailures.setSummary(localGlobalSummary(local, global));
    858         }
    859 
    860         @Override
    861         public boolean onPreferenceChange(Preference preference, Object newValue) {
    862             if (super.onPreferenceChange(preference, newValue)) {
    863                 return true;
    864             }
    865             String valueString = (String)newValue;
    866             if (TextUtils.isEmpty(valueString)) {
    867                 return false;
    868             }
    869             int value = 0;
    870             try {
    871                 value = Integer.parseInt(valueString);
    872             } catch (NumberFormatException nfe) {
    873                 String warning = mActivity.getString(R.string.number_format_warning, valueString);
    874                 Toast.makeText(mActivity, warning, Toast.LENGTH_SHORT).show();
    875             }
    876             if (preference == mMaxTimeScreenLock) {
    877                 mDPM.setMaximumTimeToLock(mDeviceAdminSample, value * MS_PER_MINUTE);
    878             } else if (preference == mMaxFailures) {
    879                 if (alertIfMonkey(mActivity, R.string.monkey_wipe_data)) {
    880                     return true;
    881                 }
    882                 mDPM.setMaximumFailedPasswordsForWipe(mDeviceAdminSample, value);
    883             }
    884             // Delay update because the change is only applied after exiting this method.
    885             postReloadSummaries();
    886             return true;
    887         }
    888 
    889         @Override
    890         public boolean onPreferenceClick(Preference preference) {
    891             if (super.onPreferenceClick(preference)) {
    892                 return true;
    893             }
    894             if (preference == mLockScreen) {
    895                 if (alertIfMonkey(mActivity, R.string.monkey_lock_screen)) {
    896                     return true;
    897                 }
    898                 mDPM.lockNow();
    899                 return true;
    900             } else if (preference == mWipeData || preference == mWipeAppData) {
    901                 if (alertIfMonkey(mActivity, R.string.monkey_wipe_data)) {
    902                     return true;
    903                 }
    904                 promptForRealDeviceWipe(preference == mWipeAppData);
    905                 return true;
    906             }
    907             return false;
    908         }
    909 
    910         /**
    911          * Wiping data is real, so we don't want it to be easy.  Show two alerts before wiping.
    912          */
    913         private void promptForRealDeviceWipe(final boolean wipeAllData) {
    914             final DeviceAdminSample activity = mActivity;
    915 
    916             AlertDialog.Builder builder = new AlertDialog.Builder(activity);
    917             builder.setMessage(R.string.wipe_warning_first);
    918             builder.setPositiveButton(R.string.wipe_warning_first_ok,
    919                     new DialogInterface.OnClickListener() {
    920                 @Override
    921                 public void onClick(DialogInterface dialog, int which) {
    922                     AlertDialog.Builder builder = new AlertDialog.Builder(activity);
    923                     if (wipeAllData) {
    924                         builder.setMessage(R.string.wipe_warning_second_full);
    925                     } else {
    926                         builder.setMessage(R.string.wipe_warning_second);
    927                     }
    928                     builder.setPositiveButton(R.string.wipe_warning_second_ok,
    929                             new DialogInterface.OnClickListener() {
    930                         @Override
    931                         public void onClick(DialogInterface dialog, int which) {
    932                             boolean stillActive = mActivity.isActiveAdmin();
    933                             if (stillActive) {
    934                                 mDPM.wipeData(wipeAllData
    935                                         ? DevicePolicyManager.WIPE_EXTERNAL_STORAGE : 0);
    936                             }
    937                         }
    938                     });
    939                     builder.setNegativeButton(R.string.wipe_warning_second_no, null);
    940                     builder.show();
    941                 }
    942             });
    943             builder.setNegativeButton(R.string.wipe_warning_first_no, null);
    944             builder.show();
    945         }
    946     }
    947 
    948     /**
    949      * PreferenceFragment for "encryption" preferences.
    950      */
    951     public static class EncryptionFragment extends AdminSampleFragment
    952             implements OnPreferenceChangeListener, OnPreferenceClickListener {
    953         private PreferenceCategory mEncryptionCategory;
    954         private CheckBoxPreference mRequireEncryption;
    955         private PreferenceScreen mActivateEncryption;
    956 
    957         @Override
    958         public void onCreate(Bundle savedInstanceState) {
    959             super.onCreate(savedInstanceState);
    960             addPreferencesFromResource(R.xml.device_admin_encryption);
    961 
    962             mEncryptionCategory = (PreferenceCategory) findPreference(KEY_CATEGORY_ENCRYPTION);
    963             mRequireEncryption = (CheckBoxPreference) findPreference(KEY_REQUIRE_ENCRYPTION);
    964             mActivateEncryption = (PreferenceScreen) findPreference(KEY_ACTIVATE_ENCRYPTION);
    965 
    966             mRequireEncryption.setOnPreferenceChangeListener(this);
    967             mActivateEncryption.setOnPreferenceClickListener(this);
    968         }
    969 
    970         @Override
    971         public void onResume() {
    972             super.onResume();
    973             mEncryptionCategory.setEnabled(mAdminActive);
    974             mRequireEncryption.setChecked(mDPM.getStorageEncryption(mDeviceAdminSample));
    975         }
    976 
    977         /**
    978          * Update the summaries of each item to show the local setting and the global setting.
    979          */
    980         @Override
    981         protected void reloadSummaries() {
    982             super.reloadSummaries();
    983 
    984             boolean local, global;
    985             local = mDPM.getStorageEncryption(mDeviceAdminSample);
    986             global = mDPM.getStorageEncryption(null);
    987             mRequireEncryption.setSummary(localGlobalSummary(local, global));
    988 
    989             int deviceStatusCode = mDPM.getStorageEncryptionStatus();
    990             String deviceStatus = statusCodeToString(deviceStatusCode);
    991             String status = mActivity.getString(R.string.status_device_encryption, deviceStatus);
    992             mActivateEncryption.setSummary(status);
    993         }
    994 
    995         @Override
    996         public boolean onPreferenceChange(Preference preference, Object newValue) {
    997             if (super.onPreferenceChange(preference, newValue)) {
    998                 return true;
    999             }
   1000             if (preference == mRequireEncryption) {
   1001                 boolean newActive = (Boolean) newValue;
   1002                 mDPM.setStorageEncryption(mDeviceAdminSample, newActive);
   1003                 // Delay update because the change is only applied after exiting this method.
   1004                 postReloadSummaries();
   1005                 return true;
   1006             }
   1007             return true;
   1008         }
   1009 
   1010         @Override
   1011         public boolean onPreferenceClick(Preference preference) {
   1012             if (super.onPreferenceClick(preference)) {
   1013                 return true;
   1014             }
   1015             if (preference == mActivateEncryption) {
   1016                 if (alertIfMonkey(mActivity, R.string.monkey_encryption)) {
   1017                     return true;
   1018                 }
   1019                 // Check to see if encryption is even supported on this device (it's optional).
   1020                 if (mDPM.getStorageEncryptionStatus() ==
   1021                         DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED) {
   1022                     AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
   1023                     builder.setMessage(R.string.encryption_not_supported);
   1024                     builder.setPositiveButton(R.string.encryption_not_supported_ok, null);
   1025                     builder.show();
   1026                     return true;
   1027                 }
   1028                 // Launch the activity to activate encryption.  May or may not return!
   1029                 Intent intent = new Intent(DevicePolicyManager.ACTION_START_ENCRYPTION);
   1030                 startActivityForResult(intent, REQUEST_CODE_START_ENCRYPTION);
   1031                 return true;
   1032             }
   1033             return false;
   1034         }
   1035 
   1036         private String statusCodeToString(int newStatusCode) {
   1037             int newStatus = R.string.encryption_status_unknown;
   1038             switch (newStatusCode) {
   1039                 case DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED:
   1040                     newStatus = R.string.encryption_status_unsupported;
   1041                     break;
   1042                 case DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE:
   1043                     newStatus = R.string.encryption_status_inactive;
   1044                     break;
   1045                 case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVATING:
   1046                     newStatus = R.string.encryption_status_activating;
   1047                     break;
   1048                 case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE:
   1049                     newStatus = R.string.encryption_status_active;
   1050                     break;
   1051             }
   1052             return mActivity.getString(newStatus);
   1053         }
   1054     }
   1055 
   1056     /**
   1057      * Simple converter used for long expiration times reported in mSec.
   1058      */
   1059     private static String timeToDaysMinutesSeconds(Context context, long time) {
   1060         long days = time / MS_PER_DAY;
   1061         long hours = (time / MS_PER_HOUR) % 24;
   1062         long minutes = (time / MS_PER_MINUTE) % 60;
   1063         return context.getString(R.string.status_days_hours_minutes, days, hours, minutes);
   1064     }
   1065 
   1066     /**
   1067      * If the "user" is a monkey, post an alert and notify the caller.  This prevents automated
   1068      * test frameworks from stumbling into annoying or dangerous operations.
   1069      */
   1070     private static boolean alertIfMonkey(Context context, int stringId) {
   1071         if (ActivityManager.isUserAMonkey()) {
   1072             AlertDialog.Builder builder = new AlertDialog.Builder(context);
   1073             builder.setMessage(stringId);
   1074             builder.setPositiveButton(R.string.monkey_ok, null);
   1075             builder.show();
   1076             return true;
   1077         } else {
   1078             return false;
   1079         }
   1080     }
   1081 
   1082     /**
   1083      * Sample implementation of a DeviceAdminReceiver.  Your controller must provide one,
   1084      * although you may or may not implement all of the methods shown here.
   1085      *
   1086      * All callbacks are on the UI thread and your implementations should not engage in any
   1087      * blocking operations, including disk I/O.
   1088      */
   1089     public static class DeviceAdminSampleReceiver extends DeviceAdminReceiver {
   1090         void showToast(Context context, String msg) {
   1091             String status = context.getString(R.string.admin_receiver_status, msg);
   1092             Toast.makeText(context, status, Toast.LENGTH_SHORT).show();
   1093         }
   1094 
   1095         @Override
   1096         public void onReceive(Context context, Intent intent) {
   1097             if (intent.getAction() == ACTION_DEVICE_ADMIN_DISABLE_REQUESTED) {
   1098                 abortBroadcast();
   1099             }
   1100             super.onReceive(context, intent);
   1101         }
   1102 
   1103         @Override
   1104         public void onEnabled(Context context, Intent intent) {
   1105             showToast(context, context.getString(R.string.admin_receiver_status_enabled));
   1106         }
   1107 
   1108         @Override
   1109         public CharSequence onDisableRequested(Context context, Intent intent) {
   1110             return context.getString(R.string.admin_receiver_status_disable_warning);
   1111         }
   1112 
   1113         @Override
   1114         public void onDisabled(Context context, Intent intent) {
   1115             showToast(context, context.getString(R.string.admin_receiver_status_disabled));
   1116         }
   1117 
   1118         @Override
   1119         public void onPasswordChanged(Context context, Intent intent) {
   1120             showToast(context, context.getString(R.string.admin_receiver_status_pw_changed));
   1121         }
   1122 
   1123         @Override
   1124         public void onPasswordFailed(Context context, Intent intent) {
   1125             showToast(context, context.getString(R.string.admin_receiver_status_pw_failed));
   1126         }
   1127 
   1128         @Override
   1129         public void onPasswordSucceeded(Context context, Intent intent) {
   1130             showToast(context, context.getString(R.string.admin_receiver_status_pw_succeeded));
   1131         }
   1132 
   1133         @Override
   1134         public void onPasswordExpiring(Context context, Intent intent) {
   1135             DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
   1136                     Context.DEVICE_POLICY_SERVICE);
   1137             long expr = dpm.getPasswordExpiration(
   1138                     new ComponentName(context, DeviceAdminSampleReceiver.class));
   1139             long delta = expr - System.currentTimeMillis();
   1140             boolean expired = delta < 0L;
   1141             String message = context.getString(expired ?
   1142                     R.string.expiration_status_past : R.string.expiration_status_future);
   1143             showToast(context, message);
   1144             Log.v(TAG, message);
   1145         }
   1146     }
   1147 
   1148     public static class DeviceAdminSampleReceiver2 extends DeviceAdminReceiver {
   1149     }
   1150 }
   1151