Home | History | Annotate | Download | only in admin
      1 /*
      2  * Copyright (C) 2011 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.android.cts.verifier.admin;
     18 
     19 import com.android.cts.verifier.PassFailButtons;
     20 import com.android.cts.verifier.R;
     21 
     22 import android.app.AlertDialog;
     23 import android.app.admin.DevicePolicyManager;
     24 import android.content.ComponentName;
     25 import android.content.Context;
     26 import android.content.Intent;
     27 import android.content.SharedPreferences;
     28 import android.content.SharedPreferences.Editor;
     29 import android.os.Bundle;
     30 import android.view.View;
     31 import android.view.View.OnClickListener;
     32 import android.view.ViewGroup;
     33 import android.widget.ArrayAdapter;
     34 import android.widget.ListView;
     35 import android.widget.TextView;
     36 import android.widget.Toast;
     37 
     38 import java.util.ArrayList;
     39 import java.util.List;
     40 import java.util.Random;
     41 
     42 /**
     43  * Test that checks that device policies are properly saved and loaded across reboots. The user
     44  * clicks a button to generate a random policy and is then asked to reboot the device. When
     45  * returning to the test, the activity checks that the device manager is reporting the values
     46  * it set before the user rebooted the device.
     47  */
     48 public class PolicySerializationTestActivity extends PassFailButtons.ListActivity {
     49 
     50     /**
     51      * Whether or not to load the expected policy from the preferences and check against
     52      * what the {@link DevicePolicyManager} reports.
     53      */
     54     private static final String LOAD_EXPECTED_POLICY_PREFERENCE = "load-expected-policy";
     55 
     56     private static final int ADD_DEVICE_ADMIN_REQUEST_CODE = 1;
     57 
     58     private DevicePolicyManager mDevicePolicyManager;
     59     private ComponentName mAdmin;
     60 
     61     private List<PolicyItem<?>> mPolicyItems = new ArrayList<PolicyItem<?>>();
     62     private PolicyAdapter mAdapter;
     63 
     64     private View mGeneratePolicyButton;
     65     private View mApplyPolicyButton;
     66 
     67     @Override
     68     protected void onCreate(Bundle savedInstanceState) {
     69         super.onCreate(savedInstanceState);
     70         setContentView(R.layout.da_policy_main);
     71         setInfoResources(R.string.da_policy_serialization_test,
     72                 R.string.da_policy_serialization_info, -1);
     73         setPassFailButtonClickListeners();
     74 
     75         mDevicePolicyManager = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
     76         mAdmin = TestDeviceAdminReceiver.getComponent(this);
     77 
     78         mGeneratePolicyButton = findViewById(R.id.generate_policy_button);
     79         mGeneratePolicyButton.setOnClickListener(new OnClickListener() {
     80             @Override
     81             public void onClick(View v) {
     82                 generateRandomPolicy();
     83                 updateWidgets();
     84             }
     85         });
     86 
     87         mApplyPolicyButton = findViewById(R.id.apply_policy_button);
     88         mApplyPolicyButton.setOnClickListener(new OnClickListener() {
     89             @Override
     90             public void onClick(View v) {
     91                 applyPolicy();
     92             }
     93         });
     94 
     95         mPolicyItems.add(new PasswordQualityPolicy(this));
     96         mPolicyItems.add(new PasswordMinimumLengthPolicy(this));
     97         mPolicyItems.add(new MaximumFailedPasswordsForWipePolicy(this));
     98         mPolicyItems.add(new MaximumTimeToLockPolicy(this));
     99         mAdapter = new PolicyAdapter(this);
    100         setListAdapter(mAdapter);
    101 
    102         loadPolicy();
    103         updateWidgets();
    104     }
    105 
    106     private void loadPolicy() {
    107         mAdapter.clear();
    108         SharedPreferences prefs = getPreferences(MODE_PRIVATE);
    109         if (prefs.getBoolean(LOAD_EXPECTED_POLICY_PREFERENCE, false)) {
    110             for (PolicyItem<?> item : mPolicyItems) {
    111                 item.loadExpectedValue(prefs);
    112                 item.loadActualValue(mDevicePolicyManager, mAdmin);
    113                 mAdapter.add(item);
    114             }
    115         }
    116     }
    117 
    118     private void generateRandomPolicy() {
    119         Random random = new Random();
    120         mAdapter.clear();
    121         for (PolicyItem<?> item : mPolicyItems) {
    122             item.setRandomExpectedValue(random);
    123             item.resetActualValue();
    124             mAdapter.add(item);
    125         }
    126 
    127         SharedPreferences prefs = getPreferences(MODE_PRIVATE);
    128         SharedPreferences.Editor editor = prefs.edit();
    129         editor.clear();
    130         editor.putBoolean(LOAD_EXPECTED_POLICY_PREFERENCE, false);
    131         editor.apply();
    132 
    133         Toast.makeText(this, R.string.da_random_policy, Toast.LENGTH_SHORT).show();
    134     }
    135 
    136     private void applyPolicy() {
    137         Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
    138         intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
    139                 TestDeviceAdminReceiver.getComponent(this));
    140         startActivityForResult(intent, ADD_DEVICE_ADMIN_REQUEST_CODE);
    141     }
    142 
    143     @Override
    144     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    145         super.onActivityResult(requestCode, resultCode, data);
    146         switch (requestCode) {
    147             case ADD_DEVICE_ADMIN_REQUEST_CODE:
    148                 handleAddDeviceAdminResult(resultCode, data);
    149                 break;
    150         }
    151     }
    152 
    153     private void handleAddDeviceAdminResult(int resultCode, Intent data) {
    154         if (resultCode == RESULT_OK) {
    155             ComponentName admin = TestDeviceAdminReceiver.getComponent(this);
    156             for (PolicyItem<?> item : mPolicyItems) {
    157                 item.applyExpectedValue(mDevicePolicyManager, admin);
    158             }
    159 
    160             SharedPreferences prefs = getPreferences(MODE_PRIVATE);
    161             SharedPreferences.Editor editor = prefs.edit();
    162             editor.clear();
    163             editor.putBoolean(LOAD_EXPECTED_POLICY_PREFERENCE, true);
    164             for (PolicyItem<?> item : mPolicyItems) {
    165                 item.saveExpectedValue(editor);
    166             }
    167             editor.apply();
    168             showRebootDialog();
    169         }
    170     }
    171 
    172     private void showRebootDialog() {
    173         new AlertDialog.Builder(this)
    174             .setIcon(android.R.drawable.ic_dialog_info)
    175             .setTitle(R.string.da_policy_serialization_test)
    176             .setMessage(R.string.da_policy_reboot)
    177             .setPositiveButton(android.R.string.ok, null)
    178             .show();
    179     }
    180 
    181     private void updateWidgets() {
    182         mApplyPolicyButton.setEnabled(!mAdapter.isEmpty());
    183 
    184         // All items need to have been serialized properly for the pass button to activate.
    185         boolean enablePass = !mAdapter.isEmpty();
    186         int numItems = mAdapter.getCount();
    187         for (int i = 0; i < numItems; i++) {
    188             PolicyItem<?> item = mAdapter.getItem(i);
    189             if (!item.matchesExpectedValue()) {
    190                 enablePass = false;
    191             }
    192         }
    193         getPassButton().setEnabled(enablePass);
    194     }
    195 
    196     @Override
    197     protected void onListItemClick(ListView l, View v, int position, long id) {
    198         super.onListItemClick(l, v, position, id);
    199         PolicyItem<?> item = mAdapter.getItem(position);
    200         new AlertDialog.Builder(this)
    201             .setIcon(android.R.drawable.ic_dialog_info)
    202             .setTitle(item.getDisplayName())
    203             .setMessage(getString(R.string.da_policy_info,
    204                     item.getDisplayExpectedValue(),
    205                     item.getDisplayActualValue()))
    206             .setPositiveButton(android.R.string.ok, null)
    207             .show();
    208     }
    209 
    210     static class PolicyAdapter extends ArrayAdapter<PolicyItem<?>> {
    211 
    212         public PolicyAdapter(Context context) {
    213             super(context, android.R.layout.simple_list_item_1);
    214         }
    215 
    216         @Override
    217         public View getView(int position, View convertView, ViewGroup parent) {
    218             TextView view = (TextView) super.getView(position, convertView, parent);
    219 
    220             PolicyItem<?> item = getItem(position);
    221             int backgroundResource = 0;
    222             int iconResource = 0;
    223             if (item.getExpectedValue() != null && item.getActualValue() != null) {
    224                 if (item.matchesExpectedValue()) {
    225                     backgroundResource = R.drawable.test_pass_gradient;
    226                     iconResource = R.drawable.fs_good;
    227                 } else {
    228                     backgroundResource = R.drawable.test_fail_gradient;
    229                     iconResource = R.drawable.fs_error;
    230                 }
    231             }
    232             view.setBackgroundResource(backgroundResource);
    233             view.setPadding(10, 0, 10, 0);
    234             view.setCompoundDrawablePadding(10);
    235             view.setCompoundDrawablesWithIntrinsicBounds(0, 0, iconResource, 0);
    236 
    237             return view;
    238         }
    239     }
    240 
    241     interface PolicyItem<T> {
    242 
    243         void setRandomExpectedValue(Random random);
    244 
    245         void applyExpectedValue(DevicePolicyManager deviceManager, ComponentName admin);
    246 
    247         void loadExpectedValue(SharedPreferences prefs);
    248 
    249         void saveExpectedValue(SharedPreferences.Editor editor);
    250 
    251         void resetActualValue();
    252 
    253         void loadActualValue(DevicePolicyManager deviceManager, ComponentName admin);
    254 
    255         String getDisplayName();
    256 
    257         T getExpectedValue();
    258 
    259         String getDisplayExpectedValue();
    260 
    261         T getActualValue();
    262 
    263         String getDisplayActualValue();
    264 
    265         boolean matchesExpectedValue();
    266     }
    267 
    268     static abstract class BasePolicyItem<T> implements PolicyItem<T> {
    269         private String mDisplayName;
    270         private T mExpectedValue;
    271         private T mActualValue;
    272 
    273         BasePolicyItem(Context context, int nameResId) {
    274             mDisplayName = context.getString(nameResId);
    275         }
    276 
    277         @Override
    278         public final void setRandomExpectedValue(Random random) {
    279             mExpectedValue = getRandomExpectedValue(random);
    280         }
    281 
    282         protected abstract T getRandomExpectedValue(Random random);
    283 
    284         @Override
    285         public final void loadExpectedValue(SharedPreferences prefs) {
    286             mExpectedValue = getPreferencesValue(prefs);
    287         }
    288 
    289         protected abstract T getPreferencesValue(SharedPreferences prefs);
    290 
    291         @Override
    292         public final void loadActualValue(DevicePolicyManager deviceManager, ComponentName admin) {
    293             mActualValue = getDeviceManagerValue(deviceManager, admin);
    294         }
    295 
    296         protected abstract T getDeviceManagerValue(DevicePolicyManager deviceManager,
    297                 ComponentName admin);
    298 
    299         @Override
    300         public final void resetActualValue() {
    301             mActualValue = null;
    302         }
    303 
    304         @Override
    305         public final String getDisplayName() {
    306             return mDisplayName;
    307         }
    308 
    309         @Override
    310         public final T getExpectedValue() {
    311             return mExpectedValue;
    312         }
    313 
    314         @Override
    315         public final String getDisplayExpectedValue() {
    316             return mExpectedValue != null ? getDisplayValue(mExpectedValue) : "";
    317         }
    318 
    319         @Override
    320         public final T getActualValue() {
    321             return mActualValue;
    322         }
    323 
    324         @Override
    325         public final String getDisplayActualValue() {
    326             return mActualValue != null ? getDisplayValue(mActualValue) : "";
    327         }
    328 
    329         protected String getDisplayValue(T value) {
    330             return "" + value;
    331         }
    332 
    333         @Override
    334         public final boolean matchesExpectedValue() {
    335             return mExpectedValue != null && mExpectedValue.equals(mActualValue);
    336         }
    337 
    338         @Override
    339         public String toString() {
    340             return getDisplayName();
    341         }
    342     }
    343 
    344     static abstract class IntegerPolicyItem extends BasePolicyItem<Integer> {
    345 
    346         private String mPreferenceKey;
    347 
    348         IntegerPolicyItem(Context context, int nameResId, String preferenceKey) {
    349             super(context, nameResId);
    350             mPreferenceKey = preferenceKey;
    351         }
    352 
    353         @Override
    354         protected final Integer getPreferencesValue(SharedPreferences prefs) {
    355             return prefs.getInt(mPreferenceKey, -1);
    356         }
    357 
    358         @Override
    359         public final void saveExpectedValue(Editor editor) {
    360             editor.putInt(mPreferenceKey, getExpectedValue());
    361         }
    362     }
    363 
    364     static abstract class LongPolicyItem extends BasePolicyItem<Long> {
    365 
    366         private String mPreferenceKey;
    367 
    368         LongPolicyItem(Context context, int nameResId, String preferenceKey) {
    369             super(context, nameResId);
    370             mPreferenceKey = preferenceKey;
    371         }
    372 
    373         @Override
    374         protected final Long getPreferencesValue(SharedPreferences prefs) {
    375             return prefs.getLong(mPreferenceKey, -1);
    376         }
    377 
    378         @Override
    379         public final void saveExpectedValue(Editor editor) {
    380             editor.putLong(mPreferenceKey, getExpectedValue());
    381         }
    382     }
    383 
    384     static class PasswordQualityPolicy extends IntegerPolicyItem {
    385 
    386         private final Context mContext;
    387 
    388         public PasswordQualityPolicy(Context context) {
    389             super(context, R.string.da_password_quality, "password-quality");
    390             mContext = context;
    391         }
    392 
    393         @Override
    394         protected Integer getRandomExpectedValue(Random random) {
    395             int[] passwordQualities = new int[] {
    396                     DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC,
    397                     DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC,
    398                     DevicePolicyManager.PASSWORD_QUALITY_NUMERIC,
    399                     DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
    400             };
    401 
    402             int index = random.nextInt(passwordQualities.length);
    403             return passwordQualities[index];
    404         }
    405 
    406         @Override
    407         public void applyExpectedValue(DevicePolicyManager deviceManager, ComponentName admin) {
    408             deviceManager.setPasswordQuality(admin, getExpectedValue());
    409         }
    410 
    411         @Override
    412         protected Integer getDeviceManagerValue(DevicePolicyManager deviceManager,
    413                 ComponentName admin) {
    414             return deviceManager.getPasswordQuality(admin);
    415         }
    416 
    417         @Override
    418         protected String getDisplayValue(Integer value) {
    419             switch (value) {
    420                 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
    421                     return mContext.getString(R.string.da_password_quality_alphabetic);
    422                 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
    423                     return mContext.getString(R.string.da_password_quality_alphanumeric);
    424                 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
    425                     return mContext.getString(R.string.da_password_quality_numeric);
    426                 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
    427                     return mContext.getString(R.string.da_password_quality_something);
    428                 default:
    429                     return Integer.toString(value);
    430             }
    431         }
    432     }
    433 
    434     static class PasswordMinimumLengthPolicy extends IntegerPolicyItem {
    435 
    436         PasswordMinimumLengthPolicy(Context context) {
    437             super(context, R.string.da_password_minimum_length, "password-minimum-length");
    438         }
    439 
    440         @Override
    441         protected Integer getRandomExpectedValue(Random random) {
    442             return random.nextInt(50);
    443         }
    444 
    445         @Override
    446         public void applyExpectedValue(DevicePolicyManager deviceManager, ComponentName admin) {
    447             deviceManager.setPasswordMinimumLength(admin, getExpectedValue());
    448         }
    449 
    450         @Override
    451         protected Integer getDeviceManagerValue(DevicePolicyManager deviceManager,
    452                 ComponentName admin) {
    453             return deviceManager.getPasswordMinimumLength(admin);
    454         }
    455     }
    456 
    457     static class MaximumFailedPasswordsForWipePolicy extends IntegerPolicyItem {
    458 
    459         MaximumFailedPasswordsForWipePolicy(Context context) {
    460             super(context, R.string.da_maximum_failed_passwords_for_wipe,
    461                     "maximum-failed-passwords-for-wipe");
    462         }
    463 
    464         @Override
    465         protected Integer getRandomExpectedValue(Random random) {
    466             return random.nextInt(50);
    467         }
    468 
    469         @Override
    470         public void applyExpectedValue(DevicePolicyManager deviceManager, ComponentName admin) {
    471             deviceManager.setMaximumFailedPasswordsForWipe(admin, getExpectedValue());
    472         }
    473 
    474         @Override
    475         protected Integer getDeviceManagerValue(DevicePolicyManager deviceManager,
    476                 ComponentName admin) {
    477             return deviceManager.getMaximumFailedPasswordsForWipe(admin);
    478         }
    479     }
    480 
    481     static class MaximumTimeToLockPolicy extends LongPolicyItem {
    482 
    483         MaximumTimeToLockPolicy(Context context) {
    484             super(context, R.string.da_maximum_time_to_lock, "maximum-time-to-lock");
    485         }
    486 
    487         @Override
    488         protected Long getRandomExpectedValue(Random random) {
    489             return (long)(1000 + random.nextInt(60 * 60 * 1000));
    490         }
    491 
    492         @Override
    493         public void applyExpectedValue(DevicePolicyManager deviceManager, ComponentName admin) {
    494             deviceManager.setMaximumTimeToLock(admin, getExpectedValue());
    495         }
    496 
    497         @Override
    498         protected Long getDeviceManagerValue(DevicePolicyManager deviceManager,
    499                 ComponentName admin) {
    500             return deviceManager.getMaximumTimeToLock(admin);
    501         }
    502     }
    503 }
    504