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