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