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