DevicePolicyManagerService.java revision c994d693b684bcba1a690310b5b2be306074cc02
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 17package com.android.server; 18 19import com.android.internal.content.PackageMonitor; 20import com.android.internal.os.storage.ExternalStorageFormatter; 21import com.android.internal.util.FastXmlSerializer; 22import com.android.internal.util.JournaledFile; 23import com.android.internal.util.XmlUtils; 24import com.android.internal.widget.LockPatternUtils; 25 26import org.xmlpull.v1.XmlPullParser; 27import org.xmlpull.v1.XmlPullParserException; 28import org.xmlpull.v1.XmlSerializer; 29 30import android.app.Activity; 31import android.app.AlarmManager; 32import android.app.PendingIntent; 33import android.app.admin.DeviceAdminInfo; 34import android.app.admin.DeviceAdminReceiver; 35import android.app.admin.DevicePolicyManager; 36import android.app.admin.IDevicePolicyManager; 37import android.content.BroadcastReceiver; 38import android.content.ComponentName; 39import android.content.ContentResolver; 40import android.content.Context; 41import android.content.Intent; 42import android.content.IntentFilter; 43import android.content.pm.PackageManager; 44import android.content.pm.PackageManager.NameNotFoundException; 45import android.content.pm.ResolveInfo; 46import android.os.Binder; 47import android.os.Handler; 48import android.os.IBinder; 49import android.os.IPowerManager; 50import android.os.PowerManager; 51import android.os.RecoverySystem; 52import android.os.RemoteCallback; 53import android.os.RemoteException; 54import android.os.ServiceManager; 55import android.os.SystemClock; 56import android.os.SystemProperties; 57import android.provider.Settings; 58import android.util.PrintWriterPrinter; 59import android.util.Printer; 60import android.util.Slog; 61import android.util.Xml; 62import android.view.WindowManagerPolicy; 63 64import java.io.File; 65import java.io.FileDescriptor; 66import java.io.FileInputStream; 67import java.io.FileNotFoundException; 68import java.io.FileOutputStream; 69import java.io.IOException; 70import java.io.PrintWriter; 71import java.text.DateFormat; 72import java.util.ArrayList; 73import java.util.Date; 74import java.util.HashMap; 75import java.util.List; 76import java.util.Set; 77 78/** 79 * Implementation of the device policy APIs. 80 */ 81public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 82 private static final String TAG = "DevicePolicyManagerService"; 83 84 private static final int REQUEST_EXPIRE_PASSWORD = 5571; 85 86 private static final long EXPIRATION_GRACE_PERIOD_MS = 5 * 86400 * 1000; // 5 days, in ms 87 88 protected static final String ACTION_EXPIRED_PASSWORD_NOTIFICATION 89 = "com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION"; 90 91 private static final long MS_PER_DAY = 86400 * 1000; 92 93 final Context mContext; 94 final MyPackageMonitor mMonitor; 95 final PowerManager.WakeLock mWakeLock; 96 97 IPowerManager mIPowerManager; 98 99 int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 100 int mActivePasswordLength = 0; 101 int mActivePasswordUpperCase = 0; 102 int mActivePasswordLowerCase = 0; 103 int mActivePasswordLetters = 0; 104 int mActivePasswordNumeric = 0; 105 int mActivePasswordSymbols = 0; 106 int mActivePasswordNonLetter = 0; 107 int mFailedPasswordAttempts = 0; 108 109 int mPasswordOwner = -1; 110 Handler mHandler = new Handler(); 111 112 final HashMap<ComponentName, ActiveAdmin> mAdminMap 113 = new HashMap<ComponentName, ActiveAdmin>(); 114 final ArrayList<ActiveAdmin> mAdminList 115 = new ArrayList<ActiveAdmin>(); 116 117 BroadcastReceiver mReceiver = new BroadcastReceiver() { 118 @Override 119 public void onReceive(Context context, Intent intent) { 120 String action = intent.getAction(); 121 if (Intent.ACTION_BOOT_COMPLETED.equals(action) 122 || ACTION_EXPIRED_PASSWORD_NOTIFICATION.equals(action)) { 123 Slog.v(TAG, "Sending password expiration notifications for action " + action); 124 mHandler.post(new Runnable() { 125 public void run() { 126 handlePasswordExpirationNotification(); 127 } 128 }); 129 } 130 } 131 }; 132 133 static class ActiveAdmin { 134 final DeviceAdminInfo info; 135 136 int passwordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 137 138 static final int DEF_MINIMUM_PASSWORD_LENGTH = 0; 139 int minimumPasswordLength = DEF_MINIMUM_PASSWORD_LENGTH; 140 141 static final int DEF_PASSWORD_HISTORY_LENGTH = 0; 142 int passwordHistoryLength = DEF_PASSWORD_HISTORY_LENGTH; 143 144 static final int DEF_MINIMUM_PASSWORD_UPPER_CASE = 0; 145 int minimumPasswordUpperCase = DEF_MINIMUM_PASSWORD_UPPER_CASE; 146 147 static final int DEF_MINIMUM_PASSWORD_LOWER_CASE = 0; 148 int minimumPasswordLowerCase = DEF_MINIMUM_PASSWORD_LOWER_CASE; 149 150 static final int DEF_MINIMUM_PASSWORD_LETTERS = 1; 151 int minimumPasswordLetters = DEF_MINIMUM_PASSWORD_LOWER_CASE; 152 153 static final int DEF_MINIMUM_PASSWORD_NUMERIC = 1; 154 int minimumPasswordNumeric = DEF_MINIMUM_PASSWORD_NUMERIC; 155 156 static final int DEF_MINIMUM_PASSWORD_SYMBOLS = 1; 157 int minimumPasswordSymbols = DEF_MINIMUM_PASSWORD_SYMBOLS; 158 159 static final int DEF_MINIMUM_PASSWORD_NON_LETTER = 0; 160 int minimumPasswordNonLetter = DEF_MINIMUM_PASSWORD_NON_LETTER; 161 162 static final long DEF_MAXIMUM_TIME_TO_UNLOCK = 0; 163 long maximumTimeToUnlock = DEF_MAXIMUM_TIME_TO_UNLOCK; 164 165 static final int DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE = 0; 166 int maximumFailedPasswordsForWipe = DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE; 167 168 static final long DEF_PASSWORD_EXPIRATION_TIMEOUT = 0; 169 long passwordExpirationTimeout = DEF_PASSWORD_EXPIRATION_TIMEOUT; 170 171 static final long DEF_PASSWORD_EXPIRATION_DATE = 0; 172 long passwordExpirationDate = DEF_PASSWORD_EXPIRATION_DATE; 173 174 boolean encryptionRequested = false; 175 176 // TODO: review implementation decisions with frameworks team 177 boolean specifiesGlobalProxy = false; 178 String globalProxySpec = null; 179 String globalProxyExclusionList = null; 180 181 ActiveAdmin(DeviceAdminInfo _info) { 182 info = _info; 183 } 184 185 int getUid() { return info.getActivityInfo().applicationInfo.uid; } 186 187 void writeToXml(XmlSerializer out) 188 throws IllegalArgumentException, IllegalStateException, IOException { 189 out.startTag(null, "policies"); 190 info.writePoliciesToXml(out); 191 out.endTag(null, "policies"); 192 if (passwordQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { 193 out.startTag(null, "password-quality"); 194 out.attribute(null, "value", Integer.toString(passwordQuality)); 195 out.endTag(null, "password-quality"); 196 if (minimumPasswordLength != DEF_MINIMUM_PASSWORD_LENGTH) { 197 out.startTag(null, "min-password-length"); 198 out.attribute(null, "value", Integer.toString(minimumPasswordLength)); 199 out.endTag(null, "min-password-length"); 200 } 201 if(passwordHistoryLength != DEF_PASSWORD_HISTORY_LENGTH) { 202 out.startTag(null, "password-history-length"); 203 out.attribute(null, "value", Integer.toString(passwordHistoryLength)); 204 out.endTag(null, "password-history-length"); 205 } 206 if (minimumPasswordUpperCase != DEF_MINIMUM_PASSWORD_UPPER_CASE) { 207 out.startTag(null, "min-password-uppercase"); 208 out.attribute(null, "value", Integer.toString(minimumPasswordUpperCase)); 209 out.endTag(null, "min-password-uppercase"); 210 } 211 if (minimumPasswordLowerCase != DEF_MINIMUM_PASSWORD_LOWER_CASE) { 212 out.startTag(null, "min-password-lowercase"); 213 out.attribute(null, "value", Integer.toString(minimumPasswordLowerCase)); 214 out.endTag(null, "min-password-lowercase"); 215 } 216 if (minimumPasswordLetters != DEF_MINIMUM_PASSWORD_LETTERS) { 217 out.startTag(null, "min-password-letters"); 218 out.attribute(null, "value", Integer.toString(minimumPasswordLetters)); 219 out.endTag(null, "min-password-letters"); 220 } 221 if (minimumPasswordNumeric != DEF_MINIMUM_PASSWORD_NUMERIC) { 222 out.startTag(null, "min-password-numeric"); 223 out.attribute(null, "value", Integer.toString(minimumPasswordNumeric)); 224 out.endTag(null, "min-password-numeric"); 225 } 226 if (minimumPasswordSymbols != DEF_MINIMUM_PASSWORD_SYMBOLS) { 227 out.startTag(null, "min-password-symbols"); 228 out.attribute(null, "value", Integer.toString(minimumPasswordSymbols)); 229 out.endTag(null, "min-password-symbols"); 230 } 231 if (minimumPasswordNonLetter > DEF_MINIMUM_PASSWORD_NON_LETTER) { 232 out.startTag(null, "min-password-nonletter"); 233 out.attribute(null, "value", Integer.toString(minimumPasswordNonLetter)); 234 out.endTag(null, "min-password-nonletter"); 235 } 236 } 237 if (maximumTimeToUnlock != DEF_MAXIMUM_TIME_TO_UNLOCK) { 238 out.startTag(null, "max-time-to-unlock"); 239 out.attribute(null, "value", Long.toString(maximumTimeToUnlock)); 240 out.endTag(null, "max-time-to-unlock"); 241 } 242 if (maximumFailedPasswordsForWipe != DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE) { 243 out.startTag(null, "max-failed-password-wipe"); 244 out.attribute(null, "value", Integer.toString(maximumFailedPasswordsForWipe)); 245 out.endTag(null, "max-failed-password-wipe"); 246 } 247 if (specifiesGlobalProxy) { 248 out.startTag(null, "specifies-global-proxy"); 249 out.attribute(null, "value", Boolean.toString(specifiesGlobalProxy)); 250 out.endTag(null, "specifies_global_proxy"); 251 if (globalProxySpec != null) { 252 out.startTag(null, "global-proxy-spec"); 253 out.attribute(null, "value", globalProxySpec); 254 out.endTag(null, "global-proxy-spec"); 255 } 256 if (globalProxyExclusionList != null) { 257 out.startTag(null, "global-proxy-exclusion-list"); 258 out.attribute(null, "value", globalProxyExclusionList); 259 out.endTag(null, "global-proxy-exclusion-list"); 260 } 261 } 262 if (passwordExpirationTimeout != DEF_PASSWORD_EXPIRATION_TIMEOUT) { 263 out.startTag(null, "password-expiration-timeout"); 264 out.attribute(null, "value", Long.toString(passwordExpirationTimeout)); 265 out.endTag(null, "password-expiration-timeout"); 266 } 267 if (passwordExpirationDate != DEF_PASSWORD_EXPIRATION_DATE) { 268 out.startTag(null, "password-expiration-date"); 269 out.attribute(null, "value", Long.toString(passwordExpirationDate)); 270 out.endTag(null, "password-expiration-date"); 271 } 272 if (encryptionRequested) { 273 out.startTag(null, "encryption-requested"); 274 out.attribute(null, "value", Boolean.toString(encryptionRequested)); 275 out.endTag(null, "encryption-requested"); 276 } 277 } 278 279 void readFromXml(XmlPullParser parser) 280 throws XmlPullParserException, IOException { 281 int outerDepth = parser.getDepth(); 282 int type; 283 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 284 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 285 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 286 continue; 287 } 288 String tag = parser.getName(); 289 if ("policies".equals(tag)) { 290 info.readPoliciesFromXml(parser); 291 } else if ("password-quality".equals(tag)) { 292 passwordQuality = Integer.parseInt( 293 parser.getAttributeValue(null, "value")); 294 } else if ("min-password-length".equals(tag)) { 295 minimumPasswordLength = Integer.parseInt( 296 parser.getAttributeValue(null, "value")); 297 } else if ("password-history-length".equals(tag)) { 298 passwordHistoryLength = Integer.parseInt( 299 parser.getAttributeValue(null, "value")); 300 } else if ("min-password-uppercase".equals(tag)) { 301 minimumPasswordUpperCase = Integer.parseInt( 302 parser.getAttributeValue(null, "value")); 303 } else if ("min-password-lowercase".equals(tag)) { 304 minimumPasswordLowerCase = Integer.parseInt( 305 parser.getAttributeValue(null, "value")); 306 } else if ("min-password-letters".equals(tag)) { 307 minimumPasswordLetters = Integer.parseInt( 308 parser.getAttributeValue(null, "value")); 309 } else if ("min-password-numeric".equals(tag)) { 310 minimumPasswordNumeric = Integer.parseInt( 311 parser.getAttributeValue(null, "value")); 312 } else if ("min-password-symbols".equals(tag)) { 313 minimumPasswordSymbols = Integer.parseInt( 314 parser.getAttributeValue(null, "value")); 315 } else if ("min-password-nonletter".equals(tag)) { 316 minimumPasswordNonLetter = Integer.parseInt( 317 parser.getAttributeValue(null, "value")); 318 } else if ("max-time-to-unlock".equals(tag)) { 319 maximumTimeToUnlock = Long.parseLong( 320 parser.getAttributeValue(null, "value")); 321 } else if ("max-failed-password-wipe".equals(tag)) { 322 maximumFailedPasswordsForWipe = Integer.parseInt( 323 parser.getAttributeValue(null, "value")); 324 } else if ("specifies-global-proxy".equals(tag)) { 325 specifiesGlobalProxy = Boolean.parseBoolean( 326 parser.getAttributeValue(null, "value")); 327 } else if ("global-proxy-spec".equals(tag)) { 328 globalProxySpec = 329 parser.getAttributeValue(null, "value"); 330 } else if ("global-proxy-exclusion-list".equals(tag)) { 331 globalProxyExclusionList = 332 parser.getAttributeValue(null, "value"); 333 } else if ("password-expiration-timeout".equals(tag)) { 334 passwordExpirationTimeout = Long.parseLong( 335 parser.getAttributeValue(null, "value")); 336 } else if ("password-expiration-date".equals(tag)) { 337 passwordExpirationDate = Long.parseLong( 338 parser.getAttributeValue(null, "value")); 339 } else if ("encryption-requested".equals(tag)) { 340 encryptionRequested = Boolean.parseBoolean( 341 parser.getAttributeValue(null, "value")); 342 } else { 343 Slog.w(TAG, "Unknown admin tag: " + tag); 344 } 345 XmlUtils.skipCurrentTag(parser); 346 } 347 } 348 349 void dump(String prefix, PrintWriter pw) { 350 pw.print(prefix); pw.print("uid="); pw.println(getUid()); 351 pw.print(prefix); pw.println("policies:"); 352 ArrayList<DeviceAdminInfo.PolicyInfo> pols = info.getUsedPolicies(); 353 if (pols != null) { 354 for (int i=0; i<pols.size(); i++) { 355 pw.print(prefix); pw.print(" "); pw.println(pols.get(i).tag); 356 } 357 } 358 pw.print(prefix); pw.print("passwordQuality=0x"); 359 pw.println(Integer.toHexString(passwordQuality)); 360 pw.print(prefix); pw.print("minimumPasswordLength="); 361 pw.println(minimumPasswordLength); 362 pw.print(prefix); pw.print("passwordHistoryLength="); 363 pw.println(passwordHistoryLength); 364 pw.print(prefix); pw.print("minimumPasswordUpperCase="); 365 pw.println(minimumPasswordUpperCase); 366 pw.print(prefix); pw.print("minimumPasswordLowerCase="); 367 pw.println(minimumPasswordLowerCase); 368 pw.print(prefix); pw.print("minimumPasswordLetters="); 369 pw.println(minimumPasswordLetters); 370 pw.print(prefix); pw.print("minimumPasswordNumeric="); 371 pw.println(minimumPasswordNumeric); 372 pw.print(prefix); pw.print("minimumPasswordSymbols="); 373 pw.println(minimumPasswordSymbols); 374 pw.print(prefix); pw.print("minimumPasswordNonLetter="); 375 pw.println(minimumPasswordNonLetter); 376 pw.print(prefix); pw.print("maximumTimeToUnlock="); 377 pw.println(maximumTimeToUnlock); 378 pw.print(prefix); pw.print("maximumFailedPasswordsForWipe="); 379 pw.println(maximumFailedPasswordsForWipe); 380 pw.print(prefix); pw.print("specifiesGlobalProxy="); 381 pw.println(specifiesGlobalProxy); 382 pw.print(prefix); pw.print("passwordExpirationTimeout="); 383 pw.println(passwordExpirationTimeout); 384 pw.print(prefix); pw.print("passwordExpirationDate="); 385 pw.println(passwordExpirationDate); 386 if (globalProxySpec != null) { 387 pw.print(prefix); pw.print("globalProxySpec="); 388 pw.println(globalProxySpec); 389 } 390 if (globalProxyExclusionList != null) { 391 pw.print(prefix); pw.print("globalProxyEclusionList="); 392 pw.println(globalProxyExclusionList); 393 } 394 pw.print(prefix); pw.print("encryptionRequested="); 395 pw.println(encryptionRequested); 396 } 397 } 398 399 class MyPackageMonitor extends PackageMonitor { 400 @Override 401 public void onSomePackagesChanged() { 402 synchronized (DevicePolicyManagerService.this) { 403 boolean removed = false; 404 for (int i=mAdminList.size()-1; i>=0; i--) { 405 ActiveAdmin aa = mAdminList.get(i); 406 int change = isPackageDisappearing(aa.info.getPackageName()); 407 if (change == PACKAGE_PERMANENT_CHANGE 408 || change == PACKAGE_TEMPORARY_CHANGE) { 409 Slog.w(TAG, "Admin unexpectedly uninstalled: " 410 + aa.info.getComponent()); 411 removed = true; 412 mAdminList.remove(i); 413 } else if (isPackageModified(aa.info.getPackageName())) { 414 try { 415 mContext.getPackageManager().getReceiverInfo( 416 aa.info.getComponent(), 0); 417 } catch (NameNotFoundException e) { 418 Slog.w(TAG, "Admin package change removed component: " 419 + aa.info.getComponent()); 420 removed = true; 421 mAdminList.remove(i); 422 } 423 } 424 } 425 if (removed) { 426 validatePasswordOwnerLocked(); 427 saveSettingsLocked(); 428 } 429 } 430 } 431 } 432 433 /** 434 * Instantiates the service. 435 */ 436 public DevicePolicyManagerService(Context context) { 437 mContext = context; 438 mMonitor = new MyPackageMonitor(); 439 mMonitor.register(context, true); 440 mWakeLock = ((PowerManager)context.getSystemService(Context.POWER_SERVICE)) 441 .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DPM"); 442 IntentFilter filter = new IntentFilter(); 443 filter.addAction(Intent.ACTION_BOOT_COMPLETED); 444 filter.addAction(ACTION_EXPIRED_PASSWORD_NOTIFICATION); 445 context.registerReceiver(mReceiver, filter); 446 } 447 448 /** 449 * Set an alarm for an upcoming event - expiration warning, expiration, or post-expiration 450 * reminders. Clears alarm if no expirations are configured. 451 */ 452 protected void setExpirationAlarmCheckLocked(Context context) { 453 final long expiration = getPasswordExpirationLocked(null); 454 final long now = System.currentTimeMillis(); 455 final long timeToExpire = expiration - now; 456 final long alarmTime; 457 if (expiration == 0) { 458 // No expirations are currently configured: Cancel alarm. 459 alarmTime = 0; 460 } else if (timeToExpire <= 0) { 461 // The password has already expired: Repeat every 24 hours. 462 alarmTime = now + MS_PER_DAY; 463 } else { 464 // Selecting the next alarm time: Roll forward to the next 24 hour multiple before 465 // the expiration time. 466 long alarmInterval = timeToExpire % MS_PER_DAY; 467 if (alarmInterval == 0) { 468 alarmInterval = MS_PER_DAY; 469 } 470 alarmTime = now + alarmInterval; 471 } 472 473 long token = Binder.clearCallingIdentity(); 474 try { 475 AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 476 PendingIntent pi = PendingIntent.getBroadcast(context, REQUEST_EXPIRE_PASSWORD, 477 new Intent(ACTION_EXPIRED_PASSWORD_NOTIFICATION), 478 PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT); 479 am.cancel(pi); 480 if (alarmTime != 0) { 481 am.set(AlarmManager.RTC, alarmTime, pi); 482 } 483 } finally { 484 Binder.restoreCallingIdentity(token); 485 } 486 } 487 488 private IPowerManager getIPowerManager() { 489 if (mIPowerManager == null) { 490 IBinder b = ServiceManager.getService(Context.POWER_SERVICE); 491 mIPowerManager = IPowerManager.Stub.asInterface(b); 492 } 493 return mIPowerManager; 494 } 495 496 ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who) { 497 ActiveAdmin admin = mAdminMap.get(who); 498 if (admin != null 499 && who.getPackageName().equals(admin.info.getActivityInfo().packageName) 500 && who.getClassName().equals(admin.info.getActivityInfo().name)) { 501 return admin; 502 } 503 return null; 504 } 505 506 ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy) 507 throws SecurityException { 508 final int callingUid = Binder.getCallingUid(); 509 if (who != null) { 510 ActiveAdmin admin = mAdminMap.get(who); 511 if (admin == null) { 512 throw new SecurityException("No active admin " + who); 513 } 514 if (admin.getUid() != callingUid) { 515 throw new SecurityException("Admin " + who + " is not owned by uid " 516 + Binder.getCallingUid()); 517 } 518 if (!admin.info.usesPolicy(reqPolicy)) { 519 throw new SecurityException("Admin " + admin.info.getComponent() 520 + " did not specify uses-policy for: " 521 + admin.info.getTagForPolicy(reqPolicy)); 522 } 523 return admin; 524 } else { 525 final int N = mAdminList.size(); 526 for (int i=0; i<N; i++) { 527 ActiveAdmin admin = mAdminList.get(i); 528 if (admin.getUid() == callingUid && admin.info.usesPolicy(reqPolicy)) { 529 return admin; 530 } 531 } 532 throw new SecurityException("No active admin owned by uid " 533 + Binder.getCallingUid() + " for policy #" + reqPolicy); 534 } 535 } 536 537 void sendAdminCommandLocked(ActiveAdmin admin, String action) { 538 sendAdminCommandLocked(admin, action, null); 539 } 540 541 void sendAdminCommandLocked(ActiveAdmin admin, String action, BroadcastReceiver result) { 542 Intent intent = new Intent(action); 543 intent.setComponent(admin.info.getComponent()); 544 if (action.equals(DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING)) { 545 intent.putExtra("expiration", admin.passwordExpirationDate); 546 } 547 if (result != null) { 548 mContext.sendOrderedBroadcast(intent, null, result, mHandler, 549 Activity.RESULT_OK, null, null); 550 } else { 551 mContext.sendBroadcast(intent); 552 } 553 } 554 555 void sendAdminCommandLocked(String action, int reqPolicy) { 556 final int N = mAdminList.size(); 557 if (N > 0) { 558 for (int i=0; i<N; i++) { 559 ActiveAdmin admin = mAdminList.get(i); 560 if (admin.info.usesPolicy(reqPolicy)) { 561 sendAdminCommandLocked(admin, action); 562 } 563 } 564 } 565 } 566 567 void removeActiveAdminLocked(final ComponentName adminReceiver) { 568 final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver); 569 if (admin != null) { 570 sendAdminCommandLocked(admin, 571 DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED, 572 new BroadcastReceiver() { 573 @Override 574 public void onReceive(Context context, Intent intent) { 575 synchronized (this) { 576 boolean doProxyCleanup = admin.info.usesPolicy( 577 DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY); 578 mAdminList.remove(admin); 579 mAdminMap.remove(adminReceiver); 580 validatePasswordOwnerLocked(); 581 if (doProxyCleanup) { 582 resetGlobalProxy(); 583 } 584 saveSettingsLocked(); 585 } 586 } 587 }); 588 } 589 } 590 591 public DeviceAdminInfo findAdmin(ComponentName adminName) { 592 Intent resolveIntent = new Intent(); 593 resolveIntent.setComponent(adminName); 594 List<ResolveInfo> infos = mContext.getPackageManager().queryBroadcastReceivers( 595 resolveIntent, PackageManager.GET_META_DATA); 596 if (infos == null || infos.size() <= 0) { 597 throw new IllegalArgumentException("Unknown admin: " + adminName); 598 } 599 600 try { 601 return new DeviceAdminInfo(mContext, infos.get(0)); 602 } catch (XmlPullParserException e) { 603 Slog.w(TAG, "Bad device admin requested: " + adminName, e); 604 return null; 605 } catch (IOException e) { 606 Slog.w(TAG, "Bad device admin requested: " + adminName, e); 607 return null; 608 } 609 } 610 611 private static JournaledFile makeJournaledFile() { 612 final String base = "/data/system/device_policies.xml"; 613 return new JournaledFile(new File(base), new File(base + ".tmp")); 614 } 615 616 private void saveSettingsLocked() { 617 JournaledFile journal = makeJournaledFile(); 618 FileOutputStream stream = null; 619 try { 620 stream = new FileOutputStream(journal.chooseForWrite(), false); 621 XmlSerializer out = new FastXmlSerializer(); 622 out.setOutput(stream, "utf-8"); 623 out.startDocument(null, true); 624 625 out.startTag(null, "policies"); 626 627 final int N = mAdminList.size(); 628 for (int i=0; i<N; i++) { 629 ActiveAdmin ap = mAdminList.get(i); 630 if (ap != null) { 631 out.startTag(null, "admin"); 632 out.attribute(null, "name", ap.info.getComponent().flattenToString()); 633 ap.writeToXml(out); 634 out.endTag(null, "admin"); 635 } 636 } 637 638 if (mPasswordOwner >= 0) { 639 out.startTag(null, "password-owner"); 640 out.attribute(null, "value", Integer.toString(mPasswordOwner)); 641 out.endTag(null, "password-owner"); 642 } 643 644 if (mFailedPasswordAttempts != 0) { 645 out.startTag(null, "failed-password-attempts"); 646 out.attribute(null, "value", Integer.toString(mFailedPasswordAttempts)); 647 out.endTag(null, "failed-password-attempts"); 648 } 649 650 if (mActivePasswordQuality != 0 || mActivePasswordLength != 0 651 || mActivePasswordUpperCase != 0 || mActivePasswordLowerCase != 0 652 || mActivePasswordLetters != 0 || mActivePasswordNumeric != 0 653 || mActivePasswordSymbols != 0 || mActivePasswordNonLetter != 0) { 654 out.startTag(null, "active-password"); 655 out.attribute(null, "quality", Integer.toString(mActivePasswordQuality)); 656 out.attribute(null, "length", Integer.toString(mActivePasswordLength)); 657 out.attribute(null, "uppercase", Integer.toString(mActivePasswordUpperCase)); 658 out.attribute(null, "lowercase", Integer.toString(mActivePasswordLowerCase)); 659 out.attribute(null, "letters", Integer.toString(mActivePasswordLetters)); 660 out.attribute(null, "numeric", Integer 661 .toString(mActivePasswordNumeric)); 662 out.attribute(null, "symbols", Integer.toString(mActivePasswordSymbols)); 663 out.attribute(null, "nonletter", Integer.toString(mActivePasswordNonLetter)); 664 out.endTag(null, "active-password"); 665 } 666 667 out.endTag(null, "policies"); 668 669 out.endDocument(); 670 stream.close(); 671 journal.commit(); 672 sendChangedNotification(); 673 } catch (IOException e) { 674 try { 675 if (stream != null) { 676 stream.close(); 677 } 678 } catch (IOException ex) { 679 // Ignore 680 } 681 journal.rollback(); 682 } 683 } 684 685 private void sendChangedNotification() { 686 Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 687 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 688 mContext.sendBroadcast(intent); 689 } 690 691 private void loadSettingsLocked() { 692 JournaledFile journal = makeJournaledFile(); 693 FileInputStream stream = null; 694 File file = journal.chooseForRead(); 695 try { 696 stream = new FileInputStream(file); 697 XmlPullParser parser = Xml.newPullParser(); 698 parser.setInput(stream, null); 699 700 int type; 701 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 702 && type != XmlPullParser.START_TAG) { 703 } 704 String tag = parser.getName(); 705 if (!"policies".equals(tag)) { 706 throw new XmlPullParserException( 707 "Settings do not start with policies tag: found " + tag); 708 } 709 type = parser.next(); 710 int outerDepth = parser.getDepth(); 711 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 712 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 713 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 714 continue; 715 } 716 tag = parser.getName(); 717 if ("admin".equals(tag)) { 718 String name = parser.getAttributeValue(null, "name"); 719 try { 720 DeviceAdminInfo dai = findAdmin( 721 ComponentName.unflattenFromString(name)); 722 if (dai != null) { 723 ActiveAdmin ap = new ActiveAdmin(dai); 724 ap.readFromXml(parser); 725 mAdminMap.put(ap.info.getComponent(), ap); 726 mAdminList.add(ap); 727 } 728 } catch (RuntimeException e) { 729 Slog.w(TAG, "Failed loading admin " + name, e); 730 } 731 } else if ("failed-password-attempts".equals(tag)) { 732 mFailedPasswordAttempts = Integer.parseInt( 733 parser.getAttributeValue(null, "value")); 734 XmlUtils.skipCurrentTag(parser); 735 } else if ("password-owner".equals(tag)) { 736 mPasswordOwner = Integer.parseInt( 737 parser.getAttributeValue(null, "value")); 738 XmlUtils.skipCurrentTag(parser); 739 } else if ("active-password".equals(tag)) { 740 mActivePasswordQuality = Integer.parseInt( 741 parser.getAttributeValue(null, "quality")); 742 mActivePasswordLength = Integer.parseInt( 743 parser.getAttributeValue(null, "length")); 744 mActivePasswordUpperCase = Integer.parseInt( 745 parser.getAttributeValue(null, "uppercase")); 746 mActivePasswordLowerCase = Integer.parseInt( 747 parser.getAttributeValue(null, "lowercase")); 748 mActivePasswordLetters = Integer.parseInt( 749 parser.getAttributeValue(null, "letters")); 750 mActivePasswordNumeric = Integer.parseInt( 751 parser.getAttributeValue(null, "numeric")); 752 mActivePasswordSymbols = Integer.parseInt( 753 parser.getAttributeValue(null, "symbols")); 754 mActivePasswordNonLetter = Integer.parseInt( 755 parser.getAttributeValue(null, "nonletter")); 756 XmlUtils.skipCurrentTag(parser); 757 } else { 758 Slog.w(TAG, "Unknown tag: " + tag); 759 XmlUtils.skipCurrentTag(parser); 760 } 761 } 762 } catch (NullPointerException e) { 763 Slog.w(TAG, "failed parsing " + file + " " + e); 764 } catch (NumberFormatException e) { 765 Slog.w(TAG, "failed parsing " + file + " " + e); 766 } catch (XmlPullParserException e) { 767 Slog.w(TAG, "failed parsing " + file + " " + e); 768 } catch (FileNotFoundException e) { 769 // Don't be noisy, this is normal if we haven't defined any policies. 770 } catch (IOException e) { 771 Slog.w(TAG, "failed parsing " + file + " " + e); 772 } catch (IndexOutOfBoundsException e) { 773 Slog.w(TAG, "failed parsing " + file + " " + e); 774 } 775 try { 776 if (stream != null) { 777 stream.close(); 778 } 779 } catch (IOException e) { 780 // Ignore 781 } 782 783 // Validate that what we stored for the password quality matches 784 // sufficiently what is currently set. Note that this is only 785 // a sanity check in case the two get out of sync; this should 786 // never normally happen. 787 LockPatternUtils utils = new LockPatternUtils(mContext); 788 if (utils.getActivePasswordQuality() < mActivePasswordQuality) { 789 Slog.w(TAG, "Active password quality 0x" 790 + Integer.toHexString(mActivePasswordQuality) 791 + " does not match actual quality 0x" 792 + Integer.toHexString(utils.getActivePasswordQuality())); 793 mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 794 mActivePasswordLength = 0; 795 mActivePasswordUpperCase = 0; 796 mActivePasswordLowerCase = 0; 797 mActivePasswordLetters = 0; 798 mActivePasswordNumeric = 0; 799 mActivePasswordSymbols = 0; 800 mActivePasswordNonLetter = 0; 801 } 802 803 validatePasswordOwnerLocked(); 804 805 long timeMs = getMaximumTimeToLock(null); 806 if (timeMs <= 0) { 807 timeMs = Integer.MAX_VALUE; 808 } 809 try { 810 getIPowerManager().setMaximumScreenOffTimeount((int)timeMs); 811 } catch (RemoteException e) { 812 Slog.w(TAG, "Failure talking with power manager", e); 813 } 814 } 815 816 static void validateQualityConstant(int quality) { 817 switch (quality) { 818 case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED: 819 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: 820 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: 821 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: 822 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: 823 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: 824 return; 825 } 826 throw new IllegalArgumentException("Invalid quality constant: 0x" 827 + Integer.toHexString(quality)); 828 } 829 830 void validatePasswordOwnerLocked() { 831 if (mPasswordOwner >= 0) { 832 boolean haveOwner = false; 833 for (int i=mAdminList.size()-1; i>=0; i--) { 834 if (mAdminList.get(i).getUid() == mPasswordOwner) { 835 haveOwner = true; 836 break; 837 } 838 } 839 if (!haveOwner) { 840 Slog.w(TAG, "Previous password owner " + mPasswordOwner 841 + " no longer active; disabling"); 842 mPasswordOwner = -1; 843 } 844 } 845 } 846 847 public void systemReady() { 848 synchronized (this) { 849 loadSettingsLocked(); 850 } 851 } 852 853 private void handlePasswordExpirationNotification() { 854 synchronized (this) { 855 final long now = System.currentTimeMillis(); 856 final int N = mAdminList.size(); 857 if (N <= 0) { 858 return; 859 } 860 for (int i=0; i < N; i++) { 861 ActiveAdmin admin = mAdminList.get(i); 862 if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD) 863 && admin.passwordExpirationTimeout > 0L 864 && admin.passwordExpirationDate > 0L 865 && now >= admin.passwordExpirationDate - EXPIRATION_GRACE_PERIOD_MS) { 866 sendAdminCommandLocked(admin, DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING); 867 } 868 } 869 setExpirationAlarmCheckLocked(mContext); 870 } 871 } 872 873 /** 874 * @param adminReceiver The admin to add 875 * @param refreshing true = update an active admin, no error 876 */ 877 public void setActiveAdmin(ComponentName adminReceiver, boolean refreshing) { 878 mContext.enforceCallingOrSelfPermission( 879 android.Manifest.permission.BIND_DEVICE_ADMIN, null); 880 881 DeviceAdminInfo info = findAdmin(adminReceiver); 882 if (info == null) { 883 throw new IllegalArgumentException("Bad admin: " + adminReceiver); 884 } 885 synchronized (this) { 886 long ident = Binder.clearCallingIdentity(); 887 try { 888 if (!refreshing && getActiveAdminUncheckedLocked(adminReceiver) != null) { 889 throw new IllegalArgumentException("Admin is already added"); 890 } 891 ActiveAdmin newAdmin = new ActiveAdmin(info); 892 mAdminMap.put(adminReceiver, newAdmin); 893 int replaceIndex = -1; 894 if (refreshing) { 895 final int N = mAdminList.size(); 896 for (int i=0; i < N; i++) { 897 ActiveAdmin oldAdmin = mAdminList.get(i); 898 if (oldAdmin.info.getComponent().equals(adminReceiver)) { 899 replaceIndex = i; 900 break; 901 } 902 } 903 } 904 if (replaceIndex == -1) { 905 mAdminList.add(newAdmin); 906 } else { 907 mAdminList.set(replaceIndex, newAdmin); 908 } 909 saveSettingsLocked(); 910 sendAdminCommandLocked(newAdmin, DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED); 911 } finally { 912 Binder.restoreCallingIdentity(ident); 913 } 914 } 915 } 916 917 public boolean isAdminActive(ComponentName adminReceiver) { 918 synchronized (this) { 919 return getActiveAdminUncheckedLocked(adminReceiver) != null; 920 } 921 } 922 923 public boolean hasGrantedPolicy(ComponentName adminReceiver, int policyId) { 924 synchronized (this) { 925 ActiveAdmin administrator = getActiveAdminUncheckedLocked(adminReceiver); 926 if (administrator == null) { 927 throw new SecurityException("No active admin " + adminReceiver); 928 } 929 return administrator.info.usesPolicy(policyId); 930 } 931 } 932 933 public List<ComponentName> getActiveAdmins() { 934 synchronized (this) { 935 final int N = mAdminList.size(); 936 if (N <= 0) { 937 return null; 938 } 939 ArrayList<ComponentName> res = new ArrayList<ComponentName>(N); 940 for (int i=0; i<N; i++) { 941 res.add(mAdminList.get(i).info.getComponent()); 942 } 943 return res; 944 } 945 } 946 947 public boolean packageHasActiveAdmins(String packageName) { 948 synchronized (this) { 949 final int N = mAdminList.size(); 950 for (int i=0; i<N; i++) { 951 if (mAdminList.get(i).info.getPackageName().equals(packageName)) { 952 return true; 953 } 954 } 955 return false; 956 } 957 } 958 959 public void removeActiveAdmin(ComponentName adminReceiver) { 960 synchronized (this) { 961 ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver); 962 if (admin == null) { 963 return; 964 } 965 if (admin.getUid() != Binder.getCallingUid()) { 966 mContext.enforceCallingOrSelfPermission( 967 android.Manifest.permission.BIND_DEVICE_ADMIN, null); 968 } 969 long ident = Binder.clearCallingIdentity(); 970 try { 971 removeActiveAdminLocked(adminReceiver); 972 } finally { 973 Binder.restoreCallingIdentity(ident); 974 } 975 } 976 } 977 978 public void setPasswordQuality(ComponentName who, int quality) { 979 validateQualityConstant(quality); 980 981 synchronized (this) { 982 if (who == null) { 983 throw new NullPointerException("ComponentName is null"); 984 } 985 ActiveAdmin ap = getActiveAdminForCallerLocked(who, 986 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); 987 if (ap.passwordQuality != quality) { 988 ap.passwordQuality = quality; 989 saveSettingsLocked(); 990 } 991 } 992 } 993 994 public int getPasswordQuality(ComponentName who) { 995 synchronized (this) { 996 int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 997 998 if (who != null) { 999 ActiveAdmin admin = getActiveAdminUncheckedLocked(who); 1000 return admin != null ? admin.passwordQuality : mode; 1001 } 1002 1003 final int N = mAdminList.size(); 1004 for (int i=0; i<N; i++) { 1005 ActiveAdmin admin = mAdminList.get(i); 1006 if (mode < admin.passwordQuality) { 1007 mode = admin.passwordQuality; 1008 } 1009 } 1010 return mode; 1011 } 1012 } 1013 1014 public void setPasswordMinimumLength(ComponentName who, int length) { 1015 synchronized (this) { 1016 if (who == null) { 1017 throw new NullPointerException("ComponentName is null"); 1018 } 1019 ActiveAdmin ap = getActiveAdminForCallerLocked(who, 1020 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); 1021 if (ap.minimumPasswordLength != length) { 1022 ap.minimumPasswordLength = length; 1023 saveSettingsLocked(); 1024 } 1025 } 1026 } 1027 1028 public int getPasswordMinimumLength(ComponentName who) { 1029 synchronized (this) { 1030 int length = 0; 1031 1032 if (who != null) { 1033 ActiveAdmin admin = getActiveAdminUncheckedLocked(who); 1034 return admin != null ? admin.minimumPasswordLength : length; 1035 } 1036 1037 final int N = mAdminList.size(); 1038 for (int i=0; i<N; i++) { 1039 ActiveAdmin admin = mAdminList.get(i); 1040 if (length < admin.minimumPasswordLength) { 1041 length = admin.minimumPasswordLength; 1042 } 1043 } 1044 return length; 1045 } 1046 } 1047 1048 public void setPasswordHistoryLength(ComponentName who, int length) { 1049 synchronized (this) { 1050 if (who == null) { 1051 throw new NullPointerException("ComponentName is null"); 1052 } 1053 ActiveAdmin ap = getActiveAdminForCallerLocked(who, 1054 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); 1055 if (ap.passwordHistoryLength != length) { 1056 ap.passwordHistoryLength = length; 1057 saveSettingsLocked(); 1058 } 1059 } 1060 } 1061 1062 public int getPasswordHistoryLength(ComponentName who) { 1063 synchronized (this) { 1064 int length = 0; 1065 1066 if (who != null) { 1067 ActiveAdmin admin = getActiveAdminUncheckedLocked(who); 1068 return admin != null ? admin.passwordHistoryLength : length; 1069 } 1070 1071 final int N = mAdminList.size(); 1072 for (int i = 0; i < N; i++) { 1073 ActiveAdmin admin = mAdminList.get(i); 1074 if (length < admin.passwordHistoryLength) { 1075 length = admin.passwordHistoryLength; 1076 } 1077 } 1078 return length; 1079 } 1080 } 1081 1082 public void setPasswordExpirationTimeout(ComponentName who, long timeout) { 1083 synchronized (this) { 1084 if (who == null) { 1085 throw new NullPointerException("ComponentName is null"); 1086 } 1087 if (timeout < 0) { 1088 throw new IllegalArgumentException("Timeout must be >= 0 ms"); 1089 } 1090 ActiveAdmin ap = getActiveAdminForCallerLocked(who, 1091 DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD); 1092 // Calling this API automatically bumps the expiration date 1093 final long expiration = timeout > 0L ? (timeout + System.currentTimeMillis()) : 0L; 1094 ap.passwordExpirationDate = expiration; 1095 ap.passwordExpirationTimeout = timeout; 1096 if (timeout > 0L) { 1097 Slog.w(TAG, "setPasswordExpiration(): password will expire on " 1098 + DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT) 1099 .format(new Date(expiration))); 1100 } 1101 saveSettingsLocked(); 1102 setExpirationAlarmCheckLocked(mContext); // in case this is the first one 1103 } 1104 } 1105 1106 /** 1107 * Return a single admin's expiration cycle time, or the min of all cycle times. 1108 * Returns 0 if not configured. 1109 */ 1110 public long getPasswordExpirationTimeout(ComponentName who) { 1111 synchronized (this) { 1112 if (who != null) { 1113 ActiveAdmin admin = getActiveAdminUncheckedLocked(who); 1114 return admin != null ? admin.passwordExpirationTimeout : 0L; 1115 } 1116 1117 long timeout = 0L; 1118 final int N = mAdminList.size(); 1119 for (int i = 0; i < N; i++) { 1120 ActiveAdmin admin = mAdminList.get(i); 1121 if (timeout == 0L || (admin.passwordExpirationTimeout != 0L 1122 && timeout > admin.passwordExpirationTimeout)) { 1123 timeout = admin.passwordExpirationTimeout; 1124 } 1125 } 1126 return timeout; 1127 } 1128 } 1129 1130 /** 1131 * Return a single admin's expiration date/time, or the min (soonest) for all admins. 1132 * Returns 0 if not configured. 1133 */ 1134 private long getPasswordExpirationLocked(ComponentName who) { 1135 if (who != null) { 1136 ActiveAdmin admin = getActiveAdminUncheckedLocked(who); 1137 return admin != null ? admin.passwordExpirationDate : 0L; 1138 } 1139 1140 long timeout = 0L; 1141 final int N = mAdminList.size(); 1142 for (int i = 0; i < N; i++) { 1143 ActiveAdmin admin = mAdminList.get(i); 1144 if (timeout == 0L || (admin.passwordExpirationDate != 0 1145 && timeout > admin.passwordExpirationDate)) { 1146 timeout = admin.passwordExpirationDate; 1147 } 1148 } 1149 return timeout; 1150 } 1151 1152 public long getPasswordExpiration(ComponentName who) { 1153 synchronized (this) { 1154 return getPasswordExpirationLocked(who); 1155 } 1156 } 1157 1158 public void setPasswordMinimumUpperCase(ComponentName who, int length) { 1159 synchronized (this) { 1160 if (who == null) { 1161 throw new NullPointerException("ComponentName is null"); 1162 } 1163 ActiveAdmin ap = getActiveAdminForCallerLocked(who, 1164 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); 1165 if (ap.minimumPasswordUpperCase != length) { 1166 ap.minimumPasswordUpperCase = length; 1167 saveSettingsLocked(); 1168 } 1169 } 1170 } 1171 1172 public int getPasswordMinimumUpperCase(ComponentName who) { 1173 synchronized (this) { 1174 int length = 0; 1175 1176 if (who != null) { 1177 ActiveAdmin admin = getActiveAdminUncheckedLocked(who); 1178 return admin != null ? admin.minimumPasswordUpperCase : length; 1179 } 1180 1181 final int N = mAdminList.size(); 1182 for (int i=0; i<N; i++) { 1183 ActiveAdmin admin = mAdminList.get(i); 1184 if (length < admin.minimumPasswordUpperCase) { 1185 length = admin.minimumPasswordUpperCase; 1186 } 1187 } 1188 return length; 1189 } 1190 } 1191 1192 public void setPasswordMinimumLowerCase(ComponentName who, int length) { 1193 synchronized (this) { 1194 if (who == null) { 1195 throw new NullPointerException("ComponentName is null"); 1196 } 1197 ActiveAdmin ap = getActiveAdminForCallerLocked(who, 1198 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); 1199 if (ap.minimumPasswordLowerCase != length) { 1200 ap.minimumPasswordLowerCase = length; 1201 saveSettingsLocked(); 1202 } 1203 } 1204 } 1205 1206 public int getPasswordMinimumLowerCase(ComponentName who) { 1207 synchronized (this) { 1208 int length = 0; 1209 1210 if (who != null) { 1211 ActiveAdmin admin = getActiveAdminUncheckedLocked(who); 1212 return admin != null ? admin.minimumPasswordLowerCase : length; 1213 } 1214 1215 final int N = mAdminList.size(); 1216 for (int i=0; i<N; i++) { 1217 ActiveAdmin admin = mAdminList.get(i); 1218 if (length < admin.minimumPasswordLowerCase) { 1219 length = admin.minimumPasswordLowerCase; 1220 } 1221 } 1222 return length; 1223 } 1224 } 1225 1226 public void setPasswordMinimumLetters(ComponentName who, int length) { 1227 synchronized (this) { 1228 if (who == null) { 1229 throw new NullPointerException("ComponentName is null"); 1230 } 1231 ActiveAdmin ap = getActiveAdminForCallerLocked(who, 1232 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); 1233 if (ap.minimumPasswordLetters != length) { 1234 ap.minimumPasswordLetters = length; 1235 saveSettingsLocked(); 1236 } 1237 } 1238 } 1239 1240 public int getPasswordMinimumLetters(ComponentName who) { 1241 synchronized (this) { 1242 int length = 0; 1243 1244 if (who != null) { 1245 ActiveAdmin admin = getActiveAdminUncheckedLocked(who); 1246 return admin != null ? admin.minimumPasswordLetters : length; 1247 } 1248 1249 final int N = mAdminList.size(); 1250 for (int i=0; i<N; i++) { 1251 ActiveAdmin admin = mAdminList.get(i); 1252 if (length < admin.minimumPasswordLetters) { 1253 length = admin.minimumPasswordLetters; 1254 } 1255 } 1256 return length; 1257 } 1258 } 1259 1260 public void setPasswordMinimumNumeric(ComponentName who, int length) { 1261 synchronized (this) { 1262 if (who == null) { 1263 throw new NullPointerException("ComponentName is null"); 1264 } 1265 ActiveAdmin ap = getActiveAdminForCallerLocked(who, 1266 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); 1267 if (ap.minimumPasswordNumeric != length) { 1268 ap.minimumPasswordNumeric = length; 1269 saveSettingsLocked(); 1270 } 1271 } 1272 } 1273 1274 public int getPasswordMinimumNumeric(ComponentName who) { 1275 synchronized (this) { 1276 int length = 0; 1277 1278 if (who != null) { 1279 ActiveAdmin admin = getActiveAdminUncheckedLocked(who); 1280 return admin != null ? admin.minimumPasswordNumeric : length; 1281 } 1282 1283 final int N = mAdminList.size(); 1284 for (int i = 0; i < N; i++) { 1285 ActiveAdmin admin = mAdminList.get(i); 1286 if (length < admin.minimumPasswordNumeric) { 1287 length = admin.minimumPasswordNumeric; 1288 } 1289 } 1290 return length; 1291 } 1292 } 1293 1294 public void setPasswordMinimumSymbols(ComponentName who, int length) { 1295 synchronized (this) { 1296 if (who == null) { 1297 throw new NullPointerException("ComponentName is null"); 1298 } 1299 ActiveAdmin ap = getActiveAdminForCallerLocked(who, 1300 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); 1301 if (ap.minimumPasswordSymbols != length) { 1302 ap.minimumPasswordSymbols = length; 1303 saveSettingsLocked(); 1304 } 1305 } 1306 } 1307 1308 public int getPasswordMinimumSymbols(ComponentName who) { 1309 synchronized (this) { 1310 int length = 0; 1311 1312 if (who != null) { 1313 ActiveAdmin admin = getActiveAdminUncheckedLocked(who); 1314 return admin != null ? admin.minimumPasswordSymbols : length; 1315 } 1316 1317 final int N = mAdminList.size(); 1318 for (int i=0; i<N; i++) { 1319 ActiveAdmin admin = mAdminList.get(i); 1320 if (length < admin.minimumPasswordSymbols) { 1321 length = admin.minimumPasswordSymbols; 1322 } 1323 } 1324 return length; 1325 } 1326 } 1327 1328 public void setPasswordMinimumNonLetter(ComponentName who, int length) { 1329 synchronized (this) { 1330 if (who == null) { 1331 throw new NullPointerException("ComponentName is null"); 1332 } 1333 ActiveAdmin ap = getActiveAdminForCallerLocked(who, 1334 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); 1335 if (ap.minimumPasswordNonLetter != length) { 1336 ap.minimumPasswordNonLetter = length; 1337 saveSettingsLocked(); 1338 } 1339 } 1340 } 1341 1342 public int getPasswordMinimumNonLetter(ComponentName who) { 1343 synchronized (this) { 1344 int length = 0; 1345 1346 if (who != null) { 1347 ActiveAdmin admin = getActiveAdminUncheckedLocked(who); 1348 return admin != null ? admin.minimumPasswordNonLetter : length; 1349 } 1350 1351 final int N = mAdminList.size(); 1352 for (int i=0; i<N; i++) { 1353 ActiveAdmin admin = mAdminList.get(i); 1354 if (length < admin.minimumPasswordNonLetter) { 1355 length = admin.minimumPasswordNonLetter; 1356 } 1357 } 1358 return length; 1359 } 1360 } 1361 1362 public boolean isActivePasswordSufficient() { 1363 synchronized (this) { 1364 // This API can only be called by an active device admin, 1365 // so try to retrieve it to check that the caller is one. 1366 getActiveAdminForCallerLocked(null, 1367 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); 1368 if (mActivePasswordQuality < getPasswordQuality(null) 1369 || mActivePasswordLength < getPasswordMinimumLength(null)) { 1370 return false; 1371 } 1372 if(mActivePasswordQuality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) { 1373 return true; 1374 } 1375 return mActivePasswordUpperCase >= getPasswordMinimumUpperCase(null) 1376 && mActivePasswordLowerCase >= getPasswordMinimumLowerCase(null) 1377 && mActivePasswordLetters >= getPasswordMinimumLetters(null) 1378 && mActivePasswordNumeric >= getPasswordMinimumNumeric(null) 1379 && mActivePasswordSymbols >= getPasswordMinimumSymbols(null) 1380 && mActivePasswordNonLetter >= getPasswordMinimumNonLetter(null); 1381 } 1382 } 1383 1384 public int getCurrentFailedPasswordAttempts() { 1385 synchronized (this) { 1386 // This API can only be called by an active device admin, 1387 // so try to retrieve it to check that the caller is one. 1388 getActiveAdminForCallerLocked(null, 1389 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN); 1390 return mFailedPasswordAttempts; 1391 } 1392 } 1393 1394 public void setMaximumFailedPasswordsForWipe(ComponentName who, int num) { 1395 synchronized (this) { 1396 // This API can only be called by an active device admin, 1397 // so try to retrieve it to check that the caller is one. 1398 getActiveAdminForCallerLocked(who, 1399 DeviceAdminInfo.USES_POLICY_WIPE_DATA); 1400 ActiveAdmin ap = getActiveAdminForCallerLocked(who, 1401 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN); 1402 if (ap.maximumFailedPasswordsForWipe != num) { 1403 ap.maximumFailedPasswordsForWipe = num; 1404 saveSettingsLocked(); 1405 } 1406 } 1407 } 1408 1409 public int getMaximumFailedPasswordsForWipe(ComponentName who) { 1410 synchronized (this) { 1411 int count = 0; 1412 1413 if (who != null) { 1414 ActiveAdmin admin = getActiveAdminUncheckedLocked(who); 1415 return admin != null ? admin.maximumFailedPasswordsForWipe : count; 1416 } 1417 1418 final int N = mAdminList.size(); 1419 for (int i=0; i<N; i++) { 1420 ActiveAdmin admin = mAdminList.get(i); 1421 if (count == 0) { 1422 count = admin.maximumFailedPasswordsForWipe; 1423 } else if (admin.maximumFailedPasswordsForWipe != 0 1424 && count > admin.maximumFailedPasswordsForWipe) { 1425 count = admin.maximumFailedPasswordsForWipe; 1426 } 1427 } 1428 return count; 1429 } 1430 } 1431 1432 public boolean resetPassword(String password, int flags) { 1433 int quality; 1434 synchronized (this) { 1435 // This API can only be called by an active device admin, 1436 // so try to retrieve it to check that the caller is one. 1437 getActiveAdminForCallerLocked(null, 1438 DeviceAdminInfo.USES_POLICY_RESET_PASSWORD); 1439 quality = getPasswordQuality(null); 1440 if (quality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { 1441 int realQuality = LockPatternUtils.computePasswordQuality(password); 1442 if (realQuality < quality 1443 && quality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) { 1444 Slog.w(TAG, "resetPassword: password quality 0x" 1445 + Integer.toHexString(quality) 1446 + " does not meet required quality 0x" 1447 + Integer.toHexString(quality)); 1448 return false; 1449 } 1450 quality = Math.max(realQuality, quality); 1451 } 1452 int length = getPasswordMinimumLength(null); 1453 if (password.length() < length) { 1454 Slog.w(TAG, "resetPassword: password length " + password.length() 1455 + " does not meet required length " + length); 1456 return false; 1457 } 1458 if (quality == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) { 1459 int letters = 0; 1460 int uppercase = 0; 1461 int lowercase = 0; 1462 int numbers = 0; 1463 int symbols = 0; 1464 int nonletter = 0; 1465 for (int i = 0; i < password.length(); i++) { 1466 char c = password.charAt(i); 1467 if (c >= 'A' && c <= 'Z') { 1468 letters++; 1469 uppercase++; 1470 } else if (c >= 'a' && c <= 'z') { 1471 letters++; 1472 lowercase++; 1473 } else if (c >= '0' && c <= '9') { 1474 numbers++; 1475 nonletter++; 1476 } else { 1477 symbols++; 1478 nonletter++; 1479 } 1480 } 1481 int neededLetters = getPasswordMinimumLetters(null); 1482 if(letters < neededLetters) { 1483 Slog.w(TAG, "resetPassword: number of letters " + letters 1484 + " does not meet required number of letters " + neededLetters); 1485 return false; 1486 } 1487 int neededNumbers = getPasswordMinimumNumeric(null); 1488 if (numbers < neededNumbers) { 1489 Slog 1490 .w(TAG, "resetPassword: number of numerical digits " + numbers 1491 + " does not meet required number of numerical digits " 1492 + neededNumbers); 1493 return false; 1494 } 1495 int neededLowerCase = getPasswordMinimumLowerCase(null); 1496 if (lowercase < neededLowerCase) { 1497 Slog.w(TAG, "resetPassword: number of lowercase letters " + lowercase 1498 + " does not meet required number of lowercase letters " 1499 + neededLowerCase); 1500 return false; 1501 } 1502 int neededUpperCase = getPasswordMinimumUpperCase(null); 1503 if (uppercase < neededUpperCase) { 1504 Slog.w(TAG, "resetPassword: number of uppercase letters " + uppercase 1505 + " does not meet required number of uppercase letters " 1506 + neededUpperCase); 1507 return false; 1508 } 1509 int neededSymbols = getPasswordMinimumSymbols(null); 1510 if (symbols < neededSymbols) { 1511 Slog.w(TAG, "resetPassword: number of special symbols " + symbols 1512 + " does not meet required number of special symbols " + neededSymbols); 1513 return false; 1514 } 1515 int neededNonLetter = getPasswordMinimumNonLetter(null); 1516 if (nonletter < neededNonLetter) { 1517 Slog.w(TAG, "resetPassword: number of non-letter characters " + nonletter 1518 + " does not meet required number of non-letter characters " 1519 + neededNonLetter); 1520 return false; 1521 } 1522 } 1523 1524 LockPatternUtils utils = new LockPatternUtils(mContext); 1525 if(utils.checkPasswordHistory(password)) { 1526 Slog.w(TAG, "resetPassword: password is the same as one of the last " 1527 + getPasswordHistoryLength(null) + " passwords"); 1528 return false; 1529 } 1530 } 1531 1532 int callingUid = Binder.getCallingUid(); 1533 if (mPasswordOwner >= 0 && mPasswordOwner != callingUid) { 1534 Slog.w(TAG, "resetPassword: already set by another uid and not entered by user"); 1535 return false; 1536 } 1537 1538 // Don't do this with the lock held, because it is going to call 1539 // back in to the service. 1540 long ident = Binder.clearCallingIdentity(); 1541 try { 1542 LockPatternUtils utils = new LockPatternUtils(mContext); 1543 utils.saveLockPassword(password, quality); 1544 synchronized (this) { 1545 int newOwner = (flags&DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY) 1546 != 0 ? callingUid : -1; 1547 if (mPasswordOwner != newOwner) { 1548 mPasswordOwner = newOwner; 1549 saveSettingsLocked(); 1550 } 1551 } 1552 } finally { 1553 Binder.restoreCallingIdentity(ident); 1554 } 1555 1556 return true; 1557 } 1558 1559 public void setMaximumTimeToLock(ComponentName who, long timeMs) { 1560 synchronized (this) { 1561 if (who == null) { 1562 throw new NullPointerException("ComponentName is null"); 1563 } 1564 ActiveAdmin ap = getActiveAdminForCallerLocked(who, 1565 DeviceAdminInfo.USES_POLICY_FORCE_LOCK); 1566 if (ap.maximumTimeToUnlock != timeMs) { 1567 ap.maximumTimeToUnlock = timeMs; 1568 1569 long ident = Binder.clearCallingIdentity(); 1570 try { 1571 saveSettingsLocked(); 1572 1573 timeMs = getMaximumTimeToLock(null); 1574 if (timeMs <= 0) { 1575 timeMs = Integer.MAX_VALUE; 1576 } 1577 1578 try { 1579 getIPowerManager().setMaximumScreenOffTimeount((int)timeMs); 1580 } catch (RemoteException e) { 1581 Slog.w(TAG, "Failure talking with power manager", e); 1582 } 1583 } finally { 1584 Binder.restoreCallingIdentity(ident); 1585 } 1586 } 1587 } 1588 } 1589 1590 public long getMaximumTimeToLock(ComponentName who) { 1591 synchronized (this) { 1592 long time = 0; 1593 1594 if (who != null) { 1595 ActiveAdmin admin = getActiveAdminUncheckedLocked(who); 1596 return admin != null ? admin.maximumTimeToUnlock : time; 1597 } 1598 1599 final int N = mAdminList.size(); 1600 for (int i=0; i<N; i++) { 1601 ActiveAdmin admin = mAdminList.get(i); 1602 if (time == 0) { 1603 time = admin.maximumTimeToUnlock; 1604 } else if (admin.maximumTimeToUnlock != 0 1605 && time > admin.maximumTimeToUnlock) { 1606 time = admin.maximumTimeToUnlock; 1607 } 1608 } 1609 return time; 1610 } 1611 } 1612 1613 public void lockNow() { 1614 synchronized (this) { 1615 // This API can only be called by an active device admin, 1616 // so try to retrieve it to check that the caller is one. 1617 getActiveAdminForCallerLocked(null, 1618 DeviceAdminInfo.USES_POLICY_FORCE_LOCK); 1619 long ident = Binder.clearCallingIdentity(); 1620 try { 1621 mIPowerManager.goToSleepWithReason(SystemClock.uptimeMillis(), 1622 WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN); 1623 } catch (RemoteException e) { 1624 } finally { 1625 Binder.restoreCallingIdentity(ident); 1626 } 1627 } 1628 } 1629 1630 void wipeDataLocked(int flags) { 1631 if ((flags&DevicePolicyManager.WIPE_EXTERNAL_STORAGE) != 0) { 1632 Intent intent = new Intent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET); 1633 intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME); 1634 mWakeLock.acquire(10000); 1635 mContext.startService(intent); 1636 } else { 1637 try { 1638 RecoverySystem.rebootWipeUserData(mContext); 1639 } catch (IOException e) { 1640 Slog.w(TAG, "Failed requesting data wipe", e); 1641 } 1642 } 1643 } 1644 1645 public void wipeData(int flags) { 1646 synchronized (this) { 1647 // This API can only be called by an active device admin, 1648 // so try to retrieve it to check that the caller is one. 1649 getActiveAdminForCallerLocked(null, 1650 DeviceAdminInfo.USES_POLICY_WIPE_DATA); 1651 long ident = Binder.clearCallingIdentity(); 1652 try { 1653 wipeDataLocked(flags); 1654 } finally { 1655 Binder.restoreCallingIdentity(ident); 1656 } 1657 } 1658 } 1659 1660 public void getRemoveWarning(ComponentName comp, final RemoteCallback result) { 1661 mContext.enforceCallingOrSelfPermission( 1662 android.Manifest.permission.BIND_DEVICE_ADMIN, null); 1663 1664 synchronized (this) { 1665 ActiveAdmin admin = getActiveAdminUncheckedLocked(comp); 1666 if (admin == null) { 1667 try { 1668 result.sendResult(null); 1669 } catch (RemoteException e) { 1670 } 1671 return; 1672 } 1673 Intent intent = new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLE_REQUESTED); 1674 intent.setComponent(admin.info.getComponent()); 1675 mContext.sendOrderedBroadcast(intent, null, new BroadcastReceiver() { 1676 @Override 1677 public void onReceive(Context context, Intent intent) { 1678 try { 1679 result.sendResult(getResultExtras(false)); 1680 } catch (RemoteException e) { 1681 } 1682 } 1683 }, null, Activity.RESULT_OK, null, null); 1684 } 1685 } 1686 1687 public void setActivePasswordState(int quality, int length, int letters, int uppercase, 1688 int lowercase, int numbers, int symbols, int nonletter) { 1689 mContext.enforceCallingOrSelfPermission( 1690 android.Manifest.permission.BIND_DEVICE_ADMIN, null); 1691 1692 validateQualityConstant(quality); 1693 1694 synchronized (this) { 1695 if (mActivePasswordQuality != quality || mActivePasswordLength != length 1696 || mFailedPasswordAttempts != 0 || mActivePasswordLetters != letters 1697 || mActivePasswordUpperCase != uppercase 1698 || mActivePasswordLowerCase != lowercase || mActivePasswordNumeric != numbers 1699 || mActivePasswordSymbols != symbols || mActivePasswordNonLetter != nonletter) { 1700 long ident = Binder.clearCallingIdentity(); 1701 try { 1702 mActivePasswordQuality = quality; 1703 mActivePasswordLength = length; 1704 mActivePasswordLetters = letters; 1705 mActivePasswordLowerCase = lowercase; 1706 mActivePasswordUpperCase = uppercase; 1707 mActivePasswordNumeric = numbers; 1708 mActivePasswordSymbols = symbols; 1709 mActivePasswordNonLetter = nonletter; 1710 mFailedPasswordAttempts = 0; 1711 saveSettingsLocked(); 1712 updatePasswordExpirationsLocked(); 1713 setExpirationAlarmCheckLocked(mContext); 1714 sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED, 1715 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); 1716 } finally { 1717 Binder.restoreCallingIdentity(ident); 1718 } 1719 } 1720 } 1721 } 1722 1723 /** 1724 * Called any time the device password is updated. Resets all password expiration clocks. 1725 */ 1726 private void updatePasswordExpirationsLocked() { 1727 final int N = mAdminList.size(); 1728 if (N > 0) { 1729 for (int i=0; i<N; i++) { 1730 ActiveAdmin admin = mAdminList.get(i); 1731 if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)) { 1732 long timeout = admin.passwordExpirationTimeout; 1733 long expiration = timeout > 0L ? (timeout + System.currentTimeMillis()) : 0L; 1734 admin.passwordExpirationDate = expiration; 1735 } 1736 } 1737 saveSettingsLocked(); 1738 } 1739 } 1740 1741 public void reportFailedPasswordAttempt() { 1742 mContext.enforceCallingOrSelfPermission( 1743 android.Manifest.permission.BIND_DEVICE_ADMIN, null); 1744 1745 synchronized (this) { 1746 long ident = Binder.clearCallingIdentity(); 1747 try { 1748 mFailedPasswordAttempts++; 1749 saveSettingsLocked(); 1750 int max = getMaximumFailedPasswordsForWipe(null); 1751 if (max > 0 && mFailedPasswordAttempts >= max) { 1752 wipeDataLocked(0); 1753 } 1754 sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_FAILED, 1755 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN); 1756 } finally { 1757 Binder.restoreCallingIdentity(ident); 1758 } 1759 } 1760 } 1761 1762 public void reportSuccessfulPasswordAttempt() { 1763 mContext.enforceCallingOrSelfPermission( 1764 android.Manifest.permission.BIND_DEVICE_ADMIN, null); 1765 1766 synchronized (this) { 1767 if (mFailedPasswordAttempts != 0 || mPasswordOwner >= 0) { 1768 long ident = Binder.clearCallingIdentity(); 1769 try { 1770 mFailedPasswordAttempts = 0; 1771 mPasswordOwner = -1; 1772 saveSettingsLocked(); 1773 sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED, 1774 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN); 1775 } finally { 1776 Binder.restoreCallingIdentity(ident); 1777 } 1778 } 1779 } 1780 } 1781 1782 public ComponentName setGlobalProxy(ComponentName who, String proxySpec, 1783 String exclusionList) { 1784 synchronized(this) { 1785 if (who == null) { 1786 throw new NullPointerException("ComponentName is null"); 1787 } 1788 1789 ActiveAdmin admin = getActiveAdminForCallerLocked(who, 1790 DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY); 1791 1792 // Scan through active admins and find if anyone has already 1793 // set the global proxy. 1794 Set<ComponentName> compSet = mAdminMap.keySet(); 1795 for (ComponentName component : compSet) { 1796 ActiveAdmin ap = mAdminMap.get(component); 1797 if ((ap.specifiesGlobalProxy) && (!component.equals(who))) { 1798 // Another admin already sets the global proxy 1799 // Return it to the caller. 1800 return component; 1801 } 1802 } 1803 if (proxySpec == null) { 1804 admin.specifiesGlobalProxy = false; 1805 admin.globalProxySpec = null; 1806 admin.globalProxyExclusionList = null; 1807 } else { 1808 1809 admin.specifiesGlobalProxy = true; 1810 admin.globalProxySpec = proxySpec; 1811 admin.globalProxyExclusionList = exclusionList; 1812 } 1813 1814 // Reset the global proxy accordingly 1815 // Do this using system permissions, as apps cannot write to secure settings 1816 long origId = Binder.clearCallingIdentity(); 1817 resetGlobalProxy(); 1818 Binder.restoreCallingIdentity(origId); 1819 return null; 1820 } 1821 } 1822 1823 public ComponentName getGlobalProxyAdmin() { 1824 synchronized(this) { 1825 // Scan through active admins and find if anyone has already 1826 // set the global proxy. 1827 final int N = mAdminList.size(); 1828 for (int i = 0; i < N; i++) { 1829 ActiveAdmin ap = mAdminList.get(i); 1830 if (ap.specifiesGlobalProxy) { 1831 // Device admin sets the global proxy 1832 // Return it to the caller. 1833 return ap.info.getComponent(); 1834 } 1835 } 1836 } 1837 // No device admin sets the global proxy. 1838 return null; 1839 } 1840 1841 private void resetGlobalProxy() { 1842 final int N = mAdminList.size(); 1843 for (int i = 0; i < N; i++) { 1844 ActiveAdmin ap = mAdminList.get(i); 1845 if (ap.specifiesGlobalProxy) { 1846 saveGlobalProxy(ap.globalProxySpec, ap.globalProxyExclusionList); 1847 return; 1848 } 1849 } 1850 // No device admins defining global proxies - reset global proxy settings to none 1851 saveGlobalProxy(null, null); 1852 } 1853 1854 private void saveGlobalProxy(String proxySpec, String exclusionList) { 1855 if (exclusionList == null) { 1856 exclusionList = ""; 1857 } 1858 if (proxySpec == null) { 1859 proxySpec = ""; 1860 } 1861 // Remove white spaces 1862 proxySpec = proxySpec.trim(); 1863 String data[] = proxySpec.split(":"); 1864 int proxyPort = 8080; 1865 if (data.length > 1) { 1866 try { 1867 proxyPort = Integer.parseInt(data[1]); 1868 } catch (NumberFormatException e) {} 1869 } 1870 exclusionList = exclusionList.trim(); 1871 ContentResolver res = mContext.getContentResolver(); 1872 Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST, data[0]); 1873 Settings.Secure.putInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, proxyPort); 1874 Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST, 1875 exclusionList); 1876 } 1877 1878 /** 1879 * Set the storage encryption request for a single admin. Returns the new total request 1880 * status (for all admins). 1881 */ 1882 public int setStorageEncryption(ComponentName who, boolean encrypt) { 1883 synchronized (this) { 1884 // Check for permissions 1885 if (who == null) { 1886 throw new NullPointerException("ComponentName is null"); 1887 } 1888 ActiveAdmin ap = getActiveAdminForCallerLocked(who, 1889 DeviceAdminInfo.USES_ENCRYPTED_STORAGE); 1890 1891 // Quick exit: If the filesystem does not support encryption, we can exit early. 1892 if (!isEncryptionSupported()) { 1893 return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED; 1894 } 1895 1896 // (1) Record the value for the admin so it's sticky 1897 if (ap.encryptionRequested != encrypt) { 1898 ap.encryptionRequested = encrypt; 1899 saveSettingsLocked(); 1900 } 1901 1902 // (2) Compute "max" for all admins 1903 boolean newRequested = false; 1904 final int N = mAdminList.size(); 1905 for (int i = 0; i < N; i++) { 1906 newRequested |= mAdminList.get(i).encryptionRequested; 1907 } 1908 1909 // Notify OS of new request 1910 setEncryptionRequested(newRequested); 1911 1912 // Return the new global request status 1913 return newRequested 1914 ? DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE 1915 : DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE; 1916 } 1917 } 1918 1919 /** 1920 * Get the current storage encryption request status for a given admin, or aggregate of all 1921 * active admins. 1922 */ 1923 public boolean getStorageEncryption(ComponentName who) { 1924 synchronized (this) { 1925 // Check for permissions if a particular caller is specified 1926 if (who != null) { 1927 // When checking for a single caller, status is based on caller's request 1928 ActiveAdmin ap = getActiveAdminUncheckedLocked(who); 1929 return ap != null ? ap.encryptionRequested : false; 1930 } 1931 1932 // If no particular caller is specified, return the aggregate set of requests. 1933 // This is short circuited by returning true on the first hit. 1934 final int N = mAdminList.size(); 1935 for (int i = 0; i < N; i++) { 1936 if (mAdminList.get(i).encryptionRequested) { 1937 return true; 1938 } 1939 } 1940 return false; 1941 } 1942 } 1943 1944 /** 1945 * Get the current encryption status of the device. 1946 */ 1947 public int getStorageEncryptionStatus() { 1948 return getEncryptionStatus(); 1949 } 1950 1951 /** 1952 * Hook to low-levels: This should report if the filesystem supports encrypted storage. 1953 */ 1954 private boolean isEncryptionSupported() { 1955 // Note, this can be implemented as 1956 // return getEncryptionStatus() != DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED; 1957 // But is provided as a separate internal method if there's a faster way to do a 1958 // simple check for supported-or-not. 1959 return getEncryptionStatus() != DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED; 1960 } 1961 1962 /** 1963 * Hook to low-levels: Reporting the current status of encryption. 1964 * @return A value such as {@link DevicePolicyManager#ENCRYPTION_STATUS_UNSUPPORTED} or 1965 * {@link DevicePolicyManager#ENCRYPTION_STATUS_INACTIVE} or 1966 * {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE}. 1967 */ 1968 private int getEncryptionStatus() { 1969 String status = SystemProperties.get("ro.crypto.state", "unsupported"); 1970 if ("encrypted".equalsIgnoreCase(status)) { 1971 return DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE; 1972 } else if ("unencrypted".equalsIgnoreCase(status)) { 1973 return DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE; 1974 } else { 1975 return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED; 1976 } 1977 } 1978 1979 /** 1980 * Hook to low-levels: If needed, record the new admin setting for encryption. 1981 */ 1982 private void setEncryptionRequested(boolean encrypt) { 1983 } 1984 1985 @Override 1986 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1987 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1988 != PackageManager.PERMISSION_GRANTED) { 1989 1990 pw.println("Permission Denial: can't dump DevicePolicyManagerService from from pid=" 1991 + Binder.getCallingPid() 1992 + ", uid=" + Binder.getCallingUid()); 1993 return; 1994 } 1995 1996 final Printer p = new PrintWriterPrinter(pw); 1997 1998 synchronized (this) { 1999 p.println("Current Device Policy Manager state:"); 2000 2001 p.println(" Enabled Device Admins:"); 2002 final int N = mAdminList.size(); 2003 for (int i=0; i<N; i++) { 2004 ActiveAdmin ap = mAdminList.get(i); 2005 if (ap != null) { 2006 pw.print(" "); pw.print(ap.info.getComponent().flattenToShortString()); 2007 pw.println(":"); 2008 ap.dump(" ", pw); 2009 } 2010 } 2011 2012 pw.println(" "); 2013 pw.print(" mActivePasswordQuality=0x"); 2014 pw.println(Integer.toHexString(mActivePasswordQuality)); 2015 pw.print(" mActivePasswordLength="); pw.println(mActivePasswordLength); 2016 pw.print(" mActivePasswordUpperCase="); pw.println(mActivePasswordUpperCase); 2017 pw.print(" mActivePasswordLowerCase="); pw.println(mActivePasswordLowerCase); 2018 pw.print(" mActivePasswordLetters="); pw.println(mActivePasswordLetters); 2019 pw.print(" mActivePasswordNumeric="); pw.println(mActivePasswordNumeric); 2020 pw.print(" mActivePasswordSymbols="); pw.println(mActivePasswordSymbols); 2021 pw.print(" mActivePasswordNonLetter="); pw.println(mActivePasswordNonLetter); 2022 pw.print(" mFailedPasswordAttempts="); pw.println(mFailedPasswordAttempts); 2023 pw.print(" mPasswordOwner="); pw.println(mPasswordOwner); 2024 } 2025 } 2026} 2027