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 17 package com.android.server; 18 19 import com.android.internal.content.PackageMonitor; 20 import com.android.internal.os.storage.ExternalStorageFormatter; 21 import com.android.internal.util.FastXmlSerializer; 22 import com.android.internal.util.JournaledFile; 23 import com.android.internal.util.XmlUtils; 24 import com.android.internal.widget.LockPatternUtils; 25 26 import org.xmlpull.v1.XmlPullParser; 27 import org.xmlpull.v1.XmlPullParserException; 28 import org.xmlpull.v1.XmlSerializer; 29 30 import android.app.Activity; 31 import android.app.admin.DeviceAdminInfo; 32 import android.app.admin.DeviceAdminReceiver; 33 import android.app.admin.DevicePolicyManager; 34 import android.app.admin.IDevicePolicyManager; 35 import android.content.BroadcastReceiver; 36 import android.content.ComponentName; 37 import android.content.Context; 38 import android.content.Intent; 39 import android.content.pm.PackageManager; 40 import android.content.pm.ResolveInfo; 41 import android.content.pm.PackageManager.NameNotFoundException; 42 import android.os.Binder; 43 import android.os.IBinder; 44 import android.os.IPowerManager; 45 import android.os.PowerManager; 46 import android.os.RecoverySystem; 47 import android.os.RemoteCallback; 48 import android.os.RemoteException; 49 import android.os.ServiceManager; 50 import android.os.SystemClock; 51 import android.util.Slog; 52 import android.util.PrintWriterPrinter; 53 import android.util.Printer; 54 import android.util.Xml; 55 import android.view.WindowManagerPolicy; 56 57 import java.io.File; 58 import java.io.FileDescriptor; 59 import java.io.FileInputStream; 60 import java.io.FileNotFoundException; 61 import java.io.FileOutputStream; 62 import java.io.IOException; 63 import java.io.PrintWriter; 64 import java.util.ArrayList; 65 import java.util.HashMap; 66 import java.util.List; 67 68 /** 69 * Implementation of the device policy APIs. 70 */ 71 public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { 72 static final String TAG = "DevicePolicyManagerService"; 73 74 final Context mContext; 75 final MyPackageMonitor mMonitor; 76 final PowerManager.WakeLock mWakeLock; 77 78 IPowerManager mIPowerManager; 79 80 int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 81 int mActivePasswordLength = 0; 82 int mFailedPasswordAttempts = 0; 83 84 int mPasswordOwner = -1; 85 86 final HashMap<ComponentName, ActiveAdmin> mAdminMap 87 = new HashMap<ComponentName, ActiveAdmin>(); 88 final ArrayList<ActiveAdmin> mAdminList 89 = new ArrayList<ActiveAdmin>(); 90 91 static class ActiveAdmin { 92 final DeviceAdminInfo info; 93 94 int passwordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 95 int minimumPasswordLength = 0; 96 long maximumTimeToUnlock = 0; 97 int maximumFailedPasswordsForWipe = 0; 98 99 ActiveAdmin(DeviceAdminInfo _info) { 100 info = _info; 101 } 102 103 int getUid() { return info.getActivityInfo().applicationInfo.uid; } 104 105 void writeToXml(XmlSerializer out) 106 throws IllegalArgumentException, IllegalStateException, IOException { 107 out.startTag(null, "policies"); 108 info.writePoliciesToXml(out); 109 out.endTag(null, "policies"); 110 if (passwordQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { 111 out.startTag(null, "password-quality"); 112 out.attribute(null, "value", Integer.toString(passwordQuality)); 113 out.endTag(null, "password-quality"); 114 if (minimumPasswordLength > 0) { 115 out.startTag(null, "min-password-length"); 116 out.attribute(null, "value", Integer.toString(minimumPasswordLength)); 117 out.endTag(null, "mn-password-length"); 118 } 119 } 120 if (maximumTimeToUnlock != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { 121 out.startTag(null, "max-time-to-unlock"); 122 out.attribute(null, "value", Long.toString(maximumTimeToUnlock)); 123 out.endTag(null, "max-time-to-unlock"); 124 } 125 if (maximumFailedPasswordsForWipe != 0) { 126 out.startTag(null, "max-failed-password-wipe"); 127 out.attribute(null, "value", Integer.toString(maximumFailedPasswordsForWipe)); 128 out.endTag(null, "max-failed-password-wipe"); 129 } 130 } 131 132 void readFromXml(XmlPullParser parser) 133 throws XmlPullParserException, IOException { 134 int outerDepth = parser.getDepth(); 135 int type; 136 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 137 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 138 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 139 continue; 140 } 141 String tag = parser.getName(); 142 if ("policies".equals(tag)) { 143 info.readPoliciesFromXml(parser); 144 } else if ("password-quality".equals(tag)) { 145 passwordQuality = Integer.parseInt( 146 parser.getAttributeValue(null, "value")); 147 } else if ("min-password-length".equals(tag)) { 148 minimumPasswordLength = Integer.parseInt( 149 parser.getAttributeValue(null, "value")); 150 } else if ("max-time-to-unlock".equals(tag)) { 151 maximumTimeToUnlock = Long.parseLong( 152 parser.getAttributeValue(null, "value")); 153 } else if ("max-failed-password-wipe".equals(tag)) { 154 maximumFailedPasswordsForWipe = Integer.parseInt( 155 parser.getAttributeValue(null, "value")); 156 } else { 157 Slog.w(TAG, "Unknown admin tag: " + tag); 158 } 159 XmlUtils.skipCurrentTag(parser); 160 } 161 } 162 163 void dump(String prefix, PrintWriter pw) { 164 pw.print(prefix); pw.print("uid="); pw.println(getUid()); 165 pw.print(prefix); pw.println("policies:"); 166 ArrayList<DeviceAdminInfo.PolicyInfo> pols = info.getUsedPolicies(); 167 if (pols != null) { 168 for (int i=0; i<pols.size(); i++) { 169 pw.print(prefix); pw.print(" "); pw.println(pols.get(i).tag); 170 } 171 } 172 pw.print(prefix); pw.print("passwordQuality=0x"); 173 pw.print(Integer.toHexString(passwordQuality)); 174 pw.print(" minimumPasswordLength="); 175 pw.println(minimumPasswordLength); 176 pw.print(prefix); pw.print("maximumTimeToUnlock="); 177 pw.println(maximumTimeToUnlock); 178 pw.print(prefix); pw.print("maximumFailedPasswordsForWipe="); 179 pw.println(maximumFailedPasswordsForWipe); 180 } 181 } 182 183 class MyPackageMonitor extends PackageMonitor { 184 public void onSomePackagesChanged() { 185 synchronized (DevicePolicyManagerService.this) { 186 boolean removed = false; 187 for (int i=mAdminList.size()-1; i>=0; i--) { 188 ActiveAdmin aa = mAdminList.get(i); 189 int change = isPackageDisappearing(aa.info.getPackageName()); 190 if (change == PACKAGE_PERMANENT_CHANGE 191 || change == PACKAGE_TEMPORARY_CHANGE) { 192 Slog.w(TAG, "Admin unexpectedly uninstalled: " 193 + aa.info.getComponent()); 194 removed = true; 195 mAdminList.remove(i); 196 } else if (isPackageModified(aa.info.getPackageName())) { 197 try { 198 mContext.getPackageManager().getReceiverInfo( 199 aa.info.getComponent(), 0); 200 } catch (NameNotFoundException e) { 201 Slog.w(TAG, "Admin package change removed component: " 202 + aa.info.getComponent()); 203 removed = true; 204 mAdminList.remove(i); 205 } 206 } 207 } 208 if (removed) { 209 validatePasswordOwnerLocked(); 210 } 211 } 212 } 213 } 214 215 /** 216 * Instantiates the service. 217 */ 218 public DevicePolicyManagerService(Context context) { 219 mContext = context; 220 mMonitor = new MyPackageMonitor(); 221 mMonitor.register(context, true); 222 mWakeLock = ((PowerManager)context.getSystemService(Context.POWER_SERVICE)) 223 .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DPM"); 224 } 225 226 private IPowerManager getIPowerManager() { 227 if (mIPowerManager == null) { 228 IBinder b = ServiceManager.getService(Context.POWER_SERVICE); 229 mIPowerManager = IPowerManager.Stub.asInterface(b); 230 } 231 return mIPowerManager; 232 } 233 234 ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who) { 235 ActiveAdmin admin = mAdminMap.get(who); 236 if (admin != null 237 && who.getPackageName().equals(admin.info.getActivityInfo().packageName) 238 && who.getClassName().equals(admin.info.getActivityInfo().name)) { 239 return admin; 240 } 241 return null; 242 } 243 244 ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy) 245 throws SecurityException { 246 final int callingUid = Binder.getCallingUid(); 247 if (who != null) { 248 ActiveAdmin admin = mAdminMap.get(who); 249 if (admin == null) { 250 throw new SecurityException("No active admin " + who); 251 } 252 if (admin.getUid() != callingUid) { 253 throw new SecurityException("Admin " + who + " is not owned by uid " 254 + Binder.getCallingUid()); 255 } 256 if (!admin.info.usesPolicy(reqPolicy)) { 257 throw new SecurityException("Admin " + admin.info.getComponent() 258 + " did not specify uses-policy for: " 259 + admin.info.getTagForPolicy(reqPolicy)); 260 } 261 return admin; 262 } else { 263 final int N = mAdminList.size(); 264 for (int i=0; i<N; i++) { 265 ActiveAdmin admin = mAdminList.get(i); 266 if (admin.getUid() == callingUid && admin.info.usesPolicy(reqPolicy)) { 267 return admin; 268 } 269 } 270 throw new SecurityException("No active admin owned by uid " 271 + Binder.getCallingUid() + " for policy #" + reqPolicy); 272 } 273 } 274 275 void sendAdminCommandLocked(ActiveAdmin admin, String action) { 276 Intent intent = new Intent(action); 277 intent.setComponent(admin.info.getComponent()); 278 mContext.sendBroadcast(intent); 279 } 280 281 void sendAdminCommandLocked(String action, int reqPolicy) { 282 final int N = mAdminList.size(); 283 if (N > 0) { 284 for (int i=0; i<N; i++) { 285 ActiveAdmin admin = mAdminList.get(i); 286 if (admin.info.usesPolicy(reqPolicy)) { 287 sendAdminCommandLocked(admin, action); 288 } 289 } 290 } 291 } 292 293 void removeActiveAdminLocked(ComponentName adminReceiver) { 294 ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver); 295 if (admin != null) { 296 sendAdminCommandLocked(admin, 297 DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED); 298 // XXX need to wait for it to complete. 299 mAdminList.remove(admin); 300 mAdminMap.remove(adminReceiver); 301 validatePasswordOwnerLocked(); 302 } 303 } 304 305 public DeviceAdminInfo findAdmin(ComponentName adminName) { 306 Intent resolveIntent = new Intent(); 307 resolveIntent.setComponent(adminName); 308 List<ResolveInfo> infos = mContext.getPackageManager().queryBroadcastReceivers( 309 resolveIntent, PackageManager.GET_META_DATA); 310 if (infos == null || infos.size() <= 0) { 311 throw new IllegalArgumentException("Unknown admin: " + adminName); 312 } 313 314 try { 315 return new DeviceAdminInfo(mContext, infos.get(0)); 316 } catch (XmlPullParserException e) { 317 Slog.w(TAG, "Bad device admin requested: " + adminName, e); 318 return null; 319 } catch (IOException e) { 320 Slog.w(TAG, "Bad device admin requested: " + adminName, e); 321 return null; 322 } 323 } 324 325 private static JournaledFile makeJournaledFile() { 326 final String base = "/data/system/device_policies.xml"; 327 return new JournaledFile(new File(base), new File(base + ".tmp")); 328 } 329 330 private void saveSettingsLocked() { 331 JournaledFile journal = makeJournaledFile(); 332 FileOutputStream stream = null; 333 try { 334 stream = new FileOutputStream(journal.chooseForWrite(), false); 335 XmlSerializer out = new FastXmlSerializer(); 336 out.setOutput(stream, "utf-8"); 337 out.startDocument(null, true); 338 339 out.startTag(null, "policies"); 340 341 final int N = mAdminList.size(); 342 for (int i=0; i<N; i++) { 343 ActiveAdmin ap = mAdminList.get(i); 344 if (ap != null) { 345 out.startTag(null, "admin"); 346 out.attribute(null, "name", ap.info.getComponent().flattenToString()); 347 ap.writeToXml(out); 348 out.endTag(null, "admin"); 349 } 350 } 351 352 if (mPasswordOwner >= 0) { 353 out.startTag(null, "password-owner"); 354 out.attribute(null, "value", Integer.toString(mPasswordOwner)); 355 out.endTag(null, "password-owner"); 356 } 357 358 if (mFailedPasswordAttempts != 0) { 359 out.startTag(null, "failed-password-attempts"); 360 out.attribute(null, "value", Integer.toString(mFailedPasswordAttempts)); 361 out.endTag(null, "failed-password-attempts"); 362 } 363 364 if (mActivePasswordQuality != 0 || mActivePasswordLength != 0) { 365 out.startTag(null, "active-password"); 366 out.attribute(null, "quality", Integer.toString(mActivePasswordQuality)); 367 out.attribute(null, "length", Integer.toString(mActivePasswordLength)); 368 out.endTag(null, "active-password"); 369 } 370 371 out.endTag(null, "policies"); 372 373 out.endDocument(); 374 stream.close(); 375 journal.commit(); 376 sendChangedNotification(); 377 } catch (IOException e) { 378 try { 379 if (stream != null) { 380 stream.close(); 381 } 382 } catch (IOException ex) { 383 // Ignore 384 } 385 journal.rollback(); 386 } 387 } 388 389 private void sendChangedNotification() { 390 Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 391 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 392 mContext.sendBroadcast(intent); 393 } 394 395 private void loadSettingsLocked() { 396 JournaledFile journal = makeJournaledFile(); 397 FileInputStream stream = null; 398 File file = journal.chooseForRead(); 399 try { 400 stream = new FileInputStream(file); 401 XmlPullParser parser = Xml.newPullParser(); 402 parser.setInput(stream, null); 403 404 int type; 405 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 406 && type != XmlPullParser.START_TAG) { 407 } 408 String tag = parser.getName(); 409 if (!"policies".equals(tag)) { 410 throw new XmlPullParserException( 411 "Settings do not start with policies tag: found " + tag); 412 } 413 type = parser.next(); 414 int outerDepth = parser.getDepth(); 415 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 416 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 417 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 418 continue; 419 } 420 tag = parser.getName(); 421 if ("admin".equals(tag)) { 422 String name = parser.getAttributeValue(null, "name"); 423 try { 424 DeviceAdminInfo dai = findAdmin( 425 ComponentName.unflattenFromString(name)); 426 if (dai != null) { 427 ActiveAdmin ap = new ActiveAdmin(dai); 428 ap.readFromXml(parser); 429 mAdminMap.put(ap.info.getComponent(), ap); 430 mAdminList.add(ap); 431 } 432 } catch (RuntimeException e) { 433 Slog.w(TAG, "Failed loading admin " + name, e); 434 } 435 } else if ("failed-password-attempts".equals(tag)) { 436 mFailedPasswordAttempts = Integer.parseInt( 437 parser.getAttributeValue(null, "value")); 438 XmlUtils.skipCurrentTag(parser); 439 } else if ("password-owner".equals(tag)) { 440 mPasswordOwner = Integer.parseInt( 441 parser.getAttributeValue(null, "value")); 442 XmlUtils.skipCurrentTag(parser); 443 } else if ("active-password".equals(tag)) { 444 mActivePasswordQuality = Integer.parseInt( 445 parser.getAttributeValue(null, "quality")); 446 mActivePasswordLength = Integer.parseInt( 447 parser.getAttributeValue(null, "length")); 448 XmlUtils.skipCurrentTag(parser); 449 } else { 450 Slog.w(TAG, "Unknown tag: " + tag); 451 XmlUtils.skipCurrentTag(parser); 452 } 453 } 454 } catch (NullPointerException e) { 455 Slog.w(TAG, "failed parsing " + file + " " + e); 456 } catch (NumberFormatException e) { 457 Slog.w(TAG, "failed parsing " + file + " " + e); 458 } catch (XmlPullParserException e) { 459 Slog.w(TAG, "failed parsing " + file + " " + e); 460 } catch (FileNotFoundException e) { 461 // Don't be noisy, this is normal if we haven't defined any policies. 462 } catch (IOException e) { 463 Slog.w(TAG, "failed parsing " + file + " " + e); 464 } catch (IndexOutOfBoundsException e) { 465 Slog.w(TAG, "failed parsing " + file + " " + e); 466 } 467 try { 468 if (stream != null) { 469 stream.close(); 470 } 471 } catch (IOException e) { 472 // Ignore 473 } 474 475 // Validate that what we stored for the password quality matches 476 // sufficiently what is currently set. Note that this is only 477 // a sanity check in case the two get out of sync; this should 478 // never normally happen. 479 LockPatternUtils utils = new LockPatternUtils(mContext); 480 if (utils.getActivePasswordQuality() < mActivePasswordQuality) { 481 Slog.w(TAG, "Active password quality 0x" 482 + Integer.toHexString(mActivePasswordQuality) 483 + " does not match actual quality 0x" 484 + Integer.toHexString(utils.getActivePasswordQuality())); 485 mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 486 mActivePasswordLength = 0; 487 } 488 489 validatePasswordOwnerLocked(); 490 491 long timeMs = getMaximumTimeToLock(null); 492 if (timeMs <= 0) { 493 timeMs = Integer.MAX_VALUE; 494 } 495 try { 496 getIPowerManager().setMaximumScreenOffTimeount((int)timeMs); 497 } catch (RemoteException e) { 498 Slog.w(TAG, "Failure talking with power manager", e); 499 } 500 } 501 502 static void validateQualityConstant(int quality) { 503 switch (quality) { 504 case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED: 505 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: 506 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: 507 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: 508 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: 509 return; 510 } 511 throw new IllegalArgumentException("Invalid quality constant: 0x" 512 + Integer.toHexString(quality)); 513 } 514 515 void validatePasswordOwnerLocked() { 516 if (mPasswordOwner >= 0) { 517 boolean haveOwner = false; 518 for (int i=mAdminList.size()-1; i>=0; i--) { 519 if (mAdminList.get(i).getUid() == mPasswordOwner) { 520 haveOwner = true; 521 break; 522 } 523 } 524 if (!haveOwner) { 525 Slog.w(TAG, "Previous password owner " + mPasswordOwner 526 + " no longer active; disabling"); 527 mPasswordOwner = -1; 528 } 529 } 530 } 531 532 public void systemReady() { 533 synchronized (this) { 534 loadSettingsLocked(); 535 } 536 } 537 538 public void setActiveAdmin(ComponentName adminReceiver) { 539 mContext.enforceCallingOrSelfPermission( 540 android.Manifest.permission.BIND_DEVICE_ADMIN, null); 541 542 DeviceAdminInfo info = findAdmin(adminReceiver); 543 if (info == null) { 544 throw new IllegalArgumentException("Bad admin: " + adminReceiver); 545 } 546 synchronized (this) { 547 long ident = Binder.clearCallingIdentity(); 548 try { 549 if (getActiveAdminUncheckedLocked(adminReceiver) != null) { 550 throw new IllegalArgumentException("Admin is already added"); 551 } 552 ActiveAdmin admin = new ActiveAdmin(info); 553 mAdminMap.put(adminReceiver, admin); 554 mAdminList.add(admin); 555 saveSettingsLocked(); 556 sendAdminCommandLocked(admin, 557 DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED); 558 } finally { 559 Binder.restoreCallingIdentity(ident); 560 } 561 } 562 } 563 564 public boolean isAdminActive(ComponentName adminReceiver) { 565 synchronized (this) { 566 return getActiveAdminUncheckedLocked(adminReceiver) != null; 567 } 568 } 569 570 public List<ComponentName> getActiveAdmins() { 571 synchronized (this) { 572 final int N = mAdminList.size(); 573 if (N <= 0) { 574 return null; 575 } 576 ArrayList<ComponentName> res = new ArrayList<ComponentName>(N); 577 for (int i=0; i<N; i++) { 578 res.add(mAdminList.get(i).info.getComponent()); 579 } 580 return res; 581 } 582 } 583 584 public boolean packageHasActiveAdmins(String packageName) { 585 synchronized (this) { 586 final int N = mAdminList.size(); 587 for (int i=0; i<N; i++) { 588 if (mAdminList.get(i).info.getPackageName().equals(packageName)) { 589 return true; 590 } 591 } 592 return false; 593 } 594 } 595 596 public void removeActiveAdmin(ComponentName adminReceiver) { 597 synchronized (this) { 598 ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver); 599 if (admin == null) { 600 return; 601 } 602 if (admin.getUid() != Binder.getCallingUid()) { 603 mContext.enforceCallingOrSelfPermission( 604 android.Manifest.permission.BIND_DEVICE_ADMIN, null); 605 } 606 long ident = Binder.clearCallingIdentity(); 607 try { 608 removeActiveAdminLocked(adminReceiver); 609 } finally { 610 Binder.restoreCallingIdentity(ident); 611 } 612 } 613 } 614 615 public void setPasswordQuality(ComponentName who, int quality) { 616 validateQualityConstant(quality); 617 618 synchronized (this) { 619 if (who == null) { 620 throw new NullPointerException("ComponentName is null"); 621 } 622 ActiveAdmin ap = getActiveAdminForCallerLocked(who, 623 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); 624 if (ap.passwordQuality != quality) { 625 ap.passwordQuality = quality; 626 saveSettingsLocked(); 627 } 628 } 629 } 630 631 public int getPasswordQuality(ComponentName who) { 632 synchronized (this) { 633 int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 634 635 if (who != null) { 636 ActiveAdmin admin = getActiveAdminUncheckedLocked(who); 637 return admin != null ? admin.passwordQuality : mode; 638 } 639 640 final int N = mAdminList.size(); 641 for (int i=0; i<N; i++) { 642 ActiveAdmin admin = mAdminList.get(i); 643 if (mode < admin.passwordQuality) { 644 mode = admin.passwordQuality; 645 } 646 } 647 return mode; 648 } 649 } 650 651 public void setPasswordMinimumLength(ComponentName who, int length) { 652 synchronized (this) { 653 if (who == null) { 654 throw new NullPointerException("ComponentName is null"); 655 } 656 ActiveAdmin ap = getActiveAdminForCallerLocked(who, 657 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); 658 if (ap.minimumPasswordLength != length) { 659 ap.minimumPasswordLength = length; 660 saveSettingsLocked(); 661 } 662 } 663 } 664 665 public int getPasswordMinimumLength(ComponentName who) { 666 synchronized (this) { 667 int length = 0; 668 669 if (who != null) { 670 ActiveAdmin admin = getActiveAdminUncheckedLocked(who); 671 return admin != null ? admin.minimumPasswordLength : length; 672 } 673 674 final int N = mAdminList.size(); 675 for (int i=0; i<N; i++) { 676 ActiveAdmin admin = mAdminList.get(i); 677 if (length < admin.minimumPasswordLength) { 678 length = admin.minimumPasswordLength; 679 } 680 } 681 return length; 682 } 683 } 684 685 public boolean isActivePasswordSufficient() { 686 synchronized (this) { 687 // This API can only be called by an active device admin, 688 // so try to retrieve it to check that the caller is one. 689 getActiveAdminForCallerLocked(null, 690 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); 691 return mActivePasswordQuality >= getPasswordQuality(null) 692 && mActivePasswordLength >= getPasswordMinimumLength(null); 693 } 694 } 695 696 public int getCurrentFailedPasswordAttempts() { 697 synchronized (this) { 698 // This API can only be called by an active device admin, 699 // so try to retrieve it to check that the caller is one. 700 getActiveAdminForCallerLocked(null, 701 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN); 702 return mFailedPasswordAttempts; 703 } 704 } 705 706 public void setMaximumFailedPasswordsForWipe(ComponentName who, int num) { 707 synchronized (this) { 708 // This API can only be called by an active device admin, 709 // so try to retrieve it to check that the caller is one. 710 getActiveAdminForCallerLocked(who, 711 DeviceAdminInfo.USES_POLICY_WIPE_DATA); 712 ActiveAdmin ap = getActiveAdminForCallerLocked(who, 713 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN); 714 if (ap.maximumFailedPasswordsForWipe != num) { 715 ap.maximumFailedPasswordsForWipe = num; 716 saveSettingsLocked(); 717 } 718 } 719 } 720 721 public int getMaximumFailedPasswordsForWipe(ComponentName who) { 722 synchronized (this) { 723 int count = 0; 724 725 if (who != null) { 726 ActiveAdmin admin = getActiveAdminUncheckedLocked(who); 727 return admin != null ? admin.maximumFailedPasswordsForWipe : count; 728 } 729 730 final int N = mAdminList.size(); 731 for (int i=0; i<N; i++) { 732 ActiveAdmin admin = mAdminList.get(i); 733 if (count == 0) { 734 count = admin.maximumFailedPasswordsForWipe; 735 } else if (admin.maximumFailedPasswordsForWipe != 0 736 && count > admin.maximumFailedPasswordsForWipe) { 737 count = admin.maximumFailedPasswordsForWipe; 738 } 739 } 740 return count; 741 } 742 } 743 744 public boolean resetPassword(String password, int flags) { 745 int quality; 746 synchronized (this) { 747 // This API can only be called by an active device admin, 748 // so try to retrieve it to check that the caller is one. 749 getActiveAdminForCallerLocked(null, 750 DeviceAdminInfo.USES_POLICY_RESET_PASSWORD); 751 quality = getPasswordQuality(null); 752 if (quality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { 753 int realQuality = LockPatternUtils.computePasswordQuality(password); 754 if (realQuality < quality) { 755 Slog.w(TAG, "resetPassword: password quality 0x" 756 + Integer.toHexString(quality) 757 + " does not meet required quality 0x" 758 + Integer.toHexString(quality)); 759 return false; 760 } 761 quality = realQuality; 762 } 763 int length = getPasswordMinimumLength(null); 764 if (password.length() < length) { 765 Slog.w(TAG, "resetPassword: password length " + password.length() 766 + " does not meet required length " + length); 767 return false; 768 } 769 } 770 771 int callingUid = Binder.getCallingUid(); 772 if (mPasswordOwner >= 0 && mPasswordOwner != callingUid) { 773 Slog.w(TAG, "resetPassword: already set by another uid and not entered by user"); 774 return false; 775 } 776 777 // Don't do this with the lock held, because it is going to call 778 // back in to the service. 779 long ident = Binder.clearCallingIdentity(); 780 try { 781 LockPatternUtils utils = new LockPatternUtils(mContext); 782 utils.saveLockPassword(password, quality); 783 synchronized (this) { 784 int newOwner = (flags&DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY) 785 != 0 ? callingUid : -1; 786 if (mPasswordOwner != newOwner) { 787 mPasswordOwner = newOwner; 788 saveSettingsLocked(); 789 } 790 } 791 } finally { 792 Binder.restoreCallingIdentity(ident); 793 } 794 795 return true; 796 } 797 798 public void setMaximumTimeToLock(ComponentName who, long timeMs) { 799 synchronized (this) { 800 if (who == null) { 801 throw new NullPointerException("ComponentName is null"); 802 } 803 ActiveAdmin ap = getActiveAdminForCallerLocked(who, 804 DeviceAdminInfo.USES_POLICY_FORCE_LOCK); 805 if (ap.maximumTimeToUnlock != timeMs) { 806 ap.maximumTimeToUnlock = timeMs; 807 808 long ident = Binder.clearCallingIdentity(); 809 try { 810 saveSettingsLocked(); 811 812 timeMs = getMaximumTimeToLock(null); 813 if (timeMs <= 0) { 814 timeMs = Integer.MAX_VALUE; 815 } 816 817 try { 818 getIPowerManager().setMaximumScreenOffTimeount((int)timeMs); 819 } catch (RemoteException e) { 820 Slog.w(TAG, "Failure talking with power manager", e); 821 } 822 } finally { 823 Binder.restoreCallingIdentity(ident); 824 } 825 } 826 } 827 } 828 829 public long getMaximumTimeToLock(ComponentName who) { 830 synchronized (this) { 831 long time = 0; 832 833 if (who != null) { 834 ActiveAdmin admin = getActiveAdminUncheckedLocked(who); 835 return admin != null ? admin.maximumTimeToUnlock : time; 836 } 837 838 final int N = mAdminList.size(); 839 for (int i=0; i<N; i++) { 840 ActiveAdmin admin = mAdminList.get(i); 841 if (time == 0) { 842 time = admin.maximumTimeToUnlock; 843 } else if (admin.maximumTimeToUnlock != 0 844 && time > admin.maximumTimeToUnlock) { 845 time = admin.maximumTimeToUnlock; 846 } 847 } 848 return time; 849 } 850 } 851 852 public void lockNow() { 853 synchronized (this) { 854 // This API can only be called by an active device admin, 855 // so try to retrieve it to check that the caller is one. 856 getActiveAdminForCallerLocked(null, 857 DeviceAdminInfo.USES_POLICY_FORCE_LOCK); 858 long ident = Binder.clearCallingIdentity(); 859 try { 860 mIPowerManager.goToSleepWithReason(SystemClock.uptimeMillis(), 861 WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN); 862 } catch (RemoteException e) { 863 } finally { 864 Binder.restoreCallingIdentity(ident); 865 } 866 } 867 } 868 869 void wipeDataLocked(int flags) { 870 if ((flags&DevicePolicyManager.WIPE_EXTERNAL_STORAGE) != 0) { 871 Intent intent = new Intent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET); 872 intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME); 873 mWakeLock.acquire(10000); 874 mContext.startService(intent); 875 } else { 876 try { 877 RecoverySystem.rebootWipeUserData(mContext); 878 } catch (IOException e) { 879 Slog.w(TAG, "Failed requesting data wipe", e); 880 } 881 } 882 } 883 884 public void wipeData(int flags) { 885 synchronized (this) { 886 // This API can only be called by an active device admin, 887 // so try to retrieve it to check that the caller is one. 888 getActiveAdminForCallerLocked(null, 889 DeviceAdminInfo.USES_POLICY_WIPE_DATA); 890 long ident = Binder.clearCallingIdentity(); 891 try { 892 wipeDataLocked(flags); 893 } finally { 894 Binder.restoreCallingIdentity(ident); 895 } 896 } 897 } 898 899 public void getRemoveWarning(ComponentName comp, final RemoteCallback result) { 900 mContext.enforceCallingOrSelfPermission( 901 android.Manifest.permission.BIND_DEVICE_ADMIN, null); 902 903 synchronized (this) { 904 ActiveAdmin admin = getActiveAdminUncheckedLocked(comp); 905 if (admin == null) { 906 try { 907 result.sendResult(null); 908 } catch (RemoteException e) { 909 } 910 return; 911 } 912 Intent intent = new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLE_REQUESTED); 913 intent.setComponent(admin.info.getComponent()); 914 mContext.sendOrderedBroadcast(intent, null, new BroadcastReceiver() { 915 @Override 916 public void onReceive(Context context, Intent intent) { 917 try { 918 result.sendResult(getResultExtras(false)); 919 } catch (RemoteException e) { 920 } 921 } 922 }, null, Activity.RESULT_OK, null, null); 923 } 924 } 925 926 public void setActivePasswordState(int quality, int length) { 927 mContext.enforceCallingOrSelfPermission( 928 android.Manifest.permission.BIND_DEVICE_ADMIN, null); 929 930 validateQualityConstant(quality); 931 932 synchronized (this) { 933 if (mActivePasswordQuality != quality || mActivePasswordLength != length 934 || mFailedPasswordAttempts != 0) { 935 long ident = Binder.clearCallingIdentity(); 936 try { 937 mActivePasswordQuality = quality; 938 mActivePasswordLength = length; 939 mFailedPasswordAttempts = 0; 940 saveSettingsLocked(); 941 sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED, 942 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); 943 } finally { 944 Binder.restoreCallingIdentity(ident); 945 } 946 } 947 } 948 } 949 950 public void reportFailedPasswordAttempt() { 951 mContext.enforceCallingOrSelfPermission( 952 android.Manifest.permission.BIND_DEVICE_ADMIN, null); 953 954 synchronized (this) { 955 long ident = Binder.clearCallingIdentity(); 956 try { 957 mFailedPasswordAttempts++; 958 saveSettingsLocked(); 959 int max = getMaximumFailedPasswordsForWipe(null); 960 if (max > 0 && mFailedPasswordAttempts >= max) { 961 wipeDataLocked(0); 962 } 963 sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_FAILED, 964 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN); 965 } finally { 966 Binder.restoreCallingIdentity(ident); 967 } 968 } 969 } 970 971 public void reportSuccessfulPasswordAttempt() { 972 mContext.enforceCallingOrSelfPermission( 973 android.Manifest.permission.BIND_DEVICE_ADMIN, null); 974 975 synchronized (this) { 976 if (mFailedPasswordAttempts != 0 || mPasswordOwner >= 0) { 977 long ident = Binder.clearCallingIdentity(); 978 try { 979 mFailedPasswordAttempts = 0; 980 mPasswordOwner = -1; 981 saveSettingsLocked(); 982 sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED, 983 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN); 984 } finally { 985 Binder.restoreCallingIdentity(ident); 986 } 987 } 988 } 989 } 990 991 @Override 992 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 993 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 994 != PackageManager.PERMISSION_GRANTED) { 995 996 pw.println("Permission Denial: can't dump DevicePolicyManagerService from from pid=" 997 + Binder.getCallingPid() 998 + ", uid=" + Binder.getCallingUid()); 999 return; 1000 } 1001 1002 final Printer p = new PrintWriterPrinter(pw); 1003 1004 synchronized (this) { 1005 p.println("Current Device Policy Manager state:"); 1006 1007 p.println(" Enabled Device Admins:"); 1008 final int N = mAdminList.size(); 1009 for (int i=0; i<N; i++) { 1010 ActiveAdmin ap = mAdminList.get(i); 1011 if (ap != null) { 1012 pw.print(" "); pw.print(ap.info.getComponent().flattenToShortString()); 1013 pw.println(":"); 1014 ap.dump(" ", pw); 1015 } 1016 } 1017 1018 pw.println(" "); 1019 pw.print(" mActivePasswordQuality=0x"); 1020 pw.println(Integer.toHexString(mActivePasswordQuality)); 1021 pw.print(" mActivePasswordLength="); pw.println(mActivePasswordLength); 1022 pw.print(" mFailedPasswordAttempts="); pw.println(mFailedPasswordAttempts); 1023 pw.print(" mPasswordOwner="); pw.println(mPasswordOwner); 1024 } 1025 } 1026 } 1027