1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.pm; 18 19 import static android.text.format.DateUtils.MINUTE_IN_MILLIS; 20 21 import android.app.Activity; 22 import android.app.ActivityManager; 23 import android.app.ActivityManagerNative; 24 import android.app.IStopUserCallback; 25 import android.content.BroadcastReceiver; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.content.pm.ApplicationInfo; 29 import android.content.pm.PackageManager; 30 import android.content.pm.PackageManager.NameNotFoundException; 31 import android.content.pm.UserInfo; 32 import android.graphics.Bitmap; 33 import android.graphics.BitmapFactory; 34 import android.os.Binder; 35 import android.os.Bundle; 36 import android.os.Debug; 37 import android.os.Environment; 38 import android.os.FileUtils; 39 import android.os.Handler; 40 import android.os.IUserManager; 41 import android.os.Process; 42 import android.os.RemoteException; 43 import android.os.ServiceManager; 44 import android.os.UserHandle; 45 import android.os.UserManager; 46 import android.util.AtomicFile; 47 import android.util.Log; 48 import android.util.Slog; 49 import android.util.SparseArray; 50 import android.util.SparseBooleanArray; 51 import android.util.TimeUtils; 52 import android.util.Xml; 53 54 import com.android.internal.app.IAppOpsService; 55 import com.android.internal.util.ArrayUtils; 56 import com.android.internal.util.FastXmlSerializer; 57 58 import org.xmlpull.v1.XmlPullParser; 59 import org.xmlpull.v1.XmlPullParserException; 60 import org.xmlpull.v1.XmlSerializer; 61 62 import java.io.BufferedOutputStream; 63 import java.io.File; 64 import java.io.FileDescriptor; 65 import java.io.FileInputStream; 66 import java.io.FileNotFoundException; 67 import java.io.FileOutputStream; 68 import java.io.IOException; 69 import java.io.PrintWriter; 70 import java.security.MessageDigest; 71 import java.security.NoSuchAlgorithmException; 72 import java.security.SecureRandom; 73 import java.util.ArrayList; 74 import java.util.List; 75 76 public class UserManagerService extends IUserManager.Stub { 77 78 private static final String LOG_TAG = "UserManagerService"; 79 80 private static final boolean DBG = false; 81 82 private static final String TAG_NAME = "name"; 83 private static final String ATTR_FLAGS = "flags"; 84 private static final String ATTR_ICON_PATH = "icon"; 85 private static final String ATTR_ID = "id"; 86 private static final String ATTR_CREATION_TIME = "created"; 87 private static final String ATTR_LAST_LOGGED_IN_TIME = "lastLoggedIn"; 88 private static final String ATTR_SALT = "salt"; 89 private static final String ATTR_PIN_HASH = "pinHash"; 90 private static final String ATTR_FAILED_ATTEMPTS = "failedAttempts"; 91 private static final String ATTR_LAST_RETRY_MS = "lastAttemptMs"; 92 private static final String ATTR_SERIAL_NO = "serialNumber"; 93 private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber"; 94 private static final String ATTR_PARTIAL = "partial"; 95 private static final String ATTR_GUEST_TO_REMOVE = "guestToRemove"; 96 private static final String ATTR_USER_VERSION = "version"; 97 private static final String ATTR_PROFILE_GROUP_ID = "profileGroupId"; 98 private static final String TAG_GUEST_RESTRICTIONS = "guestRestrictions"; 99 private static final String TAG_USERS = "users"; 100 private static final String TAG_USER = "user"; 101 private static final String TAG_RESTRICTIONS = "restrictions"; 102 private static final String TAG_ENTRY = "entry"; 103 private static final String TAG_VALUE = "value"; 104 private static final String ATTR_KEY = "key"; 105 private static final String ATTR_VALUE_TYPE = "type"; 106 private static final String ATTR_MULTIPLE = "m"; 107 108 private static final String ATTR_TYPE_STRING_ARRAY = "sa"; 109 private static final String ATTR_TYPE_STRING = "s"; 110 private static final String ATTR_TYPE_BOOLEAN = "b"; 111 private static final String ATTR_TYPE_INTEGER = "i"; 112 113 private static final String USER_INFO_DIR = "system" + File.separator + "users"; 114 private static final String USER_LIST_FILENAME = "userlist.xml"; 115 private static final String USER_PHOTO_FILENAME = "photo.png"; 116 117 private static final String RESTRICTIONS_FILE_PREFIX = "res_"; 118 private static final String XML_SUFFIX = ".xml"; 119 120 private static final int MIN_USER_ID = 10; 121 122 private static final int USER_VERSION = 5; 123 124 private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // ms 125 126 // Number of attempts before jumping to the next BACKOFF_TIMES slot 127 private static final int BACKOFF_INC_INTERVAL = 5; 128 129 // Maximum number of managed profiles permitted is 1. This cannot be increased 130 // without first making sure that the rest of the framework is prepared for it. 131 private static final int MAX_MANAGED_PROFILES = 1; 132 133 // Amount of time to force the user to wait before entering the PIN again, after failing 134 // BACKOFF_INC_INTERVAL times. 135 private static final int[] BACKOFF_TIMES = { 0, 30*1000, 60*1000, 5*60*1000, 30*60*1000 }; 136 137 138 private final Context mContext; 139 private final PackageManagerService mPm; 140 private final Object mInstallLock; 141 private final Object mPackagesLock; 142 143 private final Handler mHandler; 144 145 private final File mUsersDir; 146 private final File mUserListFile; 147 private final File mBaseUserPath; 148 149 private final SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>(); 150 private final SparseArray<Bundle> mUserRestrictions = new SparseArray<Bundle>(); 151 private final Bundle mGuestRestrictions = new Bundle(); 152 153 class RestrictionsPinState { 154 long salt; 155 String pinHash; 156 int failedAttempts; 157 long lastAttemptTime; 158 } 159 160 private final SparseArray<RestrictionsPinState> mRestrictionsPinStates = 161 new SparseArray<RestrictionsPinState>(); 162 163 /** 164 * Set of user IDs being actively removed. Removed IDs linger in this set 165 * for several seconds to work around a VFS caching issue. 166 */ 167 // @GuardedBy("mPackagesLock") 168 private final SparseBooleanArray mRemovingUserIds = new SparseBooleanArray(); 169 170 private int[] mUserIds; 171 private int mNextSerialNumber; 172 private int mUserVersion = 0; 173 174 private IAppOpsService mAppOpsService; 175 176 private static UserManagerService sInstance; 177 getInstance()178 public static UserManagerService getInstance() { 179 synchronized (UserManagerService.class) { 180 return sInstance; 181 } 182 } 183 184 /** 185 * Available for testing purposes. 186 */ UserManagerService(File dataDir, File baseUserPath)187 UserManagerService(File dataDir, File baseUserPath) { 188 this(null, null, new Object(), new Object(), dataDir, baseUserPath); 189 } 190 191 /** 192 * Called by package manager to create the service. This is closely 193 * associated with the package manager, and the given lock is the 194 * package manager's own lock. 195 */ UserManagerService(Context context, PackageManagerService pm, Object installLock, Object packagesLock)196 UserManagerService(Context context, PackageManagerService pm, 197 Object installLock, Object packagesLock) { 198 this(context, pm, installLock, packagesLock, 199 Environment.getDataDirectory(), 200 new File(Environment.getDataDirectory(), "user")); 201 } 202 203 /** 204 * Available for testing purposes. 205 */ UserManagerService(Context context, PackageManagerService pm, Object installLock, Object packagesLock, File dataDir, File baseUserPath)206 private UserManagerService(Context context, PackageManagerService pm, 207 Object installLock, Object packagesLock, 208 File dataDir, File baseUserPath) { 209 mContext = context; 210 mPm = pm; 211 mInstallLock = installLock; 212 mPackagesLock = packagesLock; 213 mHandler = new Handler(); 214 synchronized (mInstallLock) { 215 synchronized (mPackagesLock) { 216 mUsersDir = new File(dataDir, USER_INFO_DIR); 217 mUsersDir.mkdirs(); 218 // Make zeroth user directory, for services to migrate their files to that location 219 File userZeroDir = new File(mUsersDir, "0"); 220 userZeroDir.mkdirs(); 221 mBaseUserPath = baseUserPath; 222 FileUtils.setPermissions(mUsersDir.toString(), 223 FileUtils.S_IRWXU|FileUtils.S_IRWXG 224 |FileUtils.S_IROTH|FileUtils.S_IXOTH, 225 -1, -1); 226 mUserListFile = new File(mUsersDir, USER_LIST_FILENAME); 227 initDefaultGuestRestrictions(); 228 readUserListLocked(); 229 // Prune out any partially created/partially removed users. 230 ArrayList<UserInfo> partials = new ArrayList<UserInfo>(); 231 for (int i = 0; i < mUsers.size(); i++) { 232 UserInfo ui = mUsers.valueAt(i); 233 if ((ui.partial || ui.guestToRemove) && i != 0) { 234 partials.add(ui); 235 } 236 } 237 for (int i = 0; i < partials.size(); i++) { 238 UserInfo ui = partials.get(i); 239 Slog.w(LOG_TAG, "Removing partially created user #" + i 240 + " (name=" + ui.name + ")"); 241 removeUserStateLocked(ui.id); 242 } 243 sInstance = this; 244 } 245 } 246 } 247 systemReady()248 void systemReady() { 249 userForeground(UserHandle.USER_OWNER); 250 mAppOpsService = IAppOpsService.Stub.asInterface( 251 ServiceManager.getService(Context.APP_OPS_SERVICE)); 252 for (int i = 0; i < mUserIds.length; ++i) { 253 try { 254 mAppOpsService.setUserRestrictions(mUserRestrictions.get(mUserIds[i]), mUserIds[i]); 255 } catch (RemoteException e) { 256 Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions"); 257 } 258 } 259 } 260 261 @Override getUsers(boolean excludeDying)262 public List<UserInfo> getUsers(boolean excludeDying) { 263 checkManageUsersPermission("query users"); 264 synchronized (mPackagesLock) { 265 ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size()); 266 for (int i = 0; i < mUsers.size(); i++) { 267 UserInfo ui = mUsers.valueAt(i); 268 if (ui.partial) { 269 continue; 270 } 271 if (!excludeDying || !mRemovingUserIds.get(ui.id)) { 272 users.add(ui); 273 } 274 } 275 return users; 276 } 277 } 278 279 @Override getProfiles(int userId, boolean enabledOnly)280 public List<UserInfo> getProfiles(int userId, boolean enabledOnly) { 281 if (userId != UserHandle.getCallingUserId()) { 282 checkManageUsersPermission("getting profiles related to user " + userId); 283 } 284 final long ident = Binder.clearCallingIdentity(); 285 try { 286 synchronized (mPackagesLock) { 287 return getProfilesLocked(userId, enabledOnly); 288 } 289 } finally { 290 Binder.restoreCallingIdentity(ident); 291 } 292 } 293 294 /** Assume permissions already checked and caller's identity cleared */ getProfilesLocked(int userId, boolean enabledOnly)295 private List<UserInfo> getProfilesLocked(int userId, boolean enabledOnly) { 296 UserInfo user = getUserInfoLocked(userId); 297 ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size()); 298 if (user == null) { 299 // Probably a dying user 300 return users; 301 } 302 for (int i = 0; i < mUsers.size(); i++) { 303 UserInfo profile = mUsers.valueAt(i); 304 if (!isProfileOf(user, profile)) { 305 continue; 306 } 307 if (enabledOnly && !profile.isEnabled()) { 308 continue; 309 } 310 if (mRemovingUserIds.get(profile.id)) { 311 continue; 312 } 313 users.add(profile); 314 } 315 return users; 316 } 317 318 @Override getProfileParent(int userHandle)319 public UserInfo getProfileParent(int userHandle) { 320 checkManageUsersPermission("get the profile parent"); 321 synchronized (mPackagesLock) { 322 UserInfo profile = getUserInfoLocked(userHandle); 323 if (profile == null) { 324 return null; 325 } 326 int parentUserId = profile.profileGroupId; 327 if (parentUserId == UserInfo.NO_PROFILE_GROUP_ID) { 328 return null; 329 } else { 330 return getUserInfoLocked(parentUserId); 331 } 332 } 333 } 334 isProfileOf(UserInfo user, UserInfo profile)335 private boolean isProfileOf(UserInfo user, UserInfo profile) { 336 return user.id == profile.id || 337 (user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID 338 && user.profileGroupId == profile.profileGroupId); 339 } 340 341 @Override setUserEnabled(int userId)342 public void setUserEnabled(int userId) { 343 checkManageUsersPermission("enable user"); 344 synchronized (mPackagesLock) { 345 UserInfo info = getUserInfoLocked(userId); 346 if (info != null && !info.isEnabled()) { 347 info.flags ^= UserInfo.FLAG_DISABLED; 348 writeUserLocked(info); 349 } 350 } 351 } 352 353 @Override getUserInfo(int userId)354 public UserInfo getUserInfo(int userId) { 355 checkManageUsersPermission("query user"); 356 synchronized (mPackagesLock) { 357 return getUserInfoLocked(userId); 358 } 359 } 360 361 @Override isRestricted()362 public boolean isRestricted() { 363 synchronized (mPackagesLock) { 364 return getUserInfoLocked(UserHandle.getCallingUserId()).isRestricted(); 365 } 366 } 367 368 /* 369 * Should be locked on mUsers before calling this. 370 */ getUserInfoLocked(int userId)371 private UserInfo getUserInfoLocked(int userId) { 372 UserInfo ui = mUsers.get(userId); 373 // If it is partial and not in the process of being removed, return as unknown user. 374 if (ui != null && ui.partial && !mRemovingUserIds.get(userId)) { 375 Slog.w(LOG_TAG, "getUserInfo: unknown user #" + userId); 376 return null; 377 } 378 return ui; 379 } 380 exists(int userId)381 public boolean exists(int userId) { 382 synchronized (mPackagesLock) { 383 return ArrayUtils.contains(mUserIds, userId); 384 } 385 } 386 387 @Override setUserName(int userId, String name)388 public void setUserName(int userId, String name) { 389 checkManageUsersPermission("rename users"); 390 boolean changed = false; 391 synchronized (mPackagesLock) { 392 UserInfo info = mUsers.get(userId); 393 if (info == null || info.partial) { 394 Slog.w(LOG_TAG, "setUserName: unknown user #" + userId); 395 return; 396 } 397 if (name != null && !name.equals(info.name)) { 398 info.name = name; 399 writeUserLocked(info); 400 changed = true; 401 } 402 } 403 if (changed) { 404 sendUserInfoChangedBroadcast(userId); 405 } 406 } 407 408 @Override setUserIcon(int userId, Bitmap bitmap)409 public void setUserIcon(int userId, Bitmap bitmap) { 410 checkManageUsersPermission("update users"); 411 long ident = Binder.clearCallingIdentity(); 412 try { 413 synchronized (mPackagesLock) { 414 UserInfo info = mUsers.get(userId); 415 if (info == null || info.partial) { 416 Slog.w(LOG_TAG, "setUserIcon: unknown user #" + userId); 417 return; 418 } 419 writeBitmapLocked(info, bitmap); 420 writeUserLocked(info); 421 } 422 sendUserInfoChangedBroadcast(userId); 423 } finally { 424 Binder.restoreCallingIdentity(ident); 425 } 426 } 427 sendUserInfoChangedBroadcast(int userId)428 private void sendUserInfoChangedBroadcast(int userId) { 429 Intent changedIntent = new Intent(Intent.ACTION_USER_INFO_CHANGED); 430 changedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId); 431 changedIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 432 mContext.sendBroadcastAsUser(changedIntent, UserHandle.ALL); 433 } 434 435 @Override getUserIcon(int userId)436 public Bitmap getUserIcon(int userId) { 437 synchronized (mPackagesLock) { 438 UserInfo info = mUsers.get(userId); 439 if (info == null || info.partial) { 440 Slog.w(LOG_TAG, "getUserIcon: unknown user #" + userId); 441 return null; 442 } 443 int callingGroupId = mUsers.get(UserHandle.getCallingUserId()).profileGroupId; 444 if (callingGroupId == UserInfo.NO_PROFILE_GROUP_ID 445 || callingGroupId != info.profileGroupId) { 446 checkManageUsersPermission("get the icon of a user who is not related"); 447 } 448 if (info.iconPath == null) { 449 return null; 450 } 451 return BitmapFactory.decodeFile(info.iconPath); 452 } 453 } 454 makeInitialized(int userId)455 public void makeInitialized(int userId) { 456 checkManageUsersPermission("makeInitialized"); 457 synchronized (mPackagesLock) { 458 UserInfo info = mUsers.get(userId); 459 if (info == null || info.partial) { 460 Slog.w(LOG_TAG, "makeInitialized: unknown user #" + userId); 461 } 462 if ((info.flags&UserInfo.FLAG_INITIALIZED) == 0) { 463 info.flags |= UserInfo.FLAG_INITIALIZED; 464 writeUserLocked(info); 465 } 466 } 467 } 468 469 /** 470 * If default guest restrictions haven't been initialized yet, add the basic 471 * restrictions. 472 */ initDefaultGuestRestrictions()473 private void initDefaultGuestRestrictions() { 474 if (mGuestRestrictions.isEmpty()) { 475 mGuestRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, true); 476 mGuestRestrictions.putBoolean(UserManager.DISALLOW_SMS, true); 477 } 478 } 479 480 @Override getDefaultGuestRestrictions()481 public Bundle getDefaultGuestRestrictions() { 482 checkManageUsersPermission("getDefaultGuestRestrictions"); 483 synchronized (mPackagesLock) { 484 return new Bundle(mGuestRestrictions); 485 } 486 } 487 488 @Override setDefaultGuestRestrictions(Bundle restrictions)489 public void setDefaultGuestRestrictions(Bundle restrictions) { 490 checkManageUsersPermission("setDefaultGuestRestrictions"); 491 synchronized (mPackagesLock) { 492 mGuestRestrictions.clear(); 493 mGuestRestrictions.putAll(restrictions); 494 writeUserListLocked(); 495 } 496 } 497 498 @Override hasUserRestriction(String restrictionKey, int userId)499 public boolean hasUserRestriction(String restrictionKey, int userId) { 500 synchronized (mPackagesLock) { 501 Bundle restrictions = mUserRestrictions.get(userId); 502 return restrictions != null ? restrictions.getBoolean(restrictionKey) : false; 503 } 504 } 505 506 @Override getUserRestrictions(int userId)507 public Bundle getUserRestrictions(int userId) { 508 // checkManageUsersPermission("getUserRestrictions"); 509 510 synchronized (mPackagesLock) { 511 Bundle restrictions = mUserRestrictions.get(userId); 512 return restrictions != null ? new Bundle(restrictions) : new Bundle(); 513 } 514 } 515 516 @Override setUserRestrictions(Bundle restrictions, int userId)517 public void setUserRestrictions(Bundle restrictions, int userId) { 518 checkManageUsersPermission("setUserRestrictions"); 519 if (restrictions == null) return; 520 521 synchronized (mPackagesLock) { 522 mUserRestrictions.get(userId).clear(); 523 mUserRestrictions.get(userId).putAll(restrictions); 524 long token = Binder.clearCallingIdentity(); 525 try { 526 mAppOpsService.setUserRestrictions(mUserRestrictions.get(userId), userId); 527 } catch (RemoteException e) { 528 Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions"); 529 } finally { 530 Binder.restoreCallingIdentity(token); 531 } 532 writeUserLocked(mUsers.get(userId)); 533 } 534 } 535 536 /** 537 * Check if we've hit the limit of how many users can be created. 538 */ isUserLimitReachedLocked()539 private boolean isUserLimitReachedLocked() { 540 int aliveUserCount = 0; 541 final int totalUserCount = mUsers.size(); 542 // Skip over users being removed 543 for (int i = 0; i < totalUserCount; i++) { 544 UserInfo user = mUsers.valueAt(i); 545 if (!mRemovingUserIds.get(user.id) 546 && !user.isGuest() && !user.partial) { 547 aliveUserCount++; 548 } 549 } 550 return aliveUserCount >= UserManager.getMaxSupportedUsers(); 551 } 552 553 /** 554 * Enforces that only the system UID or root's UID or apps that have the 555 * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} 556 * permission can make certain calls to the UserManager. 557 * 558 * @param message used as message if SecurityException is thrown 559 * @throws SecurityException if the caller is not system or root 560 */ checkManageUsersPermission(String message)561 private static final void checkManageUsersPermission(String message) { 562 final int uid = Binder.getCallingUid(); 563 if (uid != Process.SYSTEM_UID && uid != 0 564 && ActivityManager.checkComponentPermission( 565 android.Manifest.permission.MANAGE_USERS, 566 uid, -1, true) != PackageManager.PERMISSION_GRANTED) { 567 throw new SecurityException("You need MANAGE_USERS permission to: " + message); 568 } 569 } 570 writeBitmapLocked(UserInfo info, Bitmap bitmap)571 private void writeBitmapLocked(UserInfo info, Bitmap bitmap) { 572 try { 573 File dir = new File(mUsersDir, Integer.toString(info.id)); 574 File file = new File(dir, USER_PHOTO_FILENAME); 575 if (!dir.exists()) { 576 dir.mkdir(); 577 FileUtils.setPermissions( 578 dir.getPath(), 579 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH, 580 -1, -1); 581 } 582 FileOutputStream os; 583 if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, os = new FileOutputStream(file))) { 584 info.iconPath = file.getAbsolutePath(); 585 } 586 try { 587 os.close(); 588 } catch (IOException ioe) { 589 // What the ... ! 590 } 591 } catch (FileNotFoundException e) { 592 Slog.w(LOG_TAG, "Error setting photo for user ", e); 593 } 594 } 595 596 /** 597 * Returns an array of user ids. This array is cached here for quick access, so do not modify or 598 * cache it elsewhere. 599 * @return the array of user ids. 600 */ getUserIds()601 public int[] getUserIds() { 602 synchronized (mPackagesLock) { 603 return mUserIds; 604 } 605 } 606 getUserIdsLPr()607 int[] getUserIdsLPr() { 608 return mUserIds; 609 } 610 readUserListLocked()611 private void readUserListLocked() { 612 if (!mUserListFile.exists()) { 613 fallbackToSingleUserLocked(); 614 return; 615 } 616 FileInputStream fis = null; 617 AtomicFile userListFile = new AtomicFile(mUserListFile); 618 try { 619 fis = userListFile.openRead(); 620 XmlPullParser parser = Xml.newPullParser(); 621 parser.setInput(fis, null); 622 int type; 623 while ((type = parser.next()) != XmlPullParser.START_TAG 624 && type != XmlPullParser.END_DOCUMENT) { 625 ; 626 } 627 628 if (type != XmlPullParser.START_TAG) { 629 Slog.e(LOG_TAG, "Unable to read user list"); 630 fallbackToSingleUserLocked(); 631 return; 632 } 633 634 mNextSerialNumber = -1; 635 if (parser.getName().equals(TAG_USERS)) { 636 String lastSerialNumber = parser.getAttributeValue(null, ATTR_NEXT_SERIAL_NO); 637 if (lastSerialNumber != null) { 638 mNextSerialNumber = Integer.parseInt(lastSerialNumber); 639 } 640 String versionNumber = parser.getAttributeValue(null, ATTR_USER_VERSION); 641 if (versionNumber != null) { 642 mUserVersion = Integer.parseInt(versionNumber); 643 } 644 } 645 646 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { 647 if (type == XmlPullParser.START_TAG) { 648 final String name = parser.getName(); 649 if (name.equals(TAG_USER)) { 650 String id = parser.getAttributeValue(null, ATTR_ID); 651 UserInfo user = readUserLocked(Integer.parseInt(id)); 652 653 if (user != null) { 654 mUsers.put(user.id, user); 655 if (mNextSerialNumber < 0 || mNextSerialNumber <= user.id) { 656 mNextSerialNumber = user.id + 1; 657 } 658 } 659 } else if (name.equals(TAG_GUEST_RESTRICTIONS)) { 660 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 661 && type != XmlPullParser.END_TAG) { 662 if (type == XmlPullParser.START_TAG) { 663 if (parser.getName().equals(TAG_RESTRICTIONS)) { 664 readRestrictionsLocked(parser, mGuestRestrictions); 665 } 666 break; 667 } 668 } 669 } 670 } 671 } 672 updateUserIdsLocked(); 673 upgradeIfNecessaryLocked(); 674 } catch (IOException ioe) { 675 fallbackToSingleUserLocked(); 676 } catch (XmlPullParserException pe) { 677 fallbackToSingleUserLocked(); 678 } finally { 679 if (fis != null) { 680 try { 681 fis.close(); 682 } catch (IOException e) { 683 } 684 } 685 } 686 } 687 688 /** 689 * Upgrade steps between versions, either for fixing bugs or changing the data format. 690 */ upgradeIfNecessaryLocked()691 private void upgradeIfNecessaryLocked() { 692 int userVersion = mUserVersion; 693 if (userVersion < 1) { 694 // Assign a proper name for the owner, if not initialized correctly before 695 UserInfo user = mUsers.get(UserHandle.USER_OWNER); 696 if ("Primary".equals(user.name)) { 697 user.name = mContext.getResources().getString(com.android.internal.R.string.owner_name); 698 writeUserLocked(user); 699 } 700 userVersion = 1; 701 } 702 703 if (userVersion < 2) { 704 // Owner should be marked as initialized 705 UserInfo user = mUsers.get(UserHandle.USER_OWNER); 706 if ((user.flags & UserInfo.FLAG_INITIALIZED) == 0) { 707 user.flags |= UserInfo.FLAG_INITIALIZED; 708 writeUserLocked(user); 709 } 710 userVersion = 2; 711 } 712 713 714 if (userVersion < 4) { 715 userVersion = 4; 716 } 717 718 if (userVersion < 5) { 719 initDefaultGuestRestrictions(); 720 userVersion = 5; 721 } 722 723 if (userVersion < USER_VERSION) { 724 Slog.w(LOG_TAG, "User version " + mUserVersion + " didn't upgrade as expected to " 725 + USER_VERSION); 726 } else { 727 mUserVersion = userVersion; 728 writeUserListLocked(); 729 } 730 } 731 fallbackToSingleUserLocked()732 private void fallbackToSingleUserLocked() { 733 // Create the primary user 734 UserInfo primary = new UserInfo(UserHandle.USER_OWNER, 735 mContext.getResources().getString(com.android.internal.R.string.owner_name), null, 736 UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY | UserInfo.FLAG_INITIALIZED); 737 mUsers.put(0, primary); 738 mNextSerialNumber = MIN_USER_ID; 739 mUserVersion = USER_VERSION; 740 741 Bundle restrictions = new Bundle(); 742 mUserRestrictions.append(UserHandle.USER_OWNER, restrictions); 743 744 updateUserIdsLocked(); 745 initDefaultGuestRestrictions(); 746 747 writeUserListLocked(); 748 writeUserLocked(primary); 749 } 750 751 /* 752 * Writes the user file in this format: 753 * 754 * <user flags="20039023" id="0"> 755 * <name>Primary</name> 756 * </user> 757 */ writeUserLocked(UserInfo userInfo)758 private void writeUserLocked(UserInfo userInfo) { 759 FileOutputStream fos = null; 760 AtomicFile userFile = new AtomicFile(new File(mUsersDir, userInfo.id + XML_SUFFIX)); 761 try { 762 fos = userFile.startWrite(); 763 final BufferedOutputStream bos = new BufferedOutputStream(fos); 764 765 // XmlSerializer serializer = XmlUtils.serializerInstance(); 766 final XmlSerializer serializer = new FastXmlSerializer(); 767 serializer.setOutput(bos, "utf-8"); 768 serializer.startDocument(null, true); 769 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); 770 771 serializer.startTag(null, TAG_USER); 772 serializer.attribute(null, ATTR_ID, Integer.toString(userInfo.id)); 773 serializer.attribute(null, ATTR_SERIAL_NO, Integer.toString(userInfo.serialNumber)); 774 serializer.attribute(null, ATTR_FLAGS, Integer.toString(userInfo.flags)); 775 serializer.attribute(null, ATTR_CREATION_TIME, Long.toString(userInfo.creationTime)); 776 serializer.attribute(null, ATTR_LAST_LOGGED_IN_TIME, 777 Long.toString(userInfo.lastLoggedInTime)); 778 RestrictionsPinState pinState = mRestrictionsPinStates.get(userInfo.id); 779 if (pinState != null) { 780 if (pinState.salt != 0) { 781 serializer.attribute(null, ATTR_SALT, Long.toString(pinState.salt)); 782 } 783 if (pinState.pinHash != null) { 784 serializer.attribute(null, ATTR_PIN_HASH, pinState.pinHash); 785 } 786 if (pinState.failedAttempts != 0) { 787 serializer.attribute(null, ATTR_FAILED_ATTEMPTS, 788 Integer.toString(pinState.failedAttempts)); 789 serializer.attribute(null, ATTR_LAST_RETRY_MS, 790 Long.toString(pinState.lastAttemptTime)); 791 } 792 } 793 if (userInfo.iconPath != null) { 794 serializer.attribute(null, ATTR_ICON_PATH, userInfo.iconPath); 795 } 796 if (userInfo.partial) { 797 serializer.attribute(null, ATTR_PARTIAL, "true"); 798 } 799 if (userInfo.guestToRemove) { 800 serializer.attribute(null, ATTR_GUEST_TO_REMOVE, "true"); 801 } 802 if (userInfo.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID) { 803 serializer.attribute(null, ATTR_PROFILE_GROUP_ID, 804 Integer.toString(userInfo.profileGroupId)); 805 } 806 807 serializer.startTag(null, TAG_NAME); 808 serializer.text(userInfo.name); 809 serializer.endTag(null, TAG_NAME); 810 Bundle restrictions = mUserRestrictions.get(userInfo.id); 811 if (restrictions != null) { 812 writeRestrictionsLocked(serializer, restrictions); 813 } 814 serializer.endTag(null, TAG_USER); 815 816 serializer.endDocument(); 817 userFile.finishWrite(fos); 818 } catch (Exception ioe) { 819 Slog.e(LOG_TAG, "Error writing user info " + userInfo.id + "\n" + ioe); 820 userFile.failWrite(fos); 821 } 822 } 823 824 /* 825 * Writes the user list file in this format: 826 * 827 * <users nextSerialNumber="3"> 828 * <user id="0"></user> 829 * <user id="2"></user> 830 * </users> 831 */ writeUserListLocked()832 private void writeUserListLocked() { 833 FileOutputStream fos = null; 834 AtomicFile userListFile = new AtomicFile(mUserListFile); 835 try { 836 fos = userListFile.startWrite(); 837 final BufferedOutputStream bos = new BufferedOutputStream(fos); 838 839 // XmlSerializer serializer = XmlUtils.serializerInstance(); 840 final XmlSerializer serializer = new FastXmlSerializer(); 841 serializer.setOutput(bos, "utf-8"); 842 serializer.startDocument(null, true); 843 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); 844 845 serializer.startTag(null, TAG_USERS); 846 serializer.attribute(null, ATTR_NEXT_SERIAL_NO, Integer.toString(mNextSerialNumber)); 847 serializer.attribute(null, ATTR_USER_VERSION, Integer.toString(mUserVersion)); 848 849 serializer.startTag(null, TAG_GUEST_RESTRICTIONS); 850 writeRestrictionsLocked(serializer, mGuestRestrictions); 851 serializer.endTag(null, TAG_GUEST_RESTRICTIONS); 852 for (int i = 0; i < mUsers.size(); i++) { 853 UserInfo user = mUsers.valueAt(i); 854 serializer.startTag(null, TAG_USER); 855 serializer.attribute(null, ATTR_ID, Integer.toString(user.id)); 856 serializer.endTag(null, TAG_USER); 857 } 858 859 serializer.endTag(null, TAG_USERS); 860 861 serializer.endDocument(); 862 userListFile.finishWrite(fos); 863 } catch (Exception e) { 864 userListFile.failWrite(fos); 865 Slog.e(LOG_TAG, "Error writing user list"); 866 } 867 } 868 writeRestrictionsLocked(XmlSerializer serializer, Bundle restrictions)869 private void writeRestrictionsLocked(XmlSerializer serializer, Bundle restrictions) 870 throws IOException { 871 serializer.startTag(null, TAG_RESTRICTIONS); 872 writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_WIFI); 873 writeBoolean(serializer, restrictions, UserManager.DISALLOW_MODIFY_ACCOUNTS); 874 writeBoolean(serializer, restrictions, UserManager.DISALLOW_INSTALL_APPS); 875 writeBoolean(serializer, restrictions, UserManager.DISALLOW_UNINSTALL_APPS); 876 writeBoolean(serializer, restrictions, UserManager.DISALLOW_SHARE_LOCATION); 877 writeBoolean(serializer, restrictions, 878 UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES); 879 writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_BLUETOOTH); 880 writeBoolean(serializer, restrictions, UserManager.DISALLOW_USB_FILE_TRANSFER); 881 writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_CREDENTIALS); 882 writeBoolean(serializer, restrictions, UserManager.DISALLOW_REMOVE_USER); 883 writeBoolean(serializer, restrictions, UserManager.DISALLOW_DEBUGGING_FEATURES); 884 writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_VPN); 885 writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_TETHERING); 886 writeBoolean(serializer, restrictions, UserManager.DISALLOW_FACTORY_RESET); 887 writeBoolean(serializer, restrictions, UserManager.DISALLOW_ADD_USER); 888 writeBoolean(serializer, restrictions, UserManager.ENSURE_VERIFY_APPS); 889 writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_CELL_BROADCASTS); 890 writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS); 891 writeBoolean(serializer, restrictions, UserManager.DISALLOW_APPS_CONTROL); 892 writeBoolean(serializer, restrictions, UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA); 893 writeBoolean(serializer, restrictions, UserManager.DISALLOW_UNMUTE_MICROPHONE); 894 writeBoolean(serializer, restrictions, UserManager.DISALLOW_ADJUST_VOLUME); 895 writeBoolean(serializer, restrictions, UserManager.DISALLOW_OUTGOING_CALLS); 896 writeBoolean(serializer, restrictions, UserManager.DISALLOW_SMS); 897 writeBoolean(serializer, restrictions, UserManager.DISALLOW_CREATE_WINDOWS); 898 writeBoolean(serializer, restrictions, UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE); 899 writeBoolean(serializer, restrictions, UserManager.DISALLOW_OUTGOING_BEAM); 900 serializer.endTag(null, TAG_RESTRICTIONS); 901 } 902 readUserLocked(int id)903 private UserInfo readUserLocked(int id) { 904 int flags = 0; 905 int serialNumber = id; 906 String name = null; 907 String iconPath = null; 908 long creationTime = 0L; 909 long lastLoggedInTime = 0L; 910 long salt = 0L; 911 String pinHash = null; 912 int failedAttempts = 0; 913 int profileGroupId = UserInfo.NO_PROFILE_GROUP_ID; 914 long lastAttemptTime = 0L; 915 boolean partial = false; 916 boolean guestToRemove = false; 917 Bundle restrictions = new Bundle(); 918 919 FileInputStream fis = null; 920 try { 921 AtomicFile userFile = 922 new AtomicFile(new File(mUsersDir, Integer.toString(id) + XML_SUFFIX)); 923 fis = userFile.openRead(); 924 XmlPullParser parser = Xml.newPullParser(); 925 parser.setInput(fis, null); 926 int type; 927 while ((type = parser.next()) != XmlPullParser.START_TAG 928 && type != XmlPullParser.END_DOCUMENT) { 929 ; 930 } 931 932 if (type != XmlPullParser.START_TAG) { 933 Slog.e(LOG_TAG, "Unable to read user " + id); 934 return null; 935 } 936 937 if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_USER)) { 938 int storedId = readIntAttribute(parser, ATTR_ID, -1); 939 if (storedId != id) { 940 Slog.e(LOG_TAG, "User id does not match the file name"); 941 return null; 942 } 943 serialNumber = readIntAttribute(parser, ATTR_SERIAL_NO, id); 944 flags = readIntAttribute(parser, ATTR_FLAGS, 0); 945 iconPath = parser.getAttributeValue(null, ATTR_ICON_PATH); 946 creationTime = readLongAttribute(parser, ATTR_CREATION_TIME, 0); 947 lastLoggedInTime = readLongAttribute(parser, ATTR_LAST_LOGGED_IN_TIME, 0); 948 salt = readLongAttribute(parser, ATTR_SALT, 0L); 949 pinHash = parser.getAttributeValue(null, ATTR_PIN_HASH); 950 failedAttempts = readIntAttribute(parser, ATTR_FAILED_ATTEMPTS, 0); 951 lastAttemptTime = readLongAttribute(parser, ATTR_LAST_RETRY_MS, 0L); 952 profileGroupId = readIntAttribute(parser, ATTR_PROFILE_GROUP_ID, 953 UserInfo.NO_PROFILE_GROUP_ID); 954 if (profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) { 955 // This attribute was added and renamed during development of L. 956 // TODO Remove upgrade path by 1st May 2014 957 profileGroupId = readIntAttribute(parser, "relatedGroupId", 958 UserInfo.NO_PROFILE_GROUP_ID); 959 } 960 String valueString = parser.getAttributeValue(null, ATTR_PARTIAL); 961 if ("true".equals(valueString)) { 962 partial = true; 963 } 964 valueString = parser.getAttributeValue(null, ATTR_GUEST_TO_REMOVE); 965 if ("true".equals(valueString)) { 966 guestToRemove = true; 967 } 968 969 int outerDepth = parser.getDepth(); 970 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 971 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 972 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 973 continue; 974 } 975 String tag = parser.getName(); 976 if (TAG_NAME.equals(tag)) { 977 type = parser.next(); 978 if (type == XmlPullParser.TEXT) { 979 name = parser.getText(); 980 } 981 } else if (TAG_RESTRICTIONS.equals(tag)) { 982 readRestrictionsLocked(parser, restrictions); 983 } 984 } 985 } 986 987 UserInfo userInfo = new UserInfo(id, name, iconPath, flags); 988 userInfo.serialNumber = serialNumber; 989 userInfo.creationTime = creationTime; 990 userInfo.lastLoggedInTime = lastLoggedInTime; 991 userInfo.partial = partial; 992 userInfo.guestToRemove = guestToRemove; 993 userInfo.profileGroupId = profileGroupId; 994 mUserRestrictions.append(id, restrictions); 995 if (salt != 0L) { 996 RestrictionsPinState pinState = mRestrictionsPinStates.get(id); 997 if (pinState == null) { 998 pinState = new RestrictionsPinState(); 999 mRestrictionsPinStates.put(id, pinState); 1000 } 1001 pinState.salt = salt; 1002 pinState.pinHash = pinHash; 1003 pinState.failedAttempts = failedAttempts; 1004 pinState.lastAttemptTime = lastAttemptTime; 1005 } 1006 return userInfo; 1007 1008 } catch (IOException ioe) { 1009 } catch (XmlPullParserException pe) { 1010 } finally { 1011 if (fis != null) { 1012 try { 1013 fis.close(); 1014 } catch (IOException e) { 1015 } 1016 } 1017 } 1018 return null; 1019 } 1020 readRestrictionsLocked(XmlPullParser parser, Bundle restrictions)1021 private void readRestrictionsLocked(XmlPullParser parser, Bundle restrictions) 1022 throws IOException { 1023 readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_WIFI); 1024 readBoolean(parser, restrictions, UserManager.DISALLOW_MODIFY_ACCOUNTS); 1025 readBoolean(parser, restrictions, UserManager.DISALLOW_INSTALL_APPS); 1026 readBoolean(parser, restrictions, UserManager.DISALLOW_UNINSTALL_APPS); 1027 readBoolean(parser, restrictions, UserManager.DISALLOW_SHARE_LOCATION); 1028 readBoolean(parser, restrictions, 1029 UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES); 1030 readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_BLUETOOTH); 1031 readBoolean(parser, restrictions, UserManager.DISALLOW_USB_FILE_TRANSFER); 1032 readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_CREDENTIALS); 1033 readBoolean(parser, restrictions, UserManager.DISALLOW_REMOVE_USER); 1034 readBoolean(parser, restrictions, UserManager.DISALLOW_DEBUGGING_FEATURES); 1035 readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_VPN); 1036 readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_TETHERING); 1037 readBoolean(parser, restrictions, UserManager.DISALLOW_FACTORY_RESET); 1038 readBoolean(parser, restrictions, UserManager.DISALLOW_ADD_USER); 1039 readBoolean(parser, restrictions, UserManager.ENSURE_VERIFY_APPS); 1040 readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_CELL_BROADCASTS); 1041 readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS); 1042 readBoolean(parser, restrictions, UserManager.DISALLOW_APPS_CONTROL); 1043 readBoolean(parser, restrictions, 1044 UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA); 1045 readBoolean(parser, restrictions, UserManager.DISALLOW_UNMUTE_MICROPHONE); 1046 readBoolean(parser, restrictions, UserManager.DISALLOW_ADJUST_VOLUME); 1047 readBoolean(parser, restrictions, UserManager.DISALLOW_OUTGOING_CALLS); 1048 readBoolean(parser, restrictions, UserManager.DISALLOW_SMS); 1049 readBoolean(parser, restrictions, UserManager.DISALLOW_CREATE_WINDOWS); 1050 readBoolean(parser, restrictions, UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE); 1051 readBoolean(parser, restrictions, UserManager.DISALLOW_OUTGOING_BEAM); 1052 } 1053 readBoolean(XmlPullParser parser, Bundle restrictions, String restrictionKey)1054 private void readBoolean(XmlPullParser parser, Bundle restrictions, 1055 String restrictionKey) { 1056 String value = parser.getAttributeValue(null, restrictionKey); 1057 if (value != null) { 1058 restrictions.putBoolean(restrictionKey, Boolean.parseBoolean(value)); 1059 } 1060 } 1061 writeBoolean(XmlSerializer xml, Bundle restrictions, String restrictionKey)1062 private void writeBoolean(XmlSerializer xml, Bundle restrictions, String restrictionKey) 1063 throws IOException { 1064 if (restrictions.containsKey(restrictionKey)) { 1065 xml.attribute(null, restrictionKey, 1066 Boolean.toString(restrictions.getBoolean(restrictionKey))); 1067 } 1068 } 1069 readIntAttribute(XmlPullParser parser, String attr, int defaultValue)1070 private int readIntAttribute(XmlPullParser parser, String attr, int defaultValue) { 1071 String valueString = parser.getAttributeValue(null, attr); 1072 if (valueString == null) return defaultValue; 1073 try { 1074 return Integer.parseInt(valueString); 1075 } catch (NumberFormatException nfe) { 1076 return defaultValue; 1077 } 1078 } 1079 readLongAttribute(XmlPullParser parser, String attr, long defaultValue)1080 private long readLongAttribute(XmlPullParser parser, String attr, long defaultValue) { 1081 String valueString = parser.getAttributeValue(null, attr); 1082 if (valueString == null) return defaultValue; 1083 try { 1084 return Long.parseLong(valueString); 1085 } catch (NumberFormatException nfe) { 1086 return defaultValue; 1087 } 1088 } 1089 isPackageInstalled(String pkg, int userId)1090 private boolean isPackageInstalled(String pkg, int userId) { 1091 final ApplicationInfo info = mPm.getApplicationInfo(pkg, 1092 PackageManager.GET_UNINSTALLED_PACKAGES, 1093 userId); 1094 if (info == null || (info.flags&ApplicationInfo.FLAG_INSTALLED) == 0) { 1095 return false; 1096 } 1097 return true; 1098 } 1099 1100 /** 1101 * Removes all the restrictions files (res_<packagename>) for a given user. 1102 * Does not do any permissions checking. 1103 */ cleanAppRestrictions(int userId)1104 private void cleanAppRestrictions(int userId) { 1105 synchronized (mPackagesLock) { 1106 File dir = Environment.getUserSystemDirectory(userId); 1107 String[] files = dir.list(); 1108 if (files == null) return; 1109 for (String fileName : files) { 1110 if (fileName.startsWith(RESTRICTIONS_FILE_PREFIX)) { 1111 File resFile = new File(dir, fileName); 1112 if (resFile.exists()) { 1113 resFile.delete(); 1114 } 1115 } 1116 } 1117 } 1118 } 1119 1120 /** 1121 * Removes the app restrictions file for a specific package and user id, if it exists. 1122 */ cleanAppRestrictionsForPackage(String pkg, int userId)1123 private void cleanAppRestrictionsForPackage(String pkg, int userId) { 1124 synchronized (mPackagesLock) { 1125 File dir = Environment.getUserSystemDirectory(userId); 1126 File resFile = new File(dir, packageToRestrictionsFileName(pkg)); 1127 if (resFile.exists()) { 1128 resFile.delete(); 1129 } 1130 } 1131 } 1132 1133 @Override createProfileForUser(String name, int flags, int userId)1134 public UserInfo createProfileForUser(String name, int flags, int userId) { 1135 checkManageUsersPermission("Only the system can create users"); 1136 if (userId != UserHandle.USER_OWNER) { 1137 Slog.w(LOG_TAG, "Only user owner can have profiles"); 1138 return null; 1139 } 1140 return createUserInternal(name, flags, userId); 1141 } 1142 1143 @Override createUser(String name, int flags)1144 public UserInfo createUser(String name, int flags) { 1145 checkManageUsersPermission("Only the system can create users"); 1146 return createUserInternal(name, flags, UserHandle.USER_NULL); 1147 } 1148 createUserInternal(String name, int flags, int parentId)1149 private UserInfo createUserInternal(String name, int flags, int parentId) { 1150 if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean( 1151 UserManager.DISALLOW_ADD_USER, false)) { 1152 Log.w(LOG_TAG, "Cannot add user. DISALLOW_ADD_USER is enabled."); 1153 return null; 1154 } 1155 final boolean isGuest = (flags & UserInfo.FLAG_GUEST) != 0; 1156 final long ident = Binder.clearCallingIdentity(); 1157 UserInfo userInfo = null; 1158 try { 1159 synchronized (mInstallLock) { 1160 synchronized (mPackagesLock) { 1161 UserInfo parent = null; 1162 if (parentId != UserHandle.USER_NULL) { 1163 parent = getUserInfoLocked(parentId); 1164 if (parent == null) return null; 1165 } 1166 // If we're not adding a guest user and the limit has been reached, 1167 // cannot add a user. 1168 if (!isGuest && isUserLimitReachedLocked()) { 1169 return null; 1170 } 1171 // If we're adding a guest and there already exists one, bail. 1172 if (isGuest && findCurrentGuestUserLocked() != null) { 1173 return null; 1174 } 1175 // Limit number of managed profiles that can be created 1176 if ((flags & UserInfo.FLAG_MANAGED_PROFILE) != 0 1177 && numberOfUsersOfTypeLocked(UserInfo.FLAG_MANAGED_PROFILE, true) 1178 >= MAX_MANAGED_PROFILES) { 1179 return null; 1180 } 1181 int userId = getNextAvailableIdLocked(); 1182 userInfo = new UserInfo(userId, name, null, flags); 1183 File userPath = new File(mBaseUserPath, Integer.toString(userId)); 1184 userInfo.serialNumber = mNextSerialNumber++; 1185 long now = System.currentTimeMillis(); 1186 userInfo.creationTime = (now > EPOCH_PLUS_30_YEARS) ? now : 0; 1187 userInfo.partial = true; 1188 Environment.getUserSystemDirectory(userInfo.id).mkdirs(); 1189 mUsers.put(userId, userInfo); 1190 writeUserListLocked(); 1191 if (parent != null) { 1192 if (parent.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) { 1193 parent.profileGroupId = parent.id; 1194 writeUserLocked(parent); 1195 } 1196 userInfo.profileGroupId = parent.profileGroupId; 1197 } 1198 writeUserLocked(userInfo); 1199 mPm.createNewUserLILPw(userId, userPath); 1200 userInfo.partial = false; 1201 writeUserLocked(userInfo); 1202 updateUserIdsLocked(); 1203 Bundle restrictions = new Bundle(); 1204 mUserRestrictions.append(userId, restrictions); 1205 } 1206 } 1207 if (userInfo != null) { 1208 Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED); 1209 addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userInfo.id); 1210 mContext.sendBroadcastAsUser(addedIntent, UserHandle.ALL, 1211 android.Manifest.permission.MANAGE_USERS); 1212 } 1213 } finally { 1214 Binder.restoreCallingIdentity(ident); 1215 } 1216 return userInfo; 1217 } 1218 numberOfUsersOfTypeLocked(int flags, boolean excludeDying)1219 private int numberOfUsersOfTypeLocked(int flags, boolean excludeDying) { 1220 int count = 0; 1221 for (int i = mUsers.size() - 1; i >= 0; i--) { 1222 UserInfo user = mUsers.valueAt(i); 1223 if (!excludeDying || !mRemovingUserIds.get(user.id)) { 1224 if ((user.flags & flags) != 0) { 1225 count++; 1226 } 1227 } 1228 } 1229 return count; 1230 } 1231 1232 /** 1233 * Find the current guest user. If the Guest user is partial, 1234 * then do not include it in the results as it is about to die. 1235 * This is different than {@link #numberOfUsersOfTypeLocked(int, boolean)} due to 1236 * the special handling of Guests being removed. 1237 */ findCurrentGuestUserLocked()1238 private UserInfo findCurrentGuestUserLocked() { 1239 final int size = mUsers.size(); 1240 for (int i = 0; i < size; i++) { 1241 final UserInfo user = mUsers.valueAt(i); 1242 if (user.isGuest() && !user.guestToRemove && !mRemovingUserIds.get(user.id)) { 1243 return user; 1244 } 1245 } 1246 return null; 1247 } 1248 1249 /** 1250 * Mark this guest user for deletion to allow us to create another guest 1251 * and switch to that user before actually removing this guest. 1252 * @param userHandle the userid of the current guest 1253 * @return whether the user could be marked for deletion 1254 */ markGuestForDeletion(int userHandle)1255 public boolean markGuestForDeletion(int userHandle) { 1256 checkManageUsersPermission("Only the system can remove users"); 1257 if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean( 1258 UserManager.DISALLOW_REMOVE_USER, false)) { 1259 Log.w(LOG_TAG, "Cannot remove user. DISALLOW_REMOVE_USER is enabled."); 1260 return false; 1261 } 1262 1263 long ident = Binder.clearCallingIdentity(); 1264 try { 1265 final UserInfo user; 1266 synchronized (mPackagesLock) { 1267 user = mUsers.get(userHandle); 1268 if (userHandle == 0 || user == null || mRemovingUserIds.get(userHandle)) { 1269 return false; 1270 } 1271 if (!user.isGuest()) { 1272 return false; 1273 } 1274 // We set this to a guest user that is to be removed. This is a temporary state 1275 // where we are allowed to add new Guest users, even if this one is still not 1276 // removed. This user will still show up in getUserInfo() calls. 1277 // If we don't get around to removing this Guest user, it will be purged on next 1278 // startup. 1279 user.guestToRemove = true; 1280 // Mark it as disabled, so that it isn't returned any more when 1281 // profiles are queried. 1282 user.flags |= UserInfo.FLAG_DISABLED; 1283 writeUserLocked(user); 1284 } 1285 } finally { 1286 Binder.restoreCallingIdentity(ident); 1287 } 1288 return true; 1289 } 1290 1291 /** 1292 * Removes a user and all data directories created for that user. This method should be called 1293 * after the user's processes have been terminated. 1294 * @param userHandle the user's id 1295 */ removeUser(int userHandle)1296 public boolean removeUser(int userHandle) { 1297 checkManageUsersPermission("Only the system can remove users"); 1298 if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean( 1299 UserManager.DISALLOW_REMOVE_USER, false)) { 1300 Log.w(LOG_TAG, "Cannot remove user. DISALLOW_REMOVE_USER is enabled."); 1301 return false; 1302 } 1303 1304 long ident = Binder.clearCallingIdentity(); 1305 try { 1306 final UserInfo user; 1307 synchronized (mPackagesLock) { 1308 user = mUsers.get(userHandle); 1309 if (userHandle == 0 || user == null || mRemovingUserIds.get(userHandle)) { 1310 return false; 1311 } 1312 1313 // We remember deleted user IDs to prevent them from being 1314 // reused during the current boot; they can still be reused 1315 // after a reboot. 1316 mRemovingUserIds.put(userHandle, true); 1317 1318 try { 1319 mAppOpsService.removeUser(userHandle); 1320 } catch (RemoteException e) { 1321 Log.w(LOG_TAG, "Unable to notify AppOpsService of removing user", e); 1322 } 1323 // Set this to a partially created user, so that the user will be purged 1324 // on next startup, in case the runtime stops now before stopping and 1325 // removing the user completely. 1326 user.partial = true; 1327 // Mark it as disabled, so that it isn't returned any more when 1328 // profiles are queried. 1329 user.flags |= UserInfo.FLAG_DISABLED; 1330 writeUserLocked(user); 1331 } 1332 1333 if (user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID 1334 && user.isManagedProfile()) { 1335 // Send broadcast to notify system that the user removed was a 1336 // managed user. 1337 sendProfileRemovedBroadcast(user.profileGroupId, user.id); 1338 } 1339 1340 if (DBG) Slog.i(LOG_TAG, "Stopping user " + userHandle); 1341 int res; 1342 try { 1343 res = ActivityManagerNative.getDefault().stopUser(userHandle, 1344 new IStopUserCallback.Stub() { 1345 @Override 1346 public void userStopped(int userId) { 1347 finishRemoveUser(userId); 1348 } 1349 @Override 1350 public void userStopAborted(int userId) { 1351 } 1352 }); 1353 } catch (RemoteException e) { 1354 return false; 1355 } 1356 return res == ActivityManager.USER_OP_SUCCESS; 1357 } finally { 1358 Binder.restoreCallingIdentity(ident); 1359 } 1360 } 1361 finishRemoveUser(final int userHandle)1362 void finishRemoveUser(final int userHandle) { 1363 if (DBG) Slog.i(LOG_TAG, "finishRemoveUser " + userHandle); 1364 // Let other services shutdown any activity and clean up their state before completely 1365 // wiping the user's system directory and removing from the user list 1366 long ident = Binder.clearCallingIdentity(); 1367 try { 1368 Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED); 1369 addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle); 1370 mContext.sendOrderedBroadcastAsUser(addedIntent, UserHandle.ALL, 1371 android.Manifest.permission.MANAGE_USERS, 1372 1373 new BroadcastReceiver() { 1374 @Override 1375 public void onReceive(Context context, Intent intent) { 1376 if (DBG) { 1377 Slog.i(LOG_TAG, 1378 "USER_REMOVED broadcast sent, cleaning up user data " 1379 + userHandle); 1380 } 1381 new Thread() { 1382 public void run() { 1383 synchronized (mInstallLock) { 1384 synchronized (mPackagesLock) { 1385 removeUserStateLocked(userHandle); 1386 } 1387 } 1388 } 1389 }.start(); 1390 } 1391 }, 1392 1393 null, Activity.RESULT_OK, null, null); 1394 } finally { 1395 Binder.restoreCallingIdentity(ident); 1396 } 1397 } 1398 removeUserStateLocked(final int userHandle)1399 private void removeUserStateLocked(final int userHandle) { 1400 // Cleanup package manager settings 1401 mPm.cleanUpUserLILPw(this, userHandle); 1402 1403 // Remove this user from the list 1404 mUsers.remove(userHandle); 1405 1406 mRestrictionsPinStates.remove(userHandle); 1407 // Remove user file 1408 AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX)); 1409 userFile.delete(); 1410 // Update the user list 1411 writeUserListLocked(); 1412 updateUserIdsLocked(); 1413 removeDirectoryRecursive(Environment.getUserSystemDirectory(userHandle)); 1414 } 1415 removeDirectoryRecursive(File parent)1416 private void removeDirectoryRecursive(File parent) { 1417 if (parent.isDirectory()) { 1418 String[] files = parent.list(); 1419 for (String filename : files) { 1420 File child = new File(parent, filename); 1421 removeDirectoryRecursive(child); 1422 } 1423 } 1424 parent.delete(); 1425 } 1426 sendProfileRemovedBroadcast(int parentUserId, int removedUserId)1427 private void sendProfileRemovedBroadcast(int parentUserId, int removedUserId) { 1428 Intent managedProfileIntent = new Intent(Intent.ACTION_MANAGED_PROFILE_REMOVED); 1429 managedProfileIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | 1430 Intent.FLAG_RECEIVER_FOREGROUND); 1431 managedProfileIntent.putExtra(Intent.EXTRA_USER, new UserHandle(removedUserId)); 1432 mContext.sendBroadcastAsUser(managedProfileIntent, new UserHandle(parentUserId), null); 1433 } 1434 1435 @Override getApplicationRestrictions(String packageName)1436 public Bundle getApplicationRestrictions(String packageName) { 1437 return getApplicationRestrictionsForUser(packageName, UserHandle.getCallingUserId()); 1438 } 1439 1440 @Override getApplicationRestrictionsForUser(String packageName, int userId)1441 public Bundle getApplicationRestrictionsForUser(String packageName, int userId) { 1442 if (UserHandle.getCallingUserId() != userId 1443 || !UserHandle.isSameApp(Binder.getCallingUid(), getUidForPackage(packageName))) { 1444 checkManageUsersPermission("Only system can get restrictions for other users/apps"); 1445 } 1446 synchronized (mPackagesLock) { 1447 // Read the restrictions from XML 1448 return readApplicationRestrictionsLocked(packageName, userId); 1449 } 1450 } 1451 1452 @Override setApplicationRestrictions(String packageName, Bundle restrictions, int userId)1453 public void setApplicationRestrictions(String packageName, Bundle restrictions, 1454 int userId) { 1455 if (UserHandle.getCallingUserId() != userId 1456 || !UserHandle.isSameApp(Binder.getCallingUid(), getUidForPackage(packageName))) { 1457 checkManageUsersPermission("Only system can set restrictions for other users/apps"); 1458 } 1459 synchronized (mPackagesLock) { 1460 if (restrictions == null || restrictions.isEmpty()) { 1461 cleanAppRestrictionsForPackage(packageName, userId); 1462 } else { 1463 // Write the restrictions to XML 1464 writeApplicationRestrictionsLocked(packageName, restrictions, userId); 1465 } 1466 } 1467 1468 if (isPackageInstalled(packageName, userId)) { 1469 // Notify package of changes via an intent - only sent to explicitly registered receivers. 1470 Intent changeIntent = new Intent(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED); 1471 changeIntent.setPackage(packageName); 1472 changeIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 1473 mContext.sendBroadcastAsUser(changeIntent, new UserHandle(userId)); 1474 } 1475 } 1476 1477 @Override setRestrictionsChallenge(String newPin)1478 public boolean setRestrictionsChallenge(String newPin) { 1479 checkManageUsersPermission("Only system can modify the restrictions pin"); 1480 int userId = UserHandle.getCallingUserId(); 1481 synchronized (mPackagesLock) { 1482 RestrictionsPinState pinState = mRestrictionsPinStates.get(userId); 1483 if (pinState == null) { 1484 pinState = new RestrictionsPinState(); 1485 } 1486 if (newPin == null) { 1487 pinState.salt = 0; 1488 pinState.pinHash = null; 1489 } else { 1490 try { 1491 pinState.salt = SecureRandom.getInstance("SHA1PRNG").nextLong(); 1492 } catch (NoSuchAlgorithmException e) { 1493 pinState.salt = (long) (Math.random() * Long.MAX_VALUE); 1494 } 1495 pinState.pinHash = passwordToHash(newPin, pinState.salt); 1496 pinState.failedAttempts = 0; 1497 } 1498 mRestrictionsPinStates.put(userId, pinState); 1499 writeUserLocked(mUsers.get(userId)); 1500 } 1501 return true; 1502 } 1503 1504 @Override checkRestrictionsChallenge(String pin)1505 public int checkRestrictionsChallenge(String pin) { 1506 checkManageUsersPermission("Only system can verify the restrictions pin"); 1507 int userId = UserHandle.getCallingUserId(); 1508 synchronized (mPackagesLock) { 1509 RestrictionsPinState pinState = mRestrictionsPinStates.get(userId); 1510 // If there's no pin set, return error code 1511 if (pinState == null || pinState.salt == 0 || pinState.pinHash == null) { 1512 return UserManager.PIN_VERIFICATION_FAILED_NOT_SET; 1513 } else if (pin == null) { 1514 // If just checking if user can be prompted, return remaining time 1515 int waitTime = getRemainingTimeForPinAttempt(pinState); 1516 Slog.d(LOG_TAG, "Remaining waittime peek=" + waitTime); 1517 return waitTime; 1518 } else { 1519 int waitTime = getRemainingTimeForPinAttempt(pinState); 1520 Slog.d(LOG_TAG, "Remaining waittime=" + waitTime); 1521 if (waitTime > 0) { 1522 return waitTime; 1523 } 1524 if (passwordToHash(pin, pinState.salt).equals(pinState.pinHash)) { 1525 pinState.failedAttempts = 0; 1526 writeUserLocked(mUsers.get(userId)); 1527 return UserManager.PIN_VERIFICATION_SUCCESS; 1528 } else { 1529 pinState.failedAttempts++; 1530 pinState.lastAttemptTime = System.currentTimeMillis(); 1531 writeUserLocked(mUsers.get(userId)); 1532 return waitTime; 1533 } 1534 } 1535 } 1536 } 1537 getRemainingTimeForPinAttempt(RestrictionsPinState pinState)1538 private int getRemainingTimeForPinAttempt(RestrictionsPinState pinState) { 1539 int backoffIndex = Math.min(pinState.failedAttempts / BACKOFF_INC_INTERVAL, 1540 BACKOFF_TIMES.length - 1); 1541 int backoffTime = (pinState.failedAttempts % BACKOFF_INC_INTERVAL) == 0 ? 1542 BACKOFF_TIMES[backoffIndex] : 0; 1543 return (int) Math.max(backoffTime + pinState.lastAttemptTime - System.currentTimeMillis(), 1544 0); 1545 } 1546 1547 @Override hasRestrictionsChallenge()1548 public boolean hasRestrictionsChallenge() { 1549 int userId = UserHandle.getCallingUserId(); 1550 synchronized (mPackagesLock) { 1551 return hasRestrictionsPinLocked(userId); 1552 } 1553 } 1554 hasRestrictionsPinLocked(int userId)1555 private boolean hasRestrictionsPinLocked(int userId) { 1556 RestrictionsPinState pinState = mRestrictionsPinStates.get(userId); 1557 if (pinState == null || pinState.salt == 0 || pinState.pinHash == null) { 1558 return false; 1559 } 1560 return true; 1561 } 1562 1563 @Override removeRestrictions()1564 public void removeRestrictions() { 1565 checkManageUsersPermission("Only system can remove restrictions"); 1566 final int userHandle = UserHandle.getCallingUserId(); 1567 removeRestrictionsForUser(userHandle, true); 1568 } 1569 removeRestrictionsForUser(final int userHandle, boolean unhideApps)1570 private void removeRestrictionsForUser(final int userHandle, boolean unhideApps) { 1571 synchronized (mPackagesLock) { 1572 // Remove all user restrictions 1573 setUserRestrictions(new Bundle(), userHandle); 1574 // Remove restrictions pin 1575 setRestrictionsChallenge(null); 1576 // Remove any app restrictions 1577 cleanAppRestrictions(userHandle); 1578 } 1579 if (unhideApps) { 1580 unhideAllInstalledAppsForUser(userHandle); 1581 } 1582 } 1583 unhideAllInstalledAppsForUser(final int userHandle)1584 private void unhideAllInstalledAppsForUser(final int userHandle) { 1585 mHandler.post(new Runnable() { 1586 @Override 1587 public void run() { 1588 List<ApplicationInfo> apps = 1589 mPm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES, 1590 userHandle).getList(); 1591 final long ident = Binder.clearCallingIdentity(); 1592 try { 1593 for (ApplicationInfo appInfo : apps) { 1594 if ((appInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0 1595 && (appInfo.flags & ApplicationInfo.FLAG_HIDDEN) != 0) { 1596 mPm.setApplicationHiddenSettingAsUser(appInfo.packageName, false, 1597 userHandle); 1598 } 1599 } 1600 } finally { 1601 Binder.restoreCallingIdentity(ident); 1602 } 1603 } 1604 }); 1605 } 1606 1607 /* 1608 * Generate a hash for the given password. To avoid brute force attacks, we use a salted hash. 1609 * Not the most secure, but it is at least a second level of protection. First level is that 1610 * the file is in a location only readable by the system process. 1611 * @param password the password. 1612 * @param salt the randomly generated salt 1613 * @return the hash of the pattern in a String. 1614 */ passwordToHash(String password, long salt)1615 private String passwordToHash(String password, long salt) { 1616 if (password == null) { 1617 return null; 1618 } 1619 String algo = null; 1620 String hashed = salt + password; 1621 try { 1622 byte[] saltedPassword = (password + salt).getBytes(); 1623 byte[] sha1 = MessageDigest.getInstance(algo = "SHA-1").digest(saltedPassword); 1624 byte[] md5 = MessageDigest.getInstance(algo = "MD5").digest(saltedPassword); 1625 hashed = toHex(sha1) + toHex(md5); 1626 } catch (NoSuchAlgorithmException e) { 1627 Log.w(LOG_TAG, "Failed to encode string because of missing algorithm: " + algo); 1628 } 1629 return hashed; 1630 } 1631 toHex(byte[] ary)1632 private static String toHex(byte[] ary) { 1633 final String hex = "0123456789ABCDEF"; 1634 String ret = ""; 1635 for (int i = 0; i < ary.length; i++) { 1636 ret += hex.charAt((ary[i] >> 4) & 0xf); 1637 ret += hex.charAt(ary[i] & 0xf); 1638 } 1639 return ret; 1640 } 1641 getUidForPackage(String packageName)1642 private int getUidForPackage(String packageName) { 1643 long ident = Binder.clearCallingIdentity(); 1644 try { 1645 return mContext.getPackageManager().getApplicationInfo(packageName, 1646 PackageManager.GET_UNINSTALLED_PACKAGES).uid; 1647 } catch (NameNotFoundException nnfe) { 1648 return -1; 1649 } finally { 1650 Binder.restoreCallingIdentity(ident); 1651 } 1652 } 1653 readApplicationRestrictionsLocked(String packageName, int userId)1654 private Bundle readApplicationRestrictionsLocked(String packageName, 1655 int userId) { 1656 final Bundle restrictions = new Bundle(); 1657 final ArrayList<String> values = new ArrayList<String>(); 1658 1659 FileInputStream fis = null; 1660 try { 1661 AtomicFile restrictionsFile = 1662 new AtomicFile(new File(Environment.getUserSystemDirectory(userId), 1663 packageToRestrictionsFileName(packageName))); 1664 fis = restrictionsFile.openRead(); 1665 XmlPullParser parser = Xml.newPullParser(); 1666 parser.setInput(fis, null); 1667 int type; 1668 while ((type = parser.next()) != XmlPullParser.START_TAG 1669 && type != XmlPullParser.END_DOCUMENT) { 1670 ; 1671 } 1672 1673 if (type != XmlPullParser.START_TAG) { 1674 Slog.e(LOG_TAG, "Unable to read restrictions file " 1675 + restrictionsFile.getBaseFile()); 1676 return restrictions; 1677 } 1678 1679 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { 1680 if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_ENTRY)) { 1681 String key = parser.getAttributeValue(null, ATTR_KEY); 1682 String valType = parser.getAttributeValue(null, ATTR_VALUE_TYPE); 1683 String multiple = parser.getAttributeValue(null, ATTR_MULTIPLE); 1684 if (multiple != null) { 1685 values.clear(); 1686 int count = Integer.parseInt(multiple); 1687 while (count > 0 && (type = parser.next()) != XmlPullParser.END_DOCUMENT) { 1688 if (type == XmlPullParser.START_TAG 1689 && parser.getName().equals(TAG_VALUE)) { 1690 values.add(parser.nextText().trim()); 1691 count--; 1692 } 1693 } 1694 String [] valueStrings = new String[values.size()]; 1695 values.toArray(valueStrings); 1696 restrictions.putStringArray(key, valueStrings); 1697 } else { 1698 String value = parser.nextText().trim(); 1699 if (ATTR_TYPE_BOOLEAN.equals(valType)) { 1700 restrictions.putBoolean(key, Boolean.parseBoolean(value)); 1701 } else if (ATTR_TYPE_INTEGER.equals(valType)) { 1702 restrictions.putInt(key, Integer.parseInt(value)); 1703 } else { 1704 restrictions.putString(key, value); 1705 } 1706 } 1707 } 1708 } 1709 } catch (IOException ioe) { 1710 } catch (XmlPullParserException pe) { 1711 } finally { 1712 if (fis != null) { 1713 try { 1714 fis.close(); 1715 } catch (IOException e) { 1716 } 1717 } 1718 } 1719 return restrictions; 1720 } 1721 writeApplicationRestrictionsLocked(String packageName, Bundle restrictions, int userId)1722 private void writeApplicationRestrictionsLocked(String packageName, 1723 Bundle restrictions, int userId) { 1724 FileOutputStream fos = null; 1725 AtomicFile restrictionsFile = new AtomicFile( 1726 new File(Environment.getUserSystemDirectory(userId), 1727 packageToRestrictionsFileName(packageName))); 1728 try { 1729 fos = restrictionsFile.startWrite(); 1730 final BufferedOutputStream bos = new BufferedOutputStream(fos); 1731 1732 // XmlSerializer serializer = XmlUtils.serializerInstance(); 1733 final XmlSerializer serializer = new FastXmlSerializer(); 1734 serializer.setOutput(bos, "utf-8"); 1735 serializer.startDocument(null, true); 1736 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); 1737 1738 serializer.startTag(null, TAG_RESTRICTIONS); 1739 1740 for (String key : restrictions.keySet()) { 1741 Object value = restrictions.get(key); 1742 serializer.startTag(null, TAG_ENTRY); 1743 serializer.attribute(null, ATTR_KEY, key); 1744 1745 if (value instanceof Boolean) { 1746 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BOOLEAN); 1747 serializer.text(value.toString()); 1748 } else if (value instanceof Integer) { 1749 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_INTEGER); 1750 serializer.text(value.toString()); 1751 } else if (value == null || value instanceof String) { 1752 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_STRING); 1753 serializer.text(value != null ? (String) value : ""); 1754 } else { 1755 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_STRING_ARRAY); 1756 String[] values = (String[]) value; 1757 serializer.attribute(null, ATTR_MULTIPLE, Integer.toString(values.length)); 1758 for (String choice : values) { 1759 serializer.startTag(null, TAG_VALUE); 1760 serializer.text(choice != null ? choice : ""); 1761 serializer.endTag(null, TAG_VALUE); 1762 } 1763 } 1764 serializer.endTag(null, TAG_ENTRY); 1765 } 1766 1767 serializer.endTag(null, TAG_RESTRICTIONS); 1768 1769 serializer.endDocument(); 1770 restrictionsFile.finishWrite(fos); 1771 } catch (Exception e) { 1772 restrictionsFile.failWrite(fos); 1773 Slog.e(LOG_TAG, "Error writing application restrictions list"); 1774 } 1775 } 1776 1777 @Override getUserSerialNumber(int userHandle)1778 public int getUserSerialNumber(int userHandle) { 1779 synchronized (mPackagesLock) { 1780 if (!exists(userHandle)) return -1; 1781 return getUserInfoLocked(userHandle).serialNumber; 1782 } 1783 } 1784 1785 @Override getUserHandle(int userSerialNumber)1786 public int getUserHandle(int userSerialNumber) { 1787 synchronized (mPackagesLock) { 1788 for (int userId : mUserIds) { 1789 if (getUserInfoLocked(userId).serialNumber == userSerialNumber) return userId; 1790 } 1791 // Not found 1792 return -1; 1793 } 1794 } 1795 1796 /** 1797 * Caches the list of user ids in an array, adjusting the array size when necessary. 1798 */ updateUserIdsLocked()1799 private void updateUserIdsLocked() { 1800 int num = 0; 1801 for (int i = 0; i < mUsers.size(); i++) { 1802 if (!mUsers.valueAt(i).partial) { 1803 num++; 1804 } 1805 } 1806 final int[] newUsers = new int[num]; 1807 int n = 0; 1808 for (int i = 0; i < mUsers.size(); i++) { 1809 if (!mUsers.valueAt(i).partial) { 1810 newUsers[n++] = mUsers.keyAt(i); 1811 } 1812 } 1813 mUserIds = newUsers; 1814 } 1815 1816 /** 1817 * Make a note of the last started time of a user and do some cleanup. 1818 * @param userId the user that was just foregrounded 1819 */ userForeground(int userId)1820 public void userForeground(int userId) { 1821 synchronized (mPackagesLock) { 1822 UserInfo user = mUsers.get(userId); 1823 long now = System.currentTimeMillis(); 1824 if (user == null || user.partial) { 1825 Slog.w(LOG_TAG, "userForeground: unknown user #" + userId); 1826 return; 1827 } 1828 if (now > EPOCH_PLUS_30_YEARS) { 1829 user.lastLoggedInTime = now; 1830 writeUserLocked(user); 1831 } 1832 } 1833 } 1834 1835 /** 1836 * Returns the next available user id, filling in any holes in the ids. 1837 * TODO: May not be a good idea to recycle ids, in case it results in confusion 1838 * for data and battery stats collection, or unexpected cross-talk. 1839 * @return 1840 */ getNextAvailableIdLocked()1841 private int getNextAvailableIdLocked() { 1842 synchronized (mPackagesLock) { 1843 int i = MIN_USER_ID; 1844 while (i < Integer.MAX_VALUE) { 1845 if (mUsers.indexOfKey(i) < 0 && !mRemovingUserIds.get(i)) { 1846 break; 1847 } 1848 i++; 1849 } 1850 return i; 1851 } 1852 } 1853 packageToRestrictionsFileName(String packageName)1854 private String packageToRestrictionsFileName(String packageName) { 1855 return RESTRICTIONS_FILE_PREFIX + packageName + XML_SUFFIX; 1856 } 1857 restrictionsFileNameToPackage(String fileName)1858 private String restrictionsFileNameToPackage(String fileName) { 1859 return fileName.substring(RESTRICTIONS_FILE_PREFIX.length(), 1860 (int) (fileName.length() - XML_SUFFIX.length())); 1861 } 1862 1863 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)1864 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1865 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1866 != PackageManager.PERMISSION_GRANTED) { 1867 pw.println("Permission Denial: can't dump UserManager from from pid=" 1868 + Binder.getCallingPid() 1869 + ", uid=" + Binder.getCallingUid() 1870 + " without permission " 1871 + android.Manifest.permission.DUMP); 1872 return; 1873 } 1874 1875 long now = System.currentTimeMillis(); 1876 StringBuilder sb = new StringBuilder(); 1877 synchronized (mPackagesLock) { 1878 pw.println("Users:"); 1879 for (int i = 0; i < mUsers.size(); i++) { 1880 UserInfo user = mUsers.valueAt(i); 1881 if (user == null) continue; 1882 pw.print(" "); pw.print(user); pw.print(" serialNo="); pw.print(user.serialNumber); 1883 if (mRemovingUserIds.get(mUsers.keyAt(i))) pw.print(" <removing> "); 1884 if (user.partial) pw.print(" <partial>"); 1885 pw.println(); 1886 pw.print(" Created: "); 1887 if (user.creationTime == 0) { 1888 pw.println("<unknown>"); 1889 } else { 1890 sb.setLength(0); 1891 TimeUtils.formatDuration(now - user.creationTime, sb); 1892 sb.append(" ago"); 1893 pw.println(sb); 1894 } 1895 pw.print(" Last logged in: "); 1896 if (user.lastLoggedInTime == 0) { 1897 pw.println("<unknown>"); 1898 } else { 1899 sb.setLength(0); 1900 TimeUtils.formatDuration(now - user.lastLoggedInTime, sb); 1901 sb.append(" ago"); 1902 pw.println(sb); 1903 } 1904 } 1905 } 1906 } 1907 } 1908