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