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