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