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