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