UserManagerService.java revision b531d086a61077ebc6c756f2294754b1bdb81616
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 17package com.android.server.pm; 18 19import android.Manifest; 20import android.annotation.NonNull; 21import android.annotation.Nullable; 22import android.app.Activity; 23import android.app.ActivityManager; 24import android.app.ActivityManagerInternal; 25import android.app.ActivityManagerNative; 26import android.app.IActivityManager; 27import android.app.IStopUserCallback; 28import android.content.BroadcastReceiver; 29import android.content.Context; 30import android.content.Intent; 31import android.content.IntentFilter; 32import android.content.pm.ApplicationInfo; 33import android.content.pm.PackageManager; 34import android.content.pm.PackageManager.NameNotFoundException; 35import android.content.pm.UserInfo; 36import android.content.res.Resources; 37import android.graphics.Bitmap; 38import android.os.Binder; 39import android.os.Bundle; 40import android.os.Debug; 41import android.os.Environment; 42import android.os.FileUtils; 43import android.os.Handler; 44import android.os.IBinder; 45import android.os.IUserManager; 46import android.os.Message; 47import android.os.ParcelFileDescriptor; 48import android.os.Parcelable; 49import android.os.PersistableBundle; 50import android.os.Process; 51import android.os.RemoteException; 52import android.os.ResultReceiver; 53import android.os.SELinux; 54import android.os.ServiceManager; 55import android.os.ShellCommand; 56import android.os.UserHandle; 57import android.os.UserManager; 58import android.os.UserManagerInternal; 59import android.os.UserManagerInternal.UserRestrictionsListener; 60import android.os.storage.StorageManager; 61import android.os.storage.VolumeInfo; 62import android.system.ErrnoException; 63import android.system.Os; 64import android.system.OsConstants; 65import android.util.AtomicFile; 66import android.util.Log; 67import android.util.Slog; 68import android.util.SparseArray; 69import android.util.SparseBooleanArray; 70import android.util.TimeUtils; 71import android.util.Xml; 72 73import com.android.internal.annotations.GuardedBy; 74import com.android.internal.annotations.VisibleForTesting; 75import com.android.internal.app.IAppOpsService; 76import com.android.internal.logging.MetricsLogger; 77import com.android.internal.util.FastXmlSerializer; 78import com.android.internal.util.Preconditions; 79import com.android.internal.util.XmlUtils; 80import com.android.internal.widget.LockPatternUtils; 81import com.android.server.LocalServices; 82 83import libcore.io.IoUtils; 84import libcore.util.Objects; 85 86import org.xmlpull.v1.XmlPullParser; 87import org.xmlpull.v1.XmlPullParserException; 88import org.xmlpull.v1.XmlSerializer; 89 90import java.io.BufferedOutputStream; 91import java.io.File; 92import java.io.FileDescriptor; 93import java.io.FileInputStream; 94import java.io.FileNotFoundException; 95import java.io.FileOutputStream; 96import java.io.IOException; 97import java.io.PrintWriter; 98import java.nio.charset.StandardCharsets; 99import java.util.ArrayList; 100import java.util.List; 101 102/** 103 * Service for {@link UserManager}. 104 * 105 * Method naming convention: 106 * <ul> 107 * <li> Methods suffixed with "LP" should be called within the {@link #mPackagesLock} lock. 108 * <li> Methods suffixed with "LR" should be called within the {@link #mRestrictionsLock} lock. 109 * <li> Methods suffixed with "LU" should be called within the {@link #mUsersLock} lock. 110 * </ul> 111 */ 112public class UserManagerService extends IUserManager.Stub { 113 private static final String LOG_TAG = "UserManagerService"; 114 static final boolean DBG = false; // DO NOT SUBMIT WITH TRUE 115 private static final boolean DBG_WITH_STACKTRACE = false; // DO NOT SUBMIT WITH TRUE 116 117 private static final String TAG_NAME = "name"; 118 private static final String TAG_ACCOUNT = "account"; 119 private static final String ATTR_FLAGS = "flags"; 120 private static final String ATTR_ICON_PATH = "icon"; 121 private static final String ATTR_ID = "id"; 122 private static final String ATTR_CREATION_TIME = "created"; 123 private static final String ATTR_LAST_LOGGED_IN_TIME = "lastLoggedIn"; 124 private static final String ATTR_SERIAL_NO = "serialNumber"; 125 private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber"; 126 private static final String ATTR_PARTIAL = "partial"; 127 private static final String ATTR_GUEST_TO_REMOVE = "guestToRemove"; 128 private static final String ATTR_USER_VERSION = "version"; 129 private static final String ATTR_PROFILE_GROUP_ID = "profileGroupId"; 130 private static final String ATTR_RESTRICTED_PROFILE_PARENT_ID = "restrictedProfileParentId"; 131 private static final String ATTR_SEED_ACCOUNT_NAME = "seedAccountName"; 132 private static final String ATTR_SEED_ACCOUNT_TYPE = "seedAccountType"; 133 private static final String TAG_GUEST_RESTRICTIONS = "guestRestrictions"; 134 private static final String TAG_USERS = "users"; 135 private static final String TAG_USER = "user"; 136 private static final String TAG_RESTRICTIONS = "restrictions"; 137 private static final String TAG_DEVICE_POLICY_RESTRICTIONS = "device_policy_restrictions"; 138 private static final String TAG_ENTRY = "entry"; 139 private static final String TAG_VALUE = "value"; 140 private static final String TAG_SEED_ACCOUNT_OPTIONS = "seedAccountOptions"; 141 private static final String ATTR_KEY = "key"; 142 private static final String ATTR_VALUE_TYPE = "type"; 143 private static final String ATTR_MULTIPLE = "m"; 144 145 private static final String ATTR_TYPE_STRING_ARRAY = "sa"; 146 private static final String ATTR_TYPE_STRING = "s"; 147 private static final String ATTR_TYPE_BOOLEAN = "b"; 148 private static final String ATTR_TYPE_INTEGER = "i"; 149 private static final String ATTR_TYPE_BUNDLE = "B"; 150 private static final String ATTR_TYPE_BUNDLE_ARRAY = "BA"; 151 152 private static final String USER_INFO_DIR = "system" + File.separator + "users"; 153 private static final String USER_LIST_FILENAME = "userlist.xml"; 154 private static final String USER_PHOTO_FILENAME = "photo.png"; 155 private static final String USER_PHOTO_FILENAME_TMP = USER_PHOTO_FILENAME + ".tmp"; 156 157 private static final String RESTRICTIONS_FILE_PREFIX = "res_"; 158 private static final String XML_SUFFIX = ".xml"; 159 160 private static final int MIN_USER_ID = 10; 161 // We need to keep process uid within Integer.MAX_VALUE. 162 private static final int MAX_USER_ID = Integer.MAX_VALUE / UserHandle.PER_USER_RANGE; 163 164 private static final int USER_VERSION = 6; 165 166 private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // ms 167 168 // Maximum number of managed profiles permitted per user is 1. This cannot be increased 169 // without first making sure that the rest of the framework is prepared for it. 170 private static final int MAX_MANAGED_PROFILES = 1; 171 172 static final int WRITE_USER_MSG = 1; 173 static final int WRITE_USER_DELAY = 2*1000; // 2 seconds 174 175 private static final String XATTR_SERIAL = "user.serial"; 176 177 // Tron counters 178 private static final String TRON_GUEST_CREATED = "users_guest_created"; 179 private static final String TRON_USER_CREATED = "users_user_created"; 180 181 private final Context mContext; 182 private final PackageManagerService mPm; 183 private final Object mPackagesLock; 184 // Short-term lock for internal state, when interaction/sync with PM is not required 185 private final Object mUsersLock = new Object(); 186 private final Object mRestrictionsLock = new Object(); 187 188 private final Handler mHandler; 189 190 private final File mUsersDir; 191 private final File mUserListFile; 192 193 private static final IBinder mUserRestriconToken = new Binder(); 194 195 /** 196 * User-related information that is used for persisting to flash. Only UserInfo is 197 * directly exposed to other system apps. 198 */ 199 private static class UserData { 200 // Basic user information and properties 201 UserInfo info; 202 // Account name used when there is a strong association between a user and an account 203 String account; 204 // Account information for seeding into a newly created user. This could also be 205 // used for login validation for an existing user, for updating their credentials. 206 // In the latter case, data may not need to be persisted as it is only valid for the 207 // current login session. 208 String seedAccountName; 209 String seedAccountType; 210 PersistableBundle seedAccountOptions; 211 // Whether to perist the seed account information to be available after a boot 212 boolean persistSeedData; 213 214 void clearSeedAccountData() { 215 seedAccountName = null; 216 seedAccountType = null; 217 seedAccountOptions = null; 218 persistSeedData = false; 219 } 220 } 221 222 @GuardedBy("mUsersLock") 223 private final SparseArray<UserData> mUsers = new SparseArray<>(); 224 225 /** 226 * User restrictions set via UserManager. This doesn't include restrictions set by 227 * device owner / profile owners. 228 * 229 * DO NOT Change existing {@link Bundle} in it. When changing a restriction for a user, 230 * a new {@link Bundle} should always be created and set. This is because a {@link Bundle} 231 * maybe shared between {@link #mBaseUserRestrictions} and 232 * {@link #mCachedEffectiveUserRestrictions}, but they should always updated separately. 233 * (Otherwise we won't be able to detect what restrictions have changed in 234 * {@link #updateUserRestrictionsInternalLR}. 235 */ 236 @GuardedBy("mRestrictionsLock") 237 private final SparseArray<Bundle> mBaseUserRestrictions = new SparseArray<>(); 238 239 /** 240 * Cached user restrictions that are in effect -- i.e. {@link #mBaseUserRestrictions} combined 241 * with device / profile owner restrictions. We'll initialize it lazily; use 242 * {@link #getEffectiveUserRestrictions} to access it. 243 * 244 * DO NOT Change existing {@link Bundle} in it. When changing a restriction for a user, 245 * a new {@link Bundle} should always be created and set. This is because a {@link Bundle} 246 * maybe shared between {@link #mBaseUserRestrictions} and 247 * {@link #mCachedEffectiveUserRestrictions}, but they should always updated separately. 248 * (Otherwise we won't be able to detect what restrictions have changed in 249 * {@link #updateUserRestrictionsInternalLR}. 250 */ 251 @GuardedBy("mRestrictionsLock") 252 private final SparseArray<Bundle> mCachedEffectiveUserRestrictions = new SparseArray<>(); 253 254 /** 255 * User restrictions that have already been applied in 256 * {@link #updateUserRestrictionsInternalLR(Bundle, int)}. We use it to detect restrictions 257 * that have changed since the last 258 * {@link #updateUserRestrictionsInternalLR(Bundle, int)} call. 259 */ 260 @GuardedBy("mRestrictionsLock") 261 private final SparseArray<Bundle> mAppliedUserRestrictions = new SparseArray<>(); 262 263 /** 264 * User restrictions set by {@link com.android.server.devicepolicy.DevicePolicyManagerService} 265 * that should be applied to all users, including guests. 266 */ 267 @GuardedBy("mRestrictionsLock") 268 private Bundle mDevicePolicyGlobalUserRestrictions; 269 270 /** 271 * User restrictions set by {@link com.android.server.devicepolicy.DevicePolicyManagerService} 272 * for each user. 273 */ 274 @GuardedBy("mRestrictionsLock") 275 private final SparseArray<Bundle> mDevicePolicyLocalUserRestrictions = new SparseArray<>(); 276 277 @GuardedBy("mGuestRestrictions") 278 private final Bundle mGuestRestrictions = new Bundle(); 279 280 /** 281 * Set of user IDs being actively removed. Removed IDs linger in this set 282 * for several seconds to work around a VFS caching issue. 283 */ 284 @GuardedBy("mUsersLock") 285 private final SparseBooleanArray mRemovingUserIds = new SparseBooleanArray(); 286 287 @GuardedBy("mUsersLock") 288 private int[] mUserIds; 289 @GuardedBy("mPackagesLock") 290 private int mNextSerialNumber; 291 private int mUserVersion = 0; 292 293 private IAppOpsService mAppOpsService; 294 295 private final LocalService mLocalService; 296 297 @GuardedBy("mUsersLock") 298 private boolean mIsDeviceManaged; 299 300 @GuardedBy("mUsersLock") 301 private final SparseBooleanArray mIsUserManaged = new SparseBooleanArray(); 302 303 @GuardedBy("mUserRestrictionsListeners") 304 private final ArrayList<UserRestrictionsListener> mUserRestrictionsListeners = 305 new ArrayList<>(); 306 307 private final LockPatternUtils mLockPatternUtils; 308 309 /** 310 * Whether all users should be created ephemeral. 311 */ 312 @GuardedBy("mUsersLock") 313 private boolean mForceEphemeralUsers; 314 315 private static UserManagerService sInstance; 316 317 public static UserManagerService getInstance() { 318 synchronized (UserManagerService.class) { 319 return sInstance; 320 } 321 } 322 323 @VisibleForTesting 324 UserManagerService(File dataDir) { 325 this(null, null, new Object(), dataDir); 326 } 327 328 /** 329 * Called by package manager to create the service. This is closely 330 * associated with the package manager, and the given lock is the 331 * package manager's own lock. 332 */ 333 UserManagerService(Context context, PackageManagerService pm, Object packagesLock) { 334 this(context, pm, packagesLock, Environment.getDataDirectory()); 335 } 336 337 private UserManagerService(Context context, PackageManagerService pm, 338 Object packagesLock, File dataDir) { 339 mContext = context; 340 mPm = pm; 341 mPackagesLock = packagesLock; 342 mHandler = new MainHandler(); 343 synchronized (mPackagesLock) { 344 mUsersDir = new File(dataDir, USER_INFO_DIR); 345 mUsersDir.mkdirs(); 346 // Make zeroth user directory, for services to migrate their files to that location 347 File userZeroDir = new File(mUsersDir, String.valueOf(UserHandle.USER_SYSTEM)); 348 userZeroDir.mkdirs(); 349 FileUtils.setPermissions(mUsersDir.toString(), 350 FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IROTH | FileUtils.S_IXOTH, 351 -1, -1); 352 mUserListFile = new File(mUsersDir, USER_LIST_FILENAME); 353 initDefaultGuestRestrictions(); 354 readUserListLP(); 355 sInstance = this; 356 } 357 mLocalService = new LocalService(); 358 LocalServices.addService(UserManagerInternal.class, mLocalService); 359 mLockPatternUtils = new LockPatternUtils(mContext); 360 } 361 362 void systemReady() { 363 // Prune out any partially created, partially removed and ephemeral users. 364 ArrayList<UserInfo> partials = new ArrayList<>(); 365 synchronized (mUsersLock) { 366 final int userSize = mUsers.size(); 367 for (int i = 0; i < userSize; i++) { 368 UserInfo ui = mUsers.valueAt(i).info; 369 if ((ui.partial || ui.guestToRemove || ui.isEphemeral()) && i != 0) { 370 partials.add(ui); 371 } 372 } 373 } 374 final int partialsSize = partials.size(); 375 for (int i = 0; i < partialsSize; i++) { 376 UserInfo ui = partials.get(i); 377 Slog.w(LOG_TAG, "Removing partially created user " + ui.id 378 + " (name=" + ui.name + ")"); 379 removeUserState(ui.id); 380 } 381 382 onUserForeground(UserHandle.USER_SYSTEM); 383 384 mAppOpsService = IAppOpsService.Stub.asInterface( 385 ServiceManager.getService(Context.APP_OPS_SERVICE)); 386 387 synchronized (mRestrictionsLock) { 388 applyUserRestrictionsLR(UserHandle.USER_SYSTEM); 389 } 390 } 391 392 @Override 393 public String getUserAccount(int userId) { 394 checkManageUserAndAcrossUsersFullPermission("get user account"); 395 synchronized (mUsersLock) { 396 return mUsers.get(userId).account; 397 } 398 } 399 400 @Override 401 public void setUserAccount(int userId, String accountName) { 402 checkManageUserAndAcrossUsersFullPermission("set user account"); 403 UserData userToUpdate = null; 404 synchronized (mPackagesLock) { 405 synchronized (mUsersLock) { 406 final UserData userData = mUsers.get(userId); 407 if (userData == null) { 408 Slog.e(LOG_TAG, "User not found for setting user account: u" + userId); 409 return; 410 } 411 String currentAccount = userData.account; 412 if (!Objects.equal(currentAccount, accountName)) { 413 userData.account = accountName; 414 userToUpdate = userData; 415 } 416 } 417 418 if (userToUpdate != null) { 419 writeUserLP(userToUpdate); 420 } 421 } 422 } 423 424 @Override 425 public UserInfo getPrimaryUser() { 426 checkManageUsersPermission("query users"); 427 synchronized (mUsersLock) { 428 final int userSize = mUsers.size(); 429 for (int i = 0; i < userSize; i++) { 430 UserInfo ui = mUsers.valueAt(i).info; 431 if (ui.isPrimary() && !mRemovingUserIds.get(ui.id)) { 432 return ui; 433 } 434 } 435 } 436 return null; 437 } 438 439 @Override 440 public @NonNull List<UserInfo> getUsers(boolean excludeDying) { 441 checkManageUsersPermission("query users"); 442 synchronized (mUsersLock) { 443 ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size()); 444 final int userSize = mUsers.size(); 445 for (int i = 0; i < userSize; i++) { 446 UserInfo ui = mUsers.valueAt(i).info; 447 if (ui.partial) { 448 continue; 449 } 450 if (!excludeDying || !mRemovingUserIds.get(ui.id)) { 451 users.add(ui); 452 } 453 } 454 return users; 455 } 456 } 457 458 @Override 459 public List<UserInfo> getProfiles(int userId, boolean enabledOnly) { 460 if (userId != UserHandle.getCallingUserId()) { 461 checkManageUsersPermission("getting profiles related to user " + userId); 462 } 463 final long ident = Binder.clearCallingIdentity(); 464 try { 465 synchronized (mUsersLock) { 466 return getProfilesLU(userId, enabledOnly); 467 } 468 } finally { 469 Binder.restoreCallingIdentity(ident); 470 } 471 } 472 473 /** Assume permissions already checked and caller's identity cleared */ 474 private List<UserInfo> getProfilesLU(int userId, boolean enabledOnly) { 475 UserInfo user = getUserInfoLU(userId); 476 ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size()); 477 if (user == null) { 478 // Probably a dying user 479 return users; 480 } 481 final int userSize = mUsers.size(); 482 for (int i = 0; i < userSize; i++) { 483 UserInfo profile = mUsers.valueAt(i).info; 484 if (!isProfileOf(user, profile)) { 485 continue; 486 } 487 if (enabledOnly && !profile.isEnabled()) { 488 continue; 489 } 490 if (mRemovingUserIds.get(profile.id)) { 491 continue; 492 } 493 users.add(profile); 494 } 495 return users; 496 } 497 498 @Override 499 public int getCredentialOwnerProfile(int userHandle) { 500 checkManageUsersPermission("get the credential owner"); 501 if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle)) { 502 synchronized (mUsersLock) { 503 UserInfo profileParent = getProfileParentLU(userHandle); 504 if (profileParent != null) { 505 return profileParent.id; 506 } 507 } 508 } 509 510 return userHandle; 511 } 512 513 @Override 514 public boolean isSameProfileGroup(int userId, int otherUserId) { 515 if (userId == otherUserId) return true; 516 checkManageUsersPermission("check if in the same profile group"); 517 synchronized (mPackagesLock) { 518 return isSameProfileGroupLP(userId, otherUserId); 519 } 520 } 521 522 private boolean isSameProfileGroupLP(int userId, int otherUserId) { 523 synchronized (mUsersLock) { 524 UserInfo userInfo = getUserInfoLU(userId); 525 if (userInfo == null || userInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) { 526 return false; 527 } 528 UserInfo otherUserInfo = getUserInfoLU(otherUserId); 529 if (otherUserInfo == null 530 || otherUserInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) { 531 return false; 532 } 533 return userInfo.profileGroupId == otherUserInfo.profileGroupId; 534 } 535 } 536 537 @Override 538 public UserInfo getProfileParent(int userHandle) { 539 checkManageUsersPermission("get the profile parent"); 540 synchronized (mUsersLock) { 541 return getProfileParentLU(userHandle); 542 } 543 } 544 545 private UserInfo getProfileParentLU(int userHandle) { 546 UserInfo profile = getUserInfoLU(userHandle); 547 if (profile == null) { 548 return null; 549 } 550 int parentUserId = profile.profileGroupId; 551 if (parentUserId == UserInfo.NO_PROFILE_GROUP_ID) { 552 return null; 553 } else { 554 return getUserInfoLU(parentUserId); 555 } 556 } 557 558 private static boolean isProfileOf(UserInfo user, UserInfo profile) { 559 return user.id == profile.id || 560 (user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID 561 && user.profileGroupId == profile.profileGroupId); 562 } 563 564 private void broadcastProfileAvailabilityChanges(UserHandle profileHandle, 565 UserHandle parentHandle, boolean inQuietMode) { 566 Intent intent = new Intent(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED); 567 intent.putExtra(Intent.EXTRA_QUIET_MODE, inQuietMode); 568 intent.putExtra(Intent.EXTRA_USER, profileHandle); 569 intent.putExtra(Intent.EXTRA_USER_HANDLE, profileHandle.getIdentifier()); 570 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 571 mContext.sendBroadcastAsUser(intent, parentHandle); 572 } 573 574 @Override 575 public void setQuietModeEnabled(int userHandle, boolean enableQuietMode) { 576 checkManageUsersPermission("silence profile"); 577 boolean changed = false; 578 UserInfo profile, parent; 579 synchronized (mPackagesLock) { 580 synchronized (mUsersLock) { 581 profile = getUserInfoLU(userHandle); 582 parent = getProfileParentLU(userHandle); 583 584 } 585 if (profile == null || !profile.isManagedProfile()) { 586 throw new IllegalArgumentException("User " + userHandle + " is not a profile"); 587 } 588 if (profile.isQuietModeEnabled() != enableQuietMode) { 589 profile.flags ^= UserInfo.FLAG_QUIET_MODE; 590 writeUserLP(getUserDataLU(profile.id)); 591 changed = true; 592 } 593 } 594 if (changed) { 595 long identity = Binder.clearCallingIdentity(); 596 try { 597 if (enableQuietMode) { 598 ActivityManagerNative.getDefault().stopUser(userHandle, /* force */true, null); 599 } else { 600 ActivityManagerNative.getDefault().startUserInBackground(userHandle); 601 } 602 } catch (RemoteException e) { 603 Slog.e(LOG_TAG, "fail to start/stop user for quiet mode", e); 604 } finally { 605 Binder.restoreCallingIdentity(identity); 606 } 607 608 broadcastProfileAvailabilityChanges(profile.getUserHandle(), parent.getUserHandle(), 609 enableQuietMode); 610 } 611 } 612 613 @Override 614 public boolean isQuietModeEnabled(int userHandle) { 615 synchronized (mPackagesLock) { 616 UserInfo info; 617 synchronized (mUsersLock) { 618 info = getUserInfoLU(userHandle); 619 } 620 if (info == null || !info.isManagedProfile()) { 621 return false; 622 } 623 return info.isQuietModeEnabled(); 624 } 625 } 626 627 @Override 628 public void setUserEnabled(int userId) { 629 checkManageUsersPermission("enable user"); 630 synchronized (mPackagesLock) { 631 UserInfo info; 632 synchronized (mUsersLock) { 633 info = getUserInfoLU(userId); 634 } 635 if (info != null && !info.isEnabled()) { 636 info.flags ^= UserInfo.FLAG_DISABLED; 637 writeUserLP(getUserDataLU(info.id)); 638 } 639 } 640 } 641 642 @Override 643 public UserInfo getUserInfo(int userId) { 644 int callingUserId = UserHandle.getCallingUserId(); 645 if (callingUserId != userId && !hasManageUsersPermission()) { 646 synchronized (mPackagesLock) { 647 if (!isSameProfileGroupLP(callingUserId, userId)) { 648 throw new SecurityException( 649 "You need MANAGE_USERS permission to: query users outside profile" + 650 " group"); 651 } 652 } 653 } 654 synchronized (mUsersLock) { 655 return getUserInfoLU(userId); 656 } 657 } 658 659 @Override 660 public boolean isRestricted() { 661 synchronized (mUsersLock) { 662 return getUserInfoLU(UserHandle.getCallingUserId()).isRestricted(); 663 } 664 } 665 666 @Override 667 public boolean canHaveRestrictedProfile(int userId) { 668 checkManageUsersPermission("canHaveRestrictedProfile"); 669 synchronized (mUsersLock) { 670 final UserInfo userInfo = getUserInfoLU(userId); 671 if (userInfo == null || !userInfo.canHaveProfile()) { 672 return false; 673 } 674 if (!userInfo.isAdmin()) { 675 return false; 676 } 677 // restricted profile can be created if there is no DO set and the admin user has no PO; 678 return !mIsDeviceManaged && !mIsUserManaged.get(userId); 679 } 680 } 681 682 /* 683 * Should be locked on mUsers before calling this. 684 */ 685 private UserInfo getUserInfoLU(int userId) { 686 final UserData userData = mUsers.get(userId); 687 // If it is partial and not in the process of being removed, return as unknown user. 688 if (userData != null && userData.info.partial && !mRemovingUserIds.get(userId)) { 689 Slog.w(LOG_TAG, "getUserInfo: unknown user #" + userId); 690 return null; 691 } 692 return userData != null ? userData.info : null; 693 } 694 695 private UserData getUserDataLU(int userId) { 696 final UserData userData = mUsers.get(userId); 697 // If it is partial and not in the process of being removed, return as unknown user. 698 if (userData != null && userData.info.partial && !mRemovingUserIds.get(userId)) { 699 return null; 700 } 701 return userData; 702 } 703 704 /** 705 * Obtains {@link #mUsersLock} and return UserInfo from mUsers. 706 * <p>No permissions checking or any addition checks are made</p> 707 */ 708 private UserInfo getUserInfoNoChecks(int userId) { 709 synchronized (mUsersLock) { 710 final UserData userData = mUsers.get(userId); 711 return userData != null ? userData.info : null; 712 } 713 } 714 715 /** 716 * Obtains {@link #mUsersLock} and return UserData from mUsers. 717 * <p>No permissions checking or any addition checks are made</p> 718 */ 719 private UserData getUserDataNoChecks(int userId) { 720 synchronized (mUsersLock) { 721 return mUsers.get(userId); 722 } 723 } 724 725 /** Called by PackageManagerService */ 726 public boolean exists(int userId) { 727 return getUserInfoNoChecks(userId) != null; 728 } 729 730 @Override 731 public void setUserName(int userId, String name) { 732 checkManageUsersPermission("rename users"); 733 boolean changed = false; 734 synchronized (mPackagesLock) { 735 UserData userData = getUserDataNoChecks(userId); 736 if (userData == null || userData.info.partial) { 737 Slog.w(LOG_TAG, "setUserName: unknown user #" + userId); 738 return; 739 } 740 if (name != null && !name.equals(userData.info.name)) { 741 userData.info.name = name; 742 writeUserLP(userData); 743 changed = true; 744 } 745 } 746 if (changed) { 747 sendUserInfoChangedBroadcast(userId); 748 } 749 } 750 751 @Override 752 public void setUserIcon(int userId, Bitmap bitmap) { 753 checkManageUsersPermission("update users"); 754 if (hasUserRestriction(UserManager.DISALLOW_SET_USER_ICON, userId)) { 755 Log.w(LOG_TAG, "Cannot set user icon. DISALLOW_SET_USER_ICON is enabled."); 756 return; 757 } 758 mLocalService.setUserIcon(userId, bitmap); 759 } 760 761 762 763 private void sendUserInfoChangedBroadcast(int userId) { 764 Intent changedIntent = new Intent(Intent.ACTION_USER_INFO_CHANGED); 765 changedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId); 766 changedIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 767 mContext.sendBroadcastAsUser(changedIntent, UserHandle.ALL); 768 } 769 770 @Override 771 public ParcelFileDescriptor getUserIcon(int targetUserId) { 772 String iconPath; 773 synchronized (mPackagesLock) { 774 UserInfo targetUserInfo = getUserInfoNoChecks(targetUserId); 775 if (targetUserInfo == null || targetUserInfo.partial) { 776 Slog.w(LOG_TAG, "getUserIcon: unknown user #" + targetUserId); 777 return null; 778 } 779 780 final int callingUserId = UserHandle.getCallingUserId(); 781 final int callingGroupId = getUserInfoNoChecks(callingUserId).profileGroupId; 782 final int targetGroupId = targetUserInfo.profileGroupId; 783 final boolean sameGroup = (callingGroupId != UserInfo.NO_PROFILE_GROUP_ID 784 && callingGroupId == targetGroupId); 785 if ((callingUserId != targetUserId) && !sameGroup) { 786 checkManageUsersPermission("get the icon of a user who is not related"); 787 } 788 789 if (targetUserInfo.iconPath == null) { 790 return null; 791 } 792 iconPath = targetUserInfo.iconPath; 793 } 794 795 try { 796 return ParcelFileDescriptor.open( 797 new File(iconPath), ParcelFileDescriptor.MODE_READ_ONLY); 798 } catch (FileNotFoundException e) { 799 Log.e(LOG_TAG, "Couldn't find icon file", e); 800 } 801 return null; 802 } 803 804 public void makeInitialized(int userId) { 805 checkManageUsersPermission("makeInitialized"); 806 boolean scheduleWriteUser = false; 807 UserData userData; 808 synchronized (mUsersLock) { 809 userData = mUsers.get(userId); 810 if (userData == null || userData.info.partial) { 811 Slog.w(LOG_TAG, "makeInitialized: unknown user #" + userId); 812 return; 813 } 814 if ((userData.info.flags & UserInfo.FLAG_INITIALIZED) == 0) { 815 userData.info.flags |= UserInfo.FLAG_INITIALIZED; 816 scheduleWriteUser = true; 817 } 818 } 819 if (scheduleWriteUser) { 820 scheduleWriteUser(userData); 821 } 822 } 823 824 /** 825 * If default guest restrictions haven't been initialized yet, add the basic 826 * restrictions. 827 */ 828 private void initDefaultGuestRestrictions() { 829 synchronized (mGuestRestrictions) { 830 if (mGuestRestrictions.isEmpty()) { 831 mGuestRestrictions.putBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true); 832 mGuestRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, true); 833 mGuestRestrictions.putBoolean(UserManager.DISALLOW_SMS, true); 834 } 835 } 836 } 837 838 @Override 839 public Bundle getDefaultGuestRestrictions() { 840 checkManageUsersPermission("getDefaultGuestRestrictions"); 841 synchronized (mGuestRestrictions) { 842 return new Bundle(mGuestRestrictions); 843 } 844 } 845 846 @Override 847 public void setDefaultGuestRestrictions(Bundle restrictions) { 848 checkManageUsersPermission("setDefaultGuestRestrictions"); 849 synchronized (mGuestRestrictions) { 850 mGuestRestrictions.clear(); 851 mGuestRestrictions.putAll(restrictions); 852 } 853 synchronized (mPackagesLock) { 854 writeUserListLP(); 855 } 856 } 857 858 /** 859 * See {@link UserManagerInternal#setDevicePolicyUserRestrictions(int, Bundle, Bundle)} 860 */ 861 void setDevicePolicyUserRestrictionsInner(int userId, @NonNull Bundle local, 862 @Nullable Bundle global) { 863 Preconditions.checkNotNull(local); 864 boolean globalChanged = false; 865 boolean localChanged; 866 synchronized (mRestrictionsLock) { 867 if (global != null) { 868 // Update global. 869 globalChanged = !UserRestrictionsUtils.areEqual( 870 mDevicePolicyGlobalUserRestrictions, global); 871 if (globalChanged) { 872 mDevicePolicyGlobalUserRestrictions = global; 873 } 874 } 875 { 876 // Update local. 877 final Bundle prev = mDevicePolicyLocalUserRestrictions.get(userId); 878 localChanged = !UserRestrictionsUtils.areEqual(prev, local); 879 if (localChanged) { 880 mDevicePolicyLocalUserRestrictions.put(userId, local); 881 } 882 } 883 } 884 if (DBG) { 885 Log.d(LOG_TAG, "setDevicePolicyUserRestrictions: userId=" + userId 886 + " global=" + global + (globalChanged ? " (changed)" : "") 887 + " local=" + local + (localChanged ? " (changed)" : "") 888 ); 889 } 890 // Don't call them within the mRestrictionsLock. 891 synchronized (mPackagesLock) { 892 if (globalChanged) { 893 writeUserListLP(); 894 } 895 if (localChanged) { 896 writeUserLP(getUserDataNoChecks(userId)); 897 } 898 } 899 900 synchronized (mRestrictionsLock) { 901 if (globalChanged) { 902 applyUserRestrictionsForAllUsersLR(); 903 } else if (localChanged) { 904 applyUserRestrictionsLR(userId); 905 } 906 } 907 } 908 909 @GuardedBy("mRestrictionsLock") 910 private Bundle computeEffectiveUserRestrictionsLR(int userId) { 911 final Bundle baseRestrictions = 912 UserRestrictionsUtils.nonNull(mBaseUserRestrictions.get(userId)); 913 final Bundle global = mDevicePolicyGlobalUserRestrictions; 914 final Bundle local = mDevicePolicyLocalUserRestrictions.get(userId); 915 916 if (UserRestrictionsUtils.isEmpty(global) && UserRestrictionsUtils.isEmpty(local)) { 917 // Common case first. 918 return baseRestrictions; 919 } 920 final Bundle effective = UserRestrictionsUtils.clone(baseRestrictions); 921 UserRestrictionsUtils.merge(effective, global); 922 UserRestrictionsUtils.merge(effective, local); 923 924 return effective; 925 } 926 927 @GuardedBy("mRestrictionsLock") 928 private void invalidateEffectiveUserRestrictionsLR(int userId) { 929 if (DBG) { 930 Log.d(LOG_TAG, "invalidateEffectiveUserRestrictions userId=" + userId); 931 } 932 mCachedEffectiveUserRestrictions.remove(userId); 933 } 934 935 private Bundle getEffectiveUserRestrictions(int userId) { 936 synchronized (mRestrictionsLock) { 937 Bundle restrictions = mCachedEffectiveUserRestrictions.get(userId); 938 if (restrictions == null) { 939 restrictions = computeEffectiveUserRestrictionsLR(userId); 940 mCachedEffectiveUserRestrictions.put(userId, restrictions); 941 } 942 return restrictions; 943 } 944 } 945 946 /** @return a specific user restriction that's in effect currently. */ 947 @Override 948 public boolean hasUserRestriction(String restrictionKey, int userId) { 949 if (!UserRestrictionsUtils.isValidRestriction(restrictionKey)) { 950 return false; 951 } 952 Bundle restrictions = getEffectiveUserRestrictions(userId); 953 return restrictions != null && restrictions.getBoolean(restrictionKey); 954 } 955 956 /** 957 * @return UserRestrictions that are in effect currently. This always returns a new 958 * {@link Bundle}. 959 */ 960 @Override 961 public Bundle getUserRestrictions(int userId) { 962 return UserRestrictionsUtils.clone(getEffectiveUserRestrictions(userId)); 963 } 964 965 @Override 966 public boolean hasBaseUserRestriction(String restrictionKey, int userId) { 967 checkManageUsersPermission("hasBaseUserRestriction"); 968 if (!UserRestrictionsUtils.isValidRestriction(restrictionKey)) { 969 return false; 970 } 971 synchronized (mRestrictionsLock) { 972 Bundle bundle = mBaseUserRestrictions.get(userId); 973 return (bundle != null && bundle.getBoolean(restrictionKey, false)); 974 } 975 } 976 977 @Override 978 public void setUserRestriction(String key, boolean value, int userId) { 979 checkManageUsersPermission("setUserRestriction"); 980 if (!UserRestrictionsUtils.isValidRestriction(key)) { 981 return; 982 } 983 synchronized (mRestrictionsLock) { 984 // Note we can't modify Bundles stored in mBaseUserRestrictions directly, so create 985 // a copy. 986 final Bundle newRestrictions = UserRestrictionsUtils.clone( 987 mBaseUserRestrictions.get(userId)); 988 newRestrictions.putBoolean(key, value); 989 990 updateUserRestrictionsInternalLR(newRestrictions, userId); 991 } 992 } 993 994 /** 995 * Optionally updating user restrictions, calculate the effective user restrictions and also 996 * propagate to other services and system settings. 997 * 998 * @param newRestrictions User restrictions to set. 999 * If null, will not update user restrictions and only does the propagation. 1000 * @param userId target user ID. 1001 */ 1002 @GuardedBy("mRestrictionsLock") 1003 private void updateUserRestrictionsInternalLR( 1004 @Nullable Bundle newRestrictions, int userId) { 1005 1006 final Bundle prevAppliedRestrictions = UserRestrictionsUtils.nonNull( 1007 mAppliedUserRestrictions.get(userId)); 1008 1009 // Update base restrictions. 1010 if (newRestrictions != null) { 1011 // If newRestrictions == the current one, it's probably a bug. 1012 final Bundle prevBaseRestrictions = mBaseUserRestrictions.get(userId); 1013 1014 Preconditions.checkState(prevBaseRestrictions != newRestrictions); 1015 Preconditions.checkState(mCachedEffectiveUserRestrictions.get(userId) 1016 != newRestrictions); 1017 1018 if (!UserRestrictionsUtils.areEqual(prevBaseRestrictions, newRestrictions)) { 1019 mBaseUserRestrictions.put(userId, newRestrictions); 1020 scheduleWriteUser(getUserDataNoChecks(userId)); 1021 } 1022 } 1023 1024 final Bundle effective = computeEffectiveUserRestrictionsLR(userId); 1025 1026 mCachedEffectiveUserRestrictions.put(userId, effective); 1027 1028 // Apply the new restrictions. 1029 if (DBG) { 1030 debug("Applying user restrictions: userId=" + userId 1031 + " new=" + effective + " prev=" + prevAppliedRestrictions); 1032 } 1033 1034 if (mAppOpsService != null) { // We skip it until system-ready. 1035 final long token = Binder.clearCallingIdentity(); 1036 try { 1037 mAppOpsService.setUserRestrictions(effective, mUserRestriconToken, userId); 1038 } catch (RemoteException e) { 1039 Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions"); 1040 } finally { 1041 Binder.restoreCallingIdentity(token); 1042 } 1043 } 1044 1045 propagateUserRestrictionsLR(userId, effective, prevAppliedRestrictions); 1046 1047 mAppliedUserRestrictions.put(userId, new Bundle(effective)); 1048 } 1049 1050 private void propagateUserRestrictionsLR(final int userId, 1051 Bundle newRestrictions, Bundle prevRestrictions) { 1052 // Note this method doesn't touch any state, meaning it doesn't require mRestrictionsLock 1053 // actually, but we still need some kind of synchronization otherwise we might end up 1054 // calling listeners out-of-order, thus "LR". 1055 1056 if (UserRestrictionsUtils.areEqual(newRestrictions, prevRestrictions)) { 1057 return; 1058 } 1059 1060 final Bundle newRestrictionsFinal = new Bundle(newRestrictions); 1061 final Bundle prevRestrictionsFinal = new Bundle(prevRestrictions); 1062 1063 mHandler.post(new Runnable() { 1064 @Override 1065 public void run() { 1066 UserRestrictionsUtils.applyUserRestrictions( 1067 mContext, userId, newRestrictionsFinal, prevRestrictionsFinal); 1068 1069 final UserRestrictionsListener[] listeners; 1070 synchronized (mUserRestrictionsListeners) { 1071 listeners = new UserRestrictionsListener[mUserRestrictionsListeners.size()]; 1072 mUserRestrictionsListeners.toArray(listeners); 1073 } 1074 for (int i = 0; i < listeners.length; i++) { 1075 listeners[i].onUserRestrictionsChanged(userId, 1076 newRestrictionsFinal, prevRestrictionsFinal); 1077 } 1078 } 1079 }); 1080 } 1081 1082 // Package private for the inner class. 1083 void applyUserRestrictionsLR(int userId) { 1084 updateUserRestrictionsInternalLR(null, userId); 1085 } 1086 1087 @GuardedBy("mRestrictionsLock") 1088 // Package private for the inner class. 1089 void applyUserRestrictionsForAllUsersLR() { 1090 if (DBG) { 1091 debug("applyUserRestrictionsForAllUsersLR"); 1092 } 1093 // First, invalidate all cached values. 1094 mCachedEffectiveUserRestrictions.clear(); 1095 1096 // We don't want to call into ActivityManagerNative while taking a lock, so we'll call 1097 // it on a handler. 1098 final Runnable r = new Runnable() { 1099 @Override 1100 public void run() { 1101 // Then get the list of running users. 1102 final int[] runningUsers; 1103 try { 1104 runningUsers = ActivityManagerNative.getDefault().getRunningUserIds(); 1105 } catch (RemoteException e) { 1106 Log.w(LOG_TAG, "Unable to access ActivityManagerNative"); 1107 return; 1108 } 1109 // Then re-calculate the effective restrictions and apply, only for running users. 1110 // It's okay if a new user has started after the getRunningUserIds() call, 1111 // because we'll do the same thing (re-calculate the restrictions and apply) 1112 // when we start a user. 1113 synchronized (mRestrictionsLock) { 1114 for (int i = 0; i < runningUsers.length; i++) { 1115 applyUserRestrictionsLR(runningUsers[i]); 1116 } 1117 } 1118 } 1119 }; 1120 mHandler.post(r); 1121 } 1122 1123 /** 1124 * Check if we've hit the limit of how many users can be created. 1125 */ 1126 private boolean isUserLimitReached() { 1127 int count; 1128 synchronized (mUsersLock) { 1129 count = getAliveUsersExcludingGuestsCountLU(); 1130 } 1131 return count >= UserManager.getMaxSupportedUsers(); 1132 } 1133 1134 @Override 1135 public boolean canAddMoreManagedProfiles(int userId, boolean allowedToRemoveOne) { 1136 checkManageUsersPermission("check if more managed profiles can be added."); 1137 if (ActivityManager.isLowRamDeviceStatic()) { 1138 return false; 1139 } 1140 if (!mContext.getPackageManager().hasSystemFeature( 1141 PackageManager.FEATURE_MANAGED_USERS)) { 1142 return false; 1143 } 1144 // Limit number of managed profiles that can be created 1145 final int managedProfilesCount = getProfiles(userId, true).size() - 1; 1146 final int profilesRemovedCount = managedProfilesCount > 0 && allowedToRemoveOne ? 1 : 0; 1147 if (managedProfilesCount - profilesRemovedCount >= MAX_MANAGED_PROFILES) { 1148 return false; 1149 } 1150 synchronized(mUsersLock) { 1151 UserInfo userInfo = getUserInfoLU(userId); 1152 if (!userInfo.canHaveProfile()) { 1153 return false; 1154 } 1155 int usersCountAfterRemoving = getAliveUsersExcludingGuestsCountLU() 1156 - profilesRemovedCount; 1157 // We allow creating a managed profile in the special case where there is only one user. 1158 return usersCountAfterRemoving == 1 1159 || usersCountAfterRemoving < UserManager.getMaxSupportedUsers(); 1160 } 1161 } 1162 1163 private int getAliveUsersExcludingGuestsCountLU() { 1164 int aliveUserCount = 0; 1165 final int totalUserCount = mUsers.size(); 1166 // Skip over users being removed 1167 for (int i = 0; i < totalUserCount; i++) { 1168 UserInfo user = mUsers.valueAt(i).info; 1169 if (!mRemovingUserIds.get(user.id) 1170 && !user.isGuest() && !user.partial) { 1171 aliveUserCount++; 1172 } 1173 } 1174 return aliveUserCount; 1175 } 1176 1177 /** 1178 * Enforces that only the system UID or root's UID or apps that have the 1179 * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} and 1180 * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL INTERACT_ACROSS_USERS_FULL} 1181 * permissions can make certain calls to the UserManager. 1182 * 1183 * @param message used as message if SecurityException is thrown 1184 * @throws SecurityException if the caller does not have enough privilege. 1185 */ 1186 private static final void checkManageUserAndAcrossUsersFullPermission(String message) { 1187 final int uid = Binder.getCallingUid(); 1188 if (uid != Process.SYSTEM_UID && uid != 0 1189 && ActivityManager.checkComponentPermission( 1190 Manifest.permission.MANAGE_USERS, 1191 uid, -1, true) != PackageManager.PERMISSION_GRANTED 1192 && ActivityManager.checkComponentPermission( 1193 Manifest.permission.INTERACT_ACROSS_USERS_FULL, 1194 uid, -1, true) != PackageManager.PERMISSION_GRANTED) { 1195 throw new SecurityException( 1196 "You need MANAGE_USERS and INTERACT_ACROSS_USERS_FULL permission to: " 1197 + message); 1198 } 1199 } 1200 1201 /** 1202 * Enforces that only the system UID or root's UID or apps that have the 1203 * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} 1204 * permission can make certain calls to the UserManager. 1205 * 1206 * @param message used as message if SecurityException is thrown 1207 * @throws SecurityException if the caller is not system or root 1208 * @see #hasManageUsersPermission() 1209 */ 1210 private static final void checkManageUsersPermission(String message) { 1211 if (!hasManageUsersPermission()) { 1212 throw new SecurityException("You need MANAGE_USERS permission to: " + message); 1213 } 1214 } 1215 1216 /** 1217 * @return whether the calling UID is system UID or root's UID or the calling app has the 1218 * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS}. 1219 */ 1220 private static final boolean hasManageUsersPermission() { 1221 final int callingUid = Binder.getCallingUid(); 1222 return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID) 1223 || callingUid == Process.ROOT_UID 1224 || ActivityManager.checkComponentPermission( 1225 android.Manifest.permission.MANAGE_USERS, 1226 callingUid, -1, true) == PackageManager.PERMISSION_GRANTED; 1227 } 1228 1229 /** 1230 * Enforces that only the system UID or root's UID (on any user) can make certain calls to the 1231 * UserManager. 1232 * 1233 * @param message used as message if SecurityException is thrown 1234 * @throws SecurityException if the caller is not system or root 1235 */ 1236 private static void checkSystemOrRoot(String message) { 1237 final int uid = Binder.getCallingUid(); 1238 if (!UserHandle.isSameApp(uid, Process.SYSTEM_UID) && uid != Process.ROOT_UID) { 1239 throw new SecurityException("Only system may: " + message); 1240 } 1241 } 1242 1243 private void writeBitmapLP(UserInfo info, Bitmap bitmap) { 1244 try { 1245 File dir = new File(mUsersDir, Integer.toString(info.id)); 1246 File file = new File(dir, USER_PHOTO_FILENAME); 1247 File tmp = new File(dir, USER_PHOTO_FILENAME_TMP); 1248 if (!dir.exists()) { 1249 dir.mkdir(); 1250 FileUtils.setPermissions( 1251 dir.getPath(), 1252 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH, 1253 -1, -1); 1254 } 1255 FileOutputStream os; 1256 if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, os = new FileOutputStream(tmp)) 1257 && tmp.renameTo(file) && SELinux.restorecon(file)) { 1258 info.iconPath = file.getAbsolutePath(); 1259 } 1260 try { 1261 os.close(); 1262 } catch (IOException ioe) { 1263 // What the ... ! 1264 } 1265 tmp.delete(); 1266 } catch (FileNotFoundException e) { 1267 Slog.w(LOG_TAG, "Error setting photo for user ", e); 1268 } 1269 } 1270 1271 /** 1272 * Returns an array of user ids. This array is cached here for quick access, so do not modify or 1273 * cache it elsewhere. 1274 * @return the array of user ids. 1275 */ 1276 public int[] getUserIds() { 1277 synchronized (mUsersLock) { 1278 return mUserIds; 1279 } 1280 } 1281 1282 private void readUserListLP() { 1283 if (!mUserListFile.exists()) { 1284 fallbackToSingleUserLP(); 1285 return; 1286 } 1287 FileInputStream fis = null; 1288 AtomicFile userListFile = new AtomicFile(mUserListFile); 1289 try { 1290 fis = userListFile.openRead(); 1291 XmlPullParser parser = Xml.newPullParser(); 1292 parser.setInput(fis, StandardCharsets.UTF_8.name()); 1293 int type; 1294 while ((type = parser.next()) != XmlPullParser.START_TAG 1295 && type != XmlPullParser.END_DOCUMENT) { 1296 // Skip 1297 } 1298 1299 if (type != XmlPullParser.START_TAG) { 1300 Slog.e(LOG_TAG, "Unable to read user list"); 1301 fallbackToSingleUserLP(); 1302 return; 1303 } 1304 1305 mNextSerialNumber = -1; 1306 if (parser.getName().equals(TAG_USERS)) { 1307 String lastSerialNumber = parser.getAttributeValue(null, ATTR_NEXT_SERIAL_NO); 1308 if (lastSerialNumber != null) { 1309 mNextSerialNumber = Integer.parseInt(lastSerialNumber); 1310 } 1311 String versionNumber = parser.getAttributeValue(null, ATTR_USER_VERSION); 1312 if (versionNumber != null) { 1313 mUserVersion = Integer.parseInt(versionNumber); 1314 } 1315 } 1316 1317 final Bundle newDevicePolicyGlobalUserRestrictions = new Bundle(); 1318 1319 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { 1320 if (type == XmlPullParser.START_TAG) { 1321 final String name = parser.getName(); 1322 if (name.equals(TAG_USER)) { 1323 String id = parser.getAttributeValue(null, ATTR_ID); 1324 1325 UserData userData = readUserLP(Integer.parseInt(id)); 1326 1327 if (userData != null) { 1328 synchronized (mUsersLock) { 1329 mUsers.put(userData.info.id, userData); 1330 if (mNextSerialNumber < 0 1331 || mNextSerialNumber <= userData.info.id) { 1332 mNextSerialNumber = userData.info.id + 1; 1333 } 1334 } 1335 } 1336 } else if (name.equals(TAG_GUEST_RESTRICTIONS)) { 1337 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 1338 && type != XmlPullParser.END_TAG) { 1339 if (type == XmlPullParser.START_TAG) { 1340 if (parser.getName().equals(TAG_RESTRICTIONS)) { 1341 synchronized (mGuestRestrictions) { 1342 UserRestrictionsUtils 1343 .readRestrictions(parser, mGuestRestrictions); 1344 } 1345 } else if (parser.getName().equals(TAG_DEVICE_POLICY_RESTRICTIONS) 1346 ) { 1347 UserRestrictionsUtils.readRestrictions(parser, 1348 newDevicePolicyGlobalUserRestrictions); 1349 } 1350 break; 1351 } 1352 } 1353 } 1354 } 1355 } 1356 synchronized (mRestrictionsLock) { 1357 mDevicePolicyGlobalUserRestrictions = newDevicePolicyGlobalUserRestrictions; 1358 } 1359 updateUserIds(); 1360 upgradeIfNecessaryLP(); 1361 } catch (IOException | XmlPullParserException e) { 1362 fallbackToSingleUserLP(); 1363 } finally { 1364 IoUtils.closeQuietly(fis); 1365 } 1366 } 1367 1368 /** 1369 * Upgrade steps between versions, either for fixing bugs or changing the data format. 1370 */ 1371 private void upgradeIfNecessaryLP() { 1372 final int originalVersion = mUserVersion; 1373 int userVersion = mUserVersion; 1374 if (userVersion < 1) { 1375 // Assign a proper name for the owner, if not initialized correctly before 1376 UserData userData = getUserDataNoChecks(UserHandle.USER_SYSTEM); 1377 if ("Primary".equals(userData.info.name)) { 1378 userData.info.name = 1379 mContext.getResources().getString(com.android.internal.R.string.owner_name); 1380 scheduleWriteUser(userData); 1381 } 1382 userVersion = 1; 1383 } 1384 1385 if (userVersion < 2) { 1386 // Owner should be marked as initialized 1387 UserData userData = getUserDataNoChecks(UserHandle.USER_SYSTEM); 1388 if ((userData.info.flags & UserInfo.FLAG_INITIALIZED) == 0) { 1389 userData.info.flags |= UserInfo.FLAG_INITIALIZED; 1390 scheduleWriteUser(userData); 1391 } 1392 userVersion = 2; 1393 } 1394 1395 1396 if (userVersion < 4) { 1397 userVersion = 4; 1398 } 1399 1400 if (userVersion < 5) { 1401 initDefaultGuestRestrictions(); 1402 userVersion = 5; 1403 } 1404 1405 if (userVersion < 6) { 1406 final boolean splitSystemUser = UserManager.isSplitSystemUser(); 1407 synchronized (mUsersLock) { 1408 for (int i = 0; i < mUsers.size(); i++) { 1409 UserData userData = mUsers.valueAt(i); 1410 // In non-split mode, only user 0 can have restricted profiles 1411 if (!splitSystemUser && userData.info.isRestricted() 1412 && (userData.info.restrictedProfileParentId 1413 == UserInfo.NO_PROFILE_GROUP_ID)) { 1414 userData.info.restrictedProfileParentId = UserHandle.USER_SYSTEM; 1415 scheduleWriteUser(userData); 1416 } 1417 } 1418 } 1419 userVersion = 6; 1420 } 1421 1422 if (userVersion < USER_VERSION) { 1423 Slog.w(LOG_TAG, "User version " + mUserVersion + " didn't upgrade as expected to " 1424 + USER_VERSION); 1425 } else { 1426 mUserVersion = userVersion; 1427 1428 if (originalVersion < mUserVersion) { 1429 writeUserListLP(); 1430 } 1431 } 1432 } 1433 1434 private void fallbackToSingleUserLP() { 1435 int flags = UserInfo.FLAG_INITIALIZED; 1436 // In split system user mode, the admin and primary flags are assigned to the first human 1437 // user. 1438 if (!UserManager.isSplitSystemUser()) { 1439 flags |= UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY; 1440 } 1441 // Create the system user 1442 UserInfo system = new UserInfo(UserHandle.USER_SYSTEM, 1443 mContext.getResources().getString(com.android.internal.R.string.owner_name), null, 1444 flags); 1445 UserData userData = new UserData(); 1446 userData.info = system; 1447 synchronized (mUsersLock) { 1448 mUsers.put(system.id, userData); 1449 } 1450 mNextSerialNumber = MIN_USER_ID; 1451 mUserVersion = USER_VERSION; 1452 1453 Bundle restrictions = new Bundle(); 1454 synchronized (mRestrictionsLock) { 1455 mBaseUserRestrictions.append(UserHandle.USER_SYSTEM, restrictions); 1456 } 1457 1458 updateUserIds(); 1459 initDefaultGuestRestrictions(); 1460 1461 writeUserListLP(); 1462 writeUserLP(userData); 1463 } 1464 1465 private void scheduleWriteUser(UserData UserData) { 1466 if (DBG) { 1467 debug("scheduleWriteUser"); 1468 } 1469 // No need to wrap it within a lock -- worst case, we'll just post the same message 1470 // twice. 1471 if (!mHandler.hasMessages(WRITE_USER_MSG, UserData)) { 1472 Message msg = mHandler.obtainMessage(WRITE_USER_MSG, UserData); 1473 mHandler.sendMessageDelayed(msg, WRITE_USER_DELAY); 1474 } 1475 } 1476 1477 /* 1478 * Writes the user file in this format: 1479 * 1480 * <user flags="20039023" id="0"> 1481 * <name>Primary</name> 1482 * </user> 1483 */ 1484 private void writeUserLP(UserData userData) { 1485 if (DBG) { 1486 debug("writeUserLP " + userData); 1487 } 1488 FileOutputStream fos = null; 1489 AtomicFile userFile = new AtomicFile(new File(mUsersDir, userData.info.id + XML_SUFFIX)); 1490 try { 1491 fos = userFile.startWrite(); 1492 final BufferedOutputStream bos = new BufferedOutputStream(fos); 1493 1494 // XmlSerializer serializer = XmlUtils.serializerInstance(); 1495 final XmlSerializer serializer = new FastXmlSerializer(); 1496 serializer.setOutput(bos, StandardCharsets.UTF_8.name()); 1497 serializer.startDocument(null, true); 1498 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); 1499 1500 final UserInfo userInfo = userData.info; 1501 serializer.startTag(null, TAG_USER); 1502 serializer.attribute(null, ATTR_ID, Integer.toString(userInfo.id)); 1503 serializer.attribute(null, ATTR_SERIAL_NO, Integer.toString(userInfo.serialNumber)); 1504 serializer.attribute(null, ATTR_FLAGS, Integer.toString(userInfo.flags)); 1505 serializer.attribute(null, ATTR_CREATION_TIME, Long.toString(userInfo.creationTime)); 1506 serializer.attribute(null, ATTR_LAST_LOGGED_IN_TIME, 1507 Long.toString(userInfo.lastLoggedInTime)); 1508 if (userInfo.iconPath != null) { 1509 serializer.attribute(null, ATTR_ICON_PATH, userInfo.iconPath); 1510 } 1511 if (userInfo.partial) { 1512 serializer.attribute(null, ATTR_PARTIAL, "true"); 1513 } 1514 if (userInfo.guestToRemove) { 1515 serializer.attribute(null, ATTR_GUEST_TO_REMOVE, "true"); 1516 } 1517 if (userInfo.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID) { 1518 serializer.attribute(null, ATTR_PROFILE_GROUP_ID, 1519 Integer.toString(userInfo.profileGroupId)); 1520 } 1521 if (userInfo.restrictedProfileParentId != UserInfo.NO_PROFILE_GROUP_ID) { 1522 serializer.attribute(null, ATTR_RESTRICTED_PROFILE_PARENT_ID, 1523 Integer.toString(userInfo.restrictedProfileParentId)); 1524 } 1525 // Write seed data 1526 if (userData.persistSeedData) { 1527 if (userData.seedAccountName != null) { 1528 serializer.attribute(null, ATTR_SEED_ACCOUNT_NAME, userData.seedAccountName); 1529 } 1530 if (userData.seedAccountType != null) { 1531 serializer.attribute(null, ATTR_SEED_ACCOUNT_TYPE, userData.seedAccountType); 1532 } 1533 } 1534 serializer.startTag(null, TAG_NAME); 1535 serializer.text(userInfo.name); 1536 serializer.endTag(null, TAG_NAME); 1537 synchronized (mRestrictionsLock) { 1538 UserRestrictionsUtils.writeRestrictions(serializer, 1539 mBaseUserRestrictions.get(userInfo.id), TAG_RESTRICTIONS); 1540 UserRestrictionsUtils.writeRestrictions(serializer, 1541 mDevicePolicyLocalUserRestrictions.get(userInfo.id), 1542 TAG_DEVICE_POLICY_RESTRICTIONS); 1543 } 1544 1545 if (userData.account != null) { 1546 serializer.startTag(null, TAG_ACCOUNT); 1547 serializer.text(userData.account); 1548 serializer.endTag(null, TAG_ACCOUNT); 1549 } 1550 1551 if (userData.persistSeedData && userData.seedAccountOptions != null) { 1552 serializer.startTag(null, TAG_SEED_ACCOUNT_OPTIONS); 1553 userData.seedAccountOptions.saveToXml(serializer); 1554 serializer.endTag(null, TAG_SEED_ACCOUNT_OPTIONS); 1555 } 1556 serializer.endTag(null, TAG_USER); 1557 1558 serializer.endDocument(); 1559 userFile.finishWrite(fos); 1560 } catch (Exception ioe) { 1561 Slog.e(LOG_TAG, "Error writing user info " + userData.info.id + "\n" + ioe); 1562 userFile.failWrite(fos); 1563 } 1564 } 1565 1566 /* 1567 * Writes the user list file in this format: 1568 * 1569 * <users nextSerialNumber="3"> 1570 * <user id="0"></user> 1571 * <user id="2"></user> 1572 * </users> 1573 */ 1574 private void writeUserListLP() { 1575 if (DBG) { 1576 debug("writeUserList"); 1577 } 1578 FileOutputStream fos = null; 1579 AtomicFile userListFile = new AtomicFile(mUserListFile); 1580 try { 1581 fos = userListFile.startWrite(); 1582 final BufferedOutputStream bos = new BufferedOutputStream(fos); 1583 1584 // XmlSerializer serializer = XmlUtils.serializerInstance(); 1585 final XmlSerializer serializer = new FastXmlSerializer(); 1586 serializer.setOutput(bos, StandardCharsets.UTF_8.name()); 1587 serializer.startDocument(null, true); 1588 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); 1589 1590 serializer.startTag(null, TAG_USERS); 1591 serializer.attribute(null, ATTR_NEXT_SERIAL_NO, Integer.toString(mNextSerialNumber)); 1592 serializer.attribute(null, ATTR_USER_VERSION, Integer.toString(mUserVersion)); 1593 1594 serializer.startTag(null, TAG_GUEST_RESTRICTIONS); 1595 synchronized (mGuestRestrictions) { 1596 UserRestrictionsUtils 1597 .writeRestrictions(serializer, mGuestRestrictions, TAG_RESTRICTIONS); 1598 } 1599 serializer.endTag(null, TAG_GUEST_RESTRICTIONS); 1600 synchronized (mRestrictionsLock) { 1601 UserRestrictionsUtils.writeRestrictions(serializer, 1602 mDevicePolicyGlobalUserRestrictions, TAG_DEVICE_POLICY_RESTRICTIONS); 1603 } 1604 int[] userIdsToWrite; 1605 synchronized (mUsersLock) { 1606 userIdsToWrite = new int[mUsers.size()]; 1607 for (int i = 0; i < userIdsToWrite.length; i++) { 1608 UserInfo user = mUsers.valueAt(i).info; 1609 userIdsToWrite[i] = user.id; 1610 } 1611 } 1612 for (int id : userIdsToWrite) { 1613 serializer.startTag(null, TAG_USER); 1614 serializer.attribute(null, ATTR_ID, Integer.toString(id)); 1615 serializer.endTag(null, TAG_USER); 1616 } 1617 1618 serializer.endTag(null, TAG_USERS); 1619 1620 serializer.endDocument(); 1621 userListFile.finishWrite(fos); 1622 } catch (Exception e) { 1623 userListFile.failWrite(fos); 1624 Slog.e(LOG_TAG, "Error writing user list"); 1625 } 1626 } 1627 1628 private UserData readUserLP(int id) { 1629 int flags = 0; 1630 int serialNumber = id; 1631 String name = null; 1632 String account = null; 1633 String iconPath = null; 1634 long creationTime = 0L; 1635 long lastLoggedInTime = 0L; 1636 int profileGroupId = UserInfo.NO_PROFILE_GROUP_ID; 1637 int restrictedProfileParentId = UserInfo.NO_PROFILE_GROUP_ID; 1638 boolean partial = false; 1639 boolean guestToRemove = false; 1640 boolean persistSeedData = false; 1641 String seedAccountName = null; 1642 String seedAccountType = null; 1643 PersistableBundle seedAccountOptions = null; 1644 Bundle baseRestrictions = new Bundle(); 1645 Bundle localRestrictions = new Bundle(); 1646 1647 FileInputStream fis = null; 1648 try { 1649 AtomicFile userFile = 1650 new AtomicFile(new File(mUsersDir, Integer.toString(id) + XML_SUFFIX)); 1651 fis = userFile.openRead(); 1652 XmlPullParser parser = Xml.newPullParser(); 1653 parser.setInput(fis, StandardCharsets.UTF_8.name()); 1654 int type; 1655 while ((type = parser.next()) != XmlPullParser.START_TAG 1656 && type != XmlPullParser.END_DOCUMENT) { 1657 // Skip 1658 } 1659 1660 if (type != XmlPullParser.START_TAG) { 1661 Slog.e(LOG_TAG, "Unable to read user " + id); 1662 return null; 1663 } 1664 1665 if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_USER)) { 1666 int storedId = readIntAttribute(parser, ATTR_ID, -1); 1667 if (storedId != id) { 1668 Slog.e(LOG_TAG, "User id does not match the file name"); 1669 return null; 1670 } 1671 serialNumber = readIntAttribute(parser, ATTR_SERIAL_NO, id); 1672 flags = readIntAttribute(parser, ATTR_FLAGS, 0); 1673 iconPath = parser.getAttributeValue(null, ATTR_ICON_PATH); 1674 creationTime = readLongAttribute(parser, ATTR_CREATION_TIME, 0); 1675 lastLoggedInTime = readLongAttribute(parser, ATTR_LAST_LOGGED_IN_TIME, 0); 1676 profileGroupId = readIntAttribute(parser, ATTR_PROFILE_GROUP_ID, 1677 UserInfo.NO_PROFILE_GROUP_ID); 1678 restrictedProfileParentId = readIntAttribute(parser, 1679 ATTR_RESTRICTED_PROFILE_PARENT_ID, UserInfo.NO_PROFILE_GROUP_ID); 1680 String valueString = parser.getAttributeValue(null, ATTR_PARTIAL); 1681 if ("true".equals(valueString)) { 1682 partial = true; 1683 } 1684 valueString = parser.getAttributeValue(null, ATTR_GUEST_TO_REMOVE); 1685 if ("true".equals(valueString)) { 1686 guestToRemove = true; 1687 } 1688 1689 seedAccountName = parser.getAttributeValue(null, ATTR_SEED_ACCOUNT_NAME); 1690 seedAccountType = parser.getAttributeValue(null, ATTR_SEED_ACCOUNT_TYPE); 1691 if (seedAccountName != null || seedAccountType != null) { 1692 persistSeedData = true; 1693 } 1694 1695 int outerDepth = parser.getDepth(); 1696 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 1697 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 1698 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 1699 continue; 1700 } 1701 String tag = parser.getName(); 1702 if (TAG_NAME.equals(tag)) { 1703 type = parser.next(); 1704 if (type == XmlPullParser.TEXT) { 1705 name = parser.getText(); 1706 } 1707 } else if (TAG_RESTRICTIONS.equals(tag)) { 1708 UserRestrictionsUtils.readRestrictions(parser, baseRestrictions); 1709 } else if (TAG_DEVICE_POLICY_RESTRICTIONS.equals(tag)) { 1710 UserRestrictionsUtils.readRestrictions(parser, localRestrictions); 1711 } else if (TAG_ACCOUNT.equals(tag)) { 1712 type = parser.next(); 1713 if (type == XmlPullParser.TEXT) { 1714 account = parser.getText(); 1715 } 1716 } else if (TAG_SEED_ACCOUNT_OPTIONS.equals(tag)) { 1717 seedAccountOptions = PersistableBundle.restoreFromXml(parser); 1718 persistSeedData = true; 1719 } 1720 } 1721 } 1722 1723 // Create the UserInfo object that gets passed around 1724 UserInfo userInfo = new UserInfo(id, name, iconPath, flags); 1725 userInfo.serialNumber = serialNumber; 1726 userInfo.creationTime = creationTime; 1727 userInfo.lastLoggedInTime = lastLoggedInTime; 1728 userInfo.partial = partial; 1729 userInfo.guestToRemove = guestToRemove; 1730 userInfo.profileGroupId = profileGroupId; 1731 userInfo.restrictedProfileParentId = restrictedProfileParentId; 1732 1733 // Create the UserData object that's internal to this class 1734 UserData userData = new UserData(); 1735 userData.info = userInfo; 1736 userData.account = account; 1737 userData.seedAccountName = seedAccountName; 1738 userData.seedAccountType = seedAccountType; 1739 userData.persistSeedData = persistSeedData; 1740 userData.seedAccountOptions = seedAccountOptions; 1741 1742 synchronized (mRestrictionsLock) { 1743 mBaseUserRestrictions.put(id, baseRestrictions); 1744 mDevicePolicyLocalUserRestrictions.put(id, localRestrictions); 1745 } 1746 return userData; 1747 } catch (IOException ioe) { 1748 } catch (XmlPullParserException pe) { 1749 } finally { 1750 if (fis != null) { 1751 try { 1752 fis.close(); 1753 } catch (IOException e) { 1754 } 1755 } 1756 } 1757 return null; 1758 } 1759 1760 private int readIntAttribute(XmlPullParser parser, String attr, int defaultValue) { 1761 String valueString = parser.getAttributeValue(null, attr); 1762 if (valueString == null) return defaultValue; 1763 try { 1764 return Integer.parseInt(valueString); 1765 } catch (NumberFormatException nfe) { 1766 return defaultValue; 1767 } 1768 } 1769 1770 private long readLongAttribute(XmlPullParser parser, String attr, long defaultValue) { 1771 String valueString = parser.getAttributeValue(null, attr); 1772 if (valueString == null) return defaultValue; 1773 try { 1774 return Long.parseLong(valueString); 1775 } catch (NumberFormatException nfe) { 1776 return defaultValue; 1777 } 1778 } 1779 1780 /** 1781 * Removes the app restrictions file for a specific package and user id, if it exists. 1782 */ 1783 private void cleanAppRestrictionsForPackage(String pkg, int userId) { 1784 synchronized (mPackagesLock) { 1785 File dir = Environment.getUserSystemDirectory(userId); 1786 File resFile = new File(dir, packageToRestrictionsFileName(pkg)); 1787 if (resFile.exists()) { 1788 resFile.delete(); 1789 } 1790 } 1791 } 1792 1793 @Override 1794 public UserInfo createProfileForUser(String name, int flags, int userId) { 1795 checkManageUsersPermission("Only the system can create users"); 1796 return createUserInternal(name, flags, userId); 1797 } 1798 1799 @Override 1800 public UserInfo createUser(String name, int flags) { 1801 checkManageUsersPermission("Only the system can create users"); 1802 return createUserInternal(name, flags, UserHandle.USER_NULL); 1803 } 1804 1805 private UserInfo createUserInternal(String name, int flags, int parentId) { 1806 if (hasUserRestriction(UserManager.DISALLOW_ADD_USER, UserHandle.getCallingUserId())) { 1807 Log.w(LOG_TAG, "Cannot add user. DISALLOW_ADD_USER is enabled."); 1808 return null; 1809 } 1810 return createUserInternalUnchecked(name, flags, parentId); 1811 } 1812 1813 private UserInfo createUserInternalUnchecked(String name, int flags, int parentId) { 1814 if (ActivityManager.isLowRamDeviceStatic()) { 1815 return null; 1816 } 1817 final boolean isGuest = (flags & UserInfo.FLAG_GUEST) != 0; 1818 final boolean isManagedProfile = (flags & UserInfo.FLAG_MANAGED_PROFILE) != 0; 1819 final boolean isRestricted = (flags & UserInfo.FLAG_RESTRICTED) != 0; 1820 final long ident = Binder.clearCallingIdentity(); 1821 UserInfo userInfo; 1822 UserData userData; 1823 final int userId; 1824 try { 1825 synchronized (mPackagesLock) { 1826 UserData parent = null; 1827 if (parentId != UserHandle.USER_NULL) { 1828 synchronized (mUsersLock) { 1829 parent = getUserDataLU(parentId); 1830 } 1831 if (parent == null) return null; 1832 } 1833 if (isManagedProfile && !canAddMoreManagedProfiles(parentId, false)) { 1834 Log.e(LOG_TAG, "Cannot add more managed profiles for user " + parentId); 1835 return null; 1836 } 1837 if (!isGuest && !isManagedProfile && isUserLimitReached()) { 1838 // If we're not adding a guest user or a managed profile and the limit has 1839 // been reached, cannot add a user. 1840 return null; 1841 } 1842 // If we're adding a guest and there already exists one, bail. 1843 if (isGuest && findCurrentGuestUser() != null) { 1844 return null; 1845 } 1846 // In legacy mode, restricted profile's parent can only be the owner user 1847 if (isRestricted && !UserManager.isSplitSystemUser() 1848 && (parentId != UserHandle.USER_SYSTEM)) { 1849 Log.w(LOG_TAG, "Cannot add restricted profile - parent user must be owner"); 1850 return null; 1851 } 1852 if (isRestricted && UserManager.isSplitSystemUser()) { 1853 if (parent == null) { 1854 Log.w(LOG_TAG, "Cannot add restricted profile - parent user must be " 1855 + "specified"); 1856 return null; 1857 } 1858 if (!parent.info.canHaveProfile()) { 1859 Log.w(LOG_TAG, "Cannot add restricted profile - profiles cannot be " 1860 + "created for the specified parent user id " + parentId); 1861 return null; 1862 } 1863 } 1864 if (!UserManager.isSplitSystemUser() && (flags & UserInfo.FLAG_EPHEMERAL) != 0) { 1865 Log.e(LOG_TAG, 1866 "Ephemeral users are supported on split-system-user systems only."); 1867 return null; 1868 } 1869 // In split system user mode, we assign the first human user the primary flag. 1870 // And if there is no device owner, we also assign the admin flag to primary user. 1871 if (UserManager.isSplitSystemUser() 1872 && !isGuest && !isManagedProfile && getPrimaryUser() == null) { 1873 flags |= UserInfo.FLAG_PRIMARY; 1874 synchronized (mUsersLock) { 1875 if (!mIsDeviceManaged) { 1876 flags |= UserInfo.FLAG_ADMIN; 1877 } 1878 } 1879 } 1880 1881 userId = getNextAvailableId(); 1882 Environment.getUserSystemDirectory(userId).mkdirs(); 1883 boolean ephemeralGuests = Resources.getSystem() 1884 .getBoolean(com.android.internal.R.bool.config_guestUserEphemeral); 1885 1886 synchronized (mUsersLock) { 1887 // Add ephemeral flag to guests/users if required. Also inherit it from parent. 1888 if ((isGuest && ephemeralGuests) || mForceEphemeralUsers 1889 || (parent != null && parent.info.isEphemeral())) { 1890 flags |= UserInfo.FLAG_EPHEMERAL; 1891 } 1892 1893 userInfo = new UserInfo(userId, name, null, flags); 1894 userInfo.serialNumber = mNextSerialNumber++; 1895 long now = System.currentTimeMillis(); 1896 userInfo.creationTime = (now > EPOCH_PLUS_30_YEARS) ? now : 0; 1897 userInfo.partial = true; 1898 userData = new UserData(); 1899 userData.info = userInfo; 1900 mUsers.put(userId, userData); 1901 } 1902 writeUserListLP(); 1903 if (parent != null) { 1904 if (isManagedProfile) { 1905 if (parent.info.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) { 1906 parent.info.profileGroupId = parent.info.id; 1907 writeUserLP(parent); 1908 } 1909 userInfo.profileGroupId = parent.info.profileGroupId; 1910 } else if (isRestricted) { 1911 if (parent.info.restrictedProfileParentId == UserInfo.NO_PROFILE_GROUP_ID) { 1912 parent.info.restrictedProfileParentId = parent.info.id; 1913 writeUserLP(parent); 1914 } 1915 userInfo.restrictedProfileParentId = parent.info.restrictedProfileParentId; 1916 } 1917 } 1918 } 1919 final StorageManager storage = mContext.getSystemService(StorageManager.class); 1920 storage.createUserKey(userId, userInfo.serialNumber, userInfo.isEphemeral()); 1921 prepareUserStorage(userId, userInfo.serialNumber, 1922 StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE); 1923 mPm.createNewUser(userId); 1924 userInfo.partial = false; 1925 synchronized (mPackagesLock) { 1926 writeUserLP(userData); 1927 } 1928 updateUserIds(); 1929 Bundle restrictions = new Bundle(); 1930 if (isGuest) { 1931 synchronized (mGuestRestrictions) { 1932 restrictions.putAll(mGuestRestrictions); 1933 } 1934 } 1935 synchronized (mRestrictionsLock) { 1936 mBaseUserRestrictions.append(userId, restrictions); 1937 } 1938 mPm.newUserCreated(userId); 1939 Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED); 1940 addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId); 1941 mContext.sendBroadcastAsUser(addedIntent, UserHandle.ALL, 1942 android.Manifest.permission.MANAGE_USERS); 1943 MetricsLogger.count(mContext, isGuest ? TRON_GUEST_CREATED : TRON_USER_CREATED, 1); 1944 } finally { 1945 Binder.restoreCallingIdentity(ident); 1946 } 1947 return userInfo; 1948 } 1949 1950 /** 1951 * @hide 1952 */ 1953 @Override 1954 public UserInfo createRestrictedProfile(String name, int parentUserId) { 1955 checkManageUsersPermission("setupRestrictedProfile"); 1956 final UserInfo user = createProfileForUser(name, UserInfo.FLAG_RESTRICTED, parentUserId); 1957 if (user == null) { 1958 return null; 1959 } 1960 long identity = Binder.clearCallingIdentity(); 1961 try { 1962 setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user.id); 1963 // Change the setting before applying the DISALLOW_SHARE_LOCATION restriction, otherwise 1964 // the putIntForUser() will fail. 1965 android.provider.Settings.Secure.putIntForUser(mContext.getContentResolver(), 1966 android.provider.Settings.Secure.LOCATION_MODE, 1967 android.provider.Settings.Secure.LOCATION_MODE_OFF, user.id); 1968 setUserRestriction(UserManager.DISALLOW_SHARE_LOCATION, true, user.id); 1969 } finally { 1970 Binder.restoreCallingIdentity(identity); 1971 } 1972 return user; 1973 } 1974 1975 /** 1976 * Find the current guest user. If the Guest user is partial, 1977 * then do not include it in the results as it is about to die. 1978 */ 1979 private UserInfo findCurrentGuestUser() { 1980 synchronized (mUsersLock) { 1981 final int size = mUsers.size(); 1982 for (int i = 0; i < size; i++) { 1983 final UserInfo user = mUsers.valueAt(i).info; 1984 if (user.isGuest() && !user.guestToRemove && !mRemovingUserIds.get(user.id)) { 1985 return user; 1986 } 1987 } 1988 } 1989 return null; 1990 } 1991 1992 /** 1993 * Mark this guest user for deletion to allow us to create another guest 1994 * and switch to that user before actually removing this guest. 1995 * @param userHandle the userid of the current guest 1996 * @return whether the user could be marked for deletion 1997 */ 1998 @Override 1999 public boolean markGuestForDeletion(int userHandle) { 2000 checkManageUsersPermission("Only the system can remove users"); 2001 if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean( 2002 UserManager.DISALLOW_REMOVE_USER, false)) { 2003 Log.w(LOG_TAG, "Cannot remove user. DISALLOW_REMOVE_USER is enabled."); 2004 return false; 2005 } 2006 2007 long ident = Binder.clearCallingIdentity(); 2008 try { 2009 final UserData userData; 2010 synchronized (mPackagesLock) { 2011 synchronized (mUsersLock) { 2012 userData = mUsers.get(userHandle); 2013 if (userHandle == 0 || userData == null || mRemovingUserIds.get(userHandle)) { 2014 return false; 2015 } 2016 } 2017 if (!userData.info.isGuest()) { 2018 return false; 2019 } 2020 // We set this to a guest user that is to be removed. This is a temporary state 2021 // where we are allowed to add new Guest users, even if this one is still not 2022 // removed. This user will still show up in getUserInfo() calls. 2023 // If we don't get around to removing this Guest user, it will be purged on next 2024 // startup. 2025 userData.info.guestToRemove = true; 2026 // Mark it as disabled, so that it isn't returned any more when 2027 // profiles are queried. 2028 userData.info.flags |= UserInfo.FLAG_DISABLED; 2029 writeUserLP(userData); 2030 } 2031 } finally { 2032 Binder.restoreCallingIdentity(ident); 2033 } 2034 return true; 2035 } 2036 2037 /** 2038 * Removes a user and all data directories created for that user. This method should be called 2039 * after the user's processes have been terminated. 2040 * @param userHandle the user's id 2041 */ 2042 @Override 2043 public boolean removeUser(int userHandle) { 2044 checkManageUsersPermission("Only the system can remove users"); 2045 if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean( 2046 UserManager.DISALLOW_REMOVE_USER, false)) { 2047 Log.w(LOG_TAG, "Cannot remove user. DISALLOW_REMOVE_USER is enabled."); 2048 return false; 2049 } 2050 2051 long ident = Binder.clearCallingIdentity(); 2052 try { 2053 final UserData userData; 2054 int currentUser = ActivityManager.getCurrentUser(); 2055 if (currentUser == userHandle) { 2056 Log.w(LOG_TAG, "Current user cannot be removed"); 2057 return false; 2058 } 2059 synchronized (mPackagesLock) { 2060 synchronized (mUsersLock) { 2061 userData = mUsers.get(userHandle); 2062 if (userHandle == 0 || userData == null || mRemovingUserIds.get(userHandle)) { 2063 return false; 2064 } 2065 2066 // We remember deleted user IDs to prevent them from being 2067 // reused during the current boot; they can still be reused 2068 // after a reboot. 2069 mRemovingUserIds.put(userHandle, true); 2070 } 2071 2072 try { 2073 mAppOpsService.removeUser(userHandle); 2074 } catch (RemoteException e) { 2075 Log.w(LOG_TAG, "Unable to notify AppOpsService of removing user", e); 2076 } 2077 // Set this to a partially created user, so that the user will be purged 2078 // on next startup, in case the runtime stops now before stopping and 2079 // removing the user completely. 2080 userData.info.partial = true; 2081 // Mark it as disabled, so that it isn't returned any more when 2082 // profiles are queried. 2083 userData.info.flags |= UserInfo.FLAG_DISABLED; 2084 writeUserLP(userData); 2085 } 2086 2087 if (userData.info.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID 2088 && userData.info.isManagedProfile()) { 2089 // Send broadcast to notify system that the user removed was a 2090 // managed user. 2091 sendProfileRemovedBroadcast(userData.info.profileGroupId, userData.info.id); 2092 } 2093 2094 if (DBG) Slog.i(LOG_TAG, "Stopping user " + userHandle); 2095 int res; 2096 try { 2097 res = ActivityManagerNative.getDefault().stopUser(userHandle, /* force= */ true, 2098 new IStopUserCallback.Stub() { 2099 @Override 2100 public void userStopped(int userId) { 2101 finishRemoveUser(userId); 2102 } 2103 @Override 2104 public void userStopAborted(int userId) { 2105 } 2106 }); 2107 } catch (RemoteException e) { 2108 return false; 2109 } 2110 return res == ActivityManager.USER_OP_SUCCESS; 2111 } finally { 2112 Binder.restoreCallingIdentity(ident); 2113 } 2114 } 2115 2116 void finishRemoveUser(final int userHandle) { 2117 if (DBG) Slog.i(LOG_TAG, "finishRemoveUser " + userHandle); 2118 // Let other services shutdown any activity and clean up their state before completely 2119 // wiping the user's system directory and removing from the user list 2120 long ident = Binder.clearCallingIdentity(); 2121 try { 2122 Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED); 2123 addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle); 2124 mContext.sendOrderedBroadcastAsUser(addedIntent, UserHandle.ALL, 2125 android.Manifest.permission.MANAGE_USERS, 2126 2127 new BroadcastReceiver() { 2128 @Override 2129 public void onReceive(Context context, Intent intent) { 2130 if (DBG) { 2131 Slog.i(LOG_TAG, 2132 "USER_REMOVED broadcast sent, cleaning up user data " 2133 + userHandle); 2134 } 2135 new Thread() { 2136 @Override 2137 public void run() { 2138 // Clean up any ActivityManager state 2139 LocalServices.getService(ActivityManagerInternal.class) 2140 .onUserRemoved(userHandle); 2141 removeUserState(userHandle); 2142 } 2143 }.start(); 2144 } 2145 }, 2146 2147 null, Activity.RESULT_OK, null, null); 2148 } finally { 2149 Binder.restoreCallingIdentity(ident); 2150 } 2151 } 2152 2153 private void removeUserState(final int userHandle) { 2154 mContext.getSystemService(StorageManager.class).destroyUserKey(userHandle); 2155 // Cleanup package manager settings 2156 mPm.cleanUpUser(this, userHandle); 2157 2158 // Remove this user from the list 2159 synchronized (mUsersLock) { 2160 mUsers.remove(userHandle); 2161 mIsUserManaged.delete(userHandle); 2162 } 2163 synchronized (mRestrictionsLock) { 2164 mBaseUserRestrictions.remove(userHandle); 2165 mAppliedUserRestrictions.remove(userHandle); 2166 mCachedEffectiveUserRestrictions.remove(userHandle); 2167 mDevicePolicyLocalUserRestrictions.remove(userHandle); 2168 } 2169 // Remove user file 2170 AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX)); 2171 userFile.delete(); 2172 // Update the user list 2173 synchronized (mPackagesLock) { 2174 writeUserListLP(); 2175 } 2176 updateUserIds(); 2177 File userDir = Environment.getUserSystemDirectory(userHandle); 2178 File renamedUserDir = Environment.getUserSystemDirectory(UserHandle.USER_NULL - userHandle); 2179 if (userDir.renameTo(renamedUserDir)) { 2180 removeDirectoryRecursive(renamedUserDir); 2181 } else { 2182 removeDirectoryRecursive(userDir); 2183 } 2184 } 2185 2186 private void removeDirectoryRecursive(File parent) { 2187 if (parent.isDirectory()) { 2188 String[] files = parent.list(); 2189 for (String filename : files) { 2190 File child = new File(parent, filename); 2191 removeDirectoryRecursive(child); 2192 } 2193 } 2194 parent.delete(); 2195 } 2196 2197 private void sendProfileRemovedBroadcast(int parentUserId, int removedUserId) { 2198 Intent managedProfileIntent = new Intent(Intent.ACTION_MANAGED_PROFILE_REMOVED); 2199 managedProfileIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | 2200 Intent.FLAG_RECEIVER_FOREGROUND); 2201 managedProfileIntent.putExtra(Intent.EXTRA_USER, new UserHandle(removedUserId)); 2202 managedProfileIntent.putExtra(Intent.EXTRA_USER_HANDLE, removedUserId); 2203 mContext.sendBroadcastAsUser(managedProfileIntent, new UserHandle(parentUserId), null); 2204 } 2205 2206 @Override 2207 public Bundle getApplicationRestrictions(String packageName) { 2208 return getApplicationRestrictionsForUser(packageName, UserHandle.getCallingUserId()); 2209 } 2210 2211 @Override 2212 public Bundle getApplicationRestrictionsForUser(String packageName, int userId) { 2213 if (UserHandle.getCallingUserId() != userId 2214 || !UserHandle.isSameApp(Binder.getCallingUid(), getUidForPackage(packageName))) { 2215 checkSystemOrRoot("get application restrictions for other users/apps"); 2216 } 2217 synchronized (mPackagesLock) { 2218 // Read the restrictions from XML 2219 return readApplicationRestrictionsLP(packageName, userId); 2220 } 2221 } 2222 2223 @Override 2224 public void setApplicationRestrictions(String packageName, Bundle restrictions, 2225 int userId) { 2226 checkSystemOrRoot("set application restrictions"); 2227 synchronized (mPackagesLock) { 2228 if (restrictions == null || restrictions.isEmpty()) { 2229 cleanAppRestrictionsForPackage(packageName, userId); 2230 } else { 2231 // Write the restrictions to XML 2232 writeApplicationRestrictionsLP(packageName, restrictions, userId); 2233 } 2234 } 2235 2236 // Notify package of changes via an intent - only sent to explicitly registered receivers. 2237 Intent changeIntent = new Intent(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED); 2238 changeIntent.setPackage(packageName); 2239 changeIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 2240 mContext.sendBroadcastAsUser(changeIntent, UserHandle.of(userId)); 2241 } 2242 2243 private int getUidForPackage(String packageName) { 2244 long ident = Binder.clearCallingIdentity(); 2245 try { 2246 return mContext.getPackageManager().getApplicationInfo(packageName, 2247 PackageManager.MATCH_UNINSTALLED_PACKAGES).uid; 2248 } catch (NameNotFoundException nnfe) { 2249 return -1; 2250 } finally { 2251 Binder.restoreCallingIdentity(ident); 2252 } 2253 } 2254 2255 private Bundle readApplicationRestrictionsLP(String packageName, int userId) { 2256 AtomicFile restrictionsFile = 2257 new AtomicFile(new File(Environment.getUserSystemDirectory(userId), 2258 packageToRestrictionsFileName(packageName))); 2259 return readApplicationRestrictionsLP(restrictionsFile); 2260 } 2261 2262 @VisibleForTesting 2263 static Bundle readApplicationRestrictionsLP(AtomicFile restrictionsFile) { 2264 final Bundle restrictions = new Bundle(); 2265 final ArrayList<String> values = new ArrayList<>(); 2266 if (!restrictionsFile.getBaseFile().exists()) { 2267 return restrictions; 2268 } 2269 2270 FileInputStream fis = null; 2271 try { 2272 fis = restrictionsFile.openRead(); 2273 XmlPullParser parser = Xml.newPullParser(); 2274 parser.setInput(fis, StandardCharsets.UTF_8.name()); 2275 XmlUtils.nextElement(parser); 2276 if (parser.getEventType() != XmlPullParser.START_TAG) { 2277 Slog.e(LOG_TAG, "Unable to read restrictions file " 2278 + restrictionsFile.getBaseFile()); 2279 return restrictions; 2280 } 2281 while (parser.next() != XmlPullParser.END_DOCUMENT) { 2282 readEntry(restrictions, values, parser); 2283 } 2284 } catch (IOException|XmlPullParserException e) { 2285 Log.w(LOG_TAG, "Error parsing " + restrictionsFile.getBaseFile(), e); 2286 } finally { 2287 IoUtils.closeQuietly(fis); 2288 } 2289 return restrictions; 2290 } 2291 2292 private static void readEntry(Bundle restrictions, ArrayList<String> values, 2293 XmlPullParser parser) throws XmlPullParserException, IOException { 2294 int type = parser.getEventType(); 2295 if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_ENTRY)) { 2296 String key = parser.getAttributeValue(null, ATTR_KEY); 2297 String valType = parser.getAttributeValue(null, ATTR_VALUE_TYPE); 2298 String multiple = parser.getAttributeValue(null, ATTR_MULTIPLE); 2299 if (multiple != null) { 2300 values.clear(); 2301 int count = Integer.parseInt(multiple); 2302 while (count > 0 && (type = parser.next()) != XmlPullParser.END_DOCUMENT) { 2303 if (type == XmlPullParser.START_TAG 2304 && parser.getName().equals(TAG_VALUE)) { 2305 values.add(parser.nextText().trim()); 2306 count--; 2307 } 2308 } 2309 String [] valueStrings = new String[values.size()]; 2310 values.toArray(valueStrings); 2311 restrictions.putStringArray(key, valueStrings); 2312 } else if (ATTR_TYPE_BUNDLE.equals(valType)) { 2313 restrictions.putBundle(key, readBundleEntry(parser, values)); 2314 } else if (ATTR_TYPE_BUNDLE_ARRAY.equals(valType)) { 2315 final int outerDepth = parser.getDepth(); 2316 ArrayList<Bundle> bundleList = new ArrayList<>(); 2317 while (XmlUtils.nextElementWithin(parser, outerDepth)) { 2318 Bundle childBundle = readBundleEntry(parser, values); 2319 bundleList.add(childBundle); 2320 } 2321 restrictions.putParcelableArray(key, 2322 bundleList.toArray(new Bundle[bundleList.size()])); 2323 } else { 2324 String value = parser.nextText().trim(); 2325 if (ATTR_TYPE_BOOLEAN.equals(valType)) { 2326 restrictions.putBoolean(key, Boolean.parseBoolean(value)); 2327 } else if (ATTR_TYPE_INTEGER.equals(valType)) { 2328 restrictions.putInt(key, Integer.parseInt(value)); 2329 } else { 2330 restrictions.putString(key, value); 2331 } 2332 } 2333 } 2334 } 2335 2336 private static Bundle readBundleEntry(XmlPullParser parser, ArrayList<String> values) 2337 throws IOException, XmlPullParserException { 2338 Bundle childBundle = new Bundle(); 2339 final int outerDepth = parser.getDepth(); 2340 while (XmlUtils.nextElementWithin(parser, outerDepth)) { 2341 readEntry(childBundle, values, parser); 2342 } 2343 return childBundle; 2344 } 2345 2346 private void writeApplicationRestrictionsLP(String packageName, 2347 Bundle restrictions, int userId) { 2348 AtomicFile restrictionsFile = new AtomicFile( 2349 new File(Environment.getUserSystemDirectory(userId), 2350 packageToRestrictionsFileName(packageName))); 2351 writeApplicationRestrictionsLP(restrictions, restrictionsFile); 2352 } 2353 2354 @VisibleForTesting 2355 static void writeApplicationRestrictionsLP(Bundle restrictions, AtomicFile restrictionsFile) { 2356 FileOutputStream fos = null; 2357 try { 2358 fos = restrictionsFile.startWrite(); 2359 final BufferedOutputStream bos = new BufferedOutputStream(fos); 2360 2361 final XmlSerializer serializer = new FastXmlSerializer(); 2362 serializer.setOutput(bos, StandardCharsets.UTF_8.name()); 2363 serializer.startDocument(null, true); 2364 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); 2365 2366 serializer.startTag(null, TAG_RESTRICTIONS); 2367 writeBundle(restrictions, serializer); 2368 serializer.endTag(null, TAG_RESTRICTIONS); 2369 2370 serializer.endDocument(); 2371 restrictionsFile.finishWrite(fos); 2372 } catch (Exception e) { 2373 restrictionsFile.failWrite(fos); 2374 Slog.e(LOG_TAG, "Error writing application restrictions list", e); 2375 } 2376 } 2377 2378 private static void writeBundle(Bundle restrictions, XmlSerializer serializer) 2379 throws IOException { 2380 for (String key : restrictions.keySet()) { 2381 Object value = restrictions.get(key); 2382 serializer.startTag(null, TAG_ENTRY); 2383 serializer.attribute(null, ATTR_KEY, key); 2384 2385 if (value instanceof Boolean) { 2386 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BOOLEAN); 2387 serializer.text(value.toString()); 2388 } else if (value instanceof Integer) { 2389 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_INTEGER); 2390 serializer.text(value.toString()); 2391 } else if (value == null || value instanceof String) { 2392 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_STRING); 2393 serializer.text(value != null ? (String) value : ""); 2394 } else if (value instanceof Bundle) { 2395 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BUNDLE); 2396 writeBundle((Bundle) value, serializer); 2397 } else if (value instanceof Parcelable[]) { 2398 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BUNDLE_ARRAY); 2399 Parcelable[] array = (Parcelable[]) value; 2400 for (Parcelable parcelable : array) { 2401 if (!(parcelable instanceof Bundle)) { 2402 throw new IllegalArgumentException("bundle-array can only hold Bundles"); 2403 } 2404 serializer.startTag(null, TAG_ENTRY); 2405 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BUNDLE); 2406 writeBundle((Bundle) parcelable, serializer); 2407 serializer.endTag(null, TAG_ENTRY); 2408 } 2409 } else { 2410 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_STRING_ARRAY); 2411 String[] values = (String[]) value; 2412 serializer.attribute(null, ATTR_MULTIPLE, Integer.toString(values.length)); 2413 for (String choice : values) { 2414 serializer.startTag(null, TAG_VALUE); 2415 serializer.text(choice != null ? choice : ""); 2416 serializer.endTag(null, TAG_VALUE); 2417 } 2418 } 2419 serializer.endTag(null, TAG_ENTRY); 2420 } 2421 } 2422 2423 @Override 2424 public int getUserSerialNumber(int userHandle) { 2425 synchronized (mUsersLock) { 2426 if (!exists(userHandle)) return -1; 2427 return getUserInfoLU(userHandle).serialNumber; 2428 } 2429 } 2430 2431 @Override 2432 public int getUserHandle(int userSerialNumber) { 2433 synchronized (mUsersLock) { 2434 for (int userId : mUserIds) { 2435 UserInfo info = getUserInfoLU(userId); 2436 if (info != null && info.serialNumber == userSerialNumber) return userId; 2437 } 2438 // Not found 2439 return -1; 2440 } 2441 } 2442 2443 @Override 2444 public long getUserCreationTime(int userHandle) { 2445 int callingUserId = UserHandle.getCallingUserId(); 2446 UserInfo userInfo = null; 2447 synchronized (mUsersLock) { 2448 if (callingUserId == userHandle) { 2449 userInfo = getUserInfoLU(userHandle); 2450 } else { 2451 UserInfo parent = getProfileParentLU(userHandle); 2452 if (parent != null && parent.id == callingUserId) { 2453 userInfo = getUserInfoLU(userHandle); 2454 } 2455 } 2456 } 2457 if (userInfo == null) { 2458 throw new SecurityException("userHandle can only be the calling user or a managed " 2459 + "profile associated with this user"); 2460 } 2461 return userInfo.creationTime; 2462 } 2463 2464 /** 2465 * Caches the list of user ids in an array, adjusting the array size when necessary. 2466 */ 2467 private void updateUserIds() { 2468 int num = 0; 2469 synchronized (mUsersLock) { 2470 final int userSize = mUsers.size(); 2471 for (int i = 0; i < userSize; i++) { 2472 if (!mUsers.valueAt(i).info.partial) { 2473 num++; 2474 } 2475 } 2476 final int[] newUsers = new int[num]; 2477 int n = 0; 2478 for (int i = 0; i < userSize; i++) { 2479 if (!mUsers.valueAt(i).info.partial) { 2480 newUsers[n++] = mUsers.keyAt(i); 2481 } 2482 } 2483 mUserIds = newUsers; 2484 } 2485 } 2486 2487 /** 2488 * Prepare storage areas for given user on all mounted devices. 2489 */ 2490 private void prepareUserStorage(int userId, int userSerial, int flags) { 2491 final StorageManager storage = mContext.getSystemService(StorageManager.class); 2492 for (VolumeInfo vol : storage.getWritablePrivateVolumes()) { 2493 final String volumeUuid = vol.getFsUuid(); 2494 storage.prepareUserStorage(volumeUuid, userId, userSerial, flags); 2495 } 2496 } 2497 2498 /** 2499 * Called right before a user is started. This gives us a chance to prepare 2500 * app storage and apply any user restrictions. 2501 */ 2502 public void onBeforeStartUser(int userId) { 2503 final int userSerial = getUserSerialNumber(userId); 2504 prepareUserStorage(userId, userSerial, StorageManager.FLAG_STORAGE_DE); 2505 mPm.reconcileAppsData(userId, StorageManager.FLAG_STORAGE_DE); 2506 2507 if (userId != UserHandle.USER_SYSTEM) { 2508 synchronized (mRestrictionsLock) { 2509 applyUserRestrictionsLR(userId); 2510 } 2511 } 2512 } 2513 2514 /** 2515 * Called right before a user is unlocked. This gives us a chance to prepare 2516 * app storage. 2517 */ 2518 public void onBeforeUnlockUser(int userId) { 2519 final int userSerial = getUserSerialNumber(userId); 2520 prepareUserStorage(userId, userSerial, StorageManager.FLAG_STORAGE_CE); 2521 mPm.reconcileAppsData(userId, StorageManager.FLAG_STORAGE_CE); 2522 } 2523 2524 /** 2525 * Make a note of the last started time of a user and do some cleanup. 2526 * @param userId the user that was just foregrounded 2527 */ 2528 public void onUserForeground(int userId) { 2529 UserData userData = getUserDataNoChecks(userId); 2530 if (userData == null || userData.info.partial) { 2531 Slog.w(LOG_TAG, "userForeground: unknown user #" + userId); 2532 return; 2533 } 2534 long now = System.currentTimeMillis(); 2535 if (now > EPOCH_PLUS_30_YEARS) { 2536 userData.info.lastLoggedInTime = now; 2537 scheduleWriteUser(userData); 2538 } 2539 } 2540 2541 /** 2542 * Returns the next available user id, filling in any holes in the ids. 2543 * TODO: May not be a good idea to recycle ids, in case it results in confusion 2544 * for data and battery stats collection, or unexpected cross-talk. 2545 */ 2546 private int getNextAvailableId() { 2547 synchronized (mUsersLock) { 2548 int i = MIN_USER_ID; 2549 while (i < MAX_USER_ID) { 2550 if (mUsers.indexOfKey(i) < 0 && !mRemovingUserIds.get(i)) { 2551 return i; 2552 } 2553 i++; 2554 } 2555 } 2556 throw new IllegalStateException("No user id available!"); 2557 } 2558 2559 private String packageToRestrictionsFileName(String packageName) { 2560 return RESTRICTIONS_FILE_PREFIX + packageName + XML_SUFFIX; 2561 } 2562 2563 /** 2564 * Enforce that serial number stored in user directory inode matches the 2565 * given expected value. Gracefully sets the serial number if currently 2566 * undefined. 2567 * 2568 * @throws IOException when problem extracting serial number, or serial 2569 * number is mismatched. 2570 */ 2571 public static void enforceSerialNumber(File file, int serialNumber) throws IOException { 2572 final int foundSerial = getSerialNumber(file); 2573 Slog.v(LOG_TAG, "Found " + file + " with serial number " + foundSerial); 2574 2575 if (foundSerial == -1) { 2576 Slog.d(LOG_TAG, "Serial number missing on " + file + "; assuming current is valid"); 2577 try { 2578 setSerialNumber(file, serialNumber); 2579 } catch (IOException e) { 2580 Slog.w(LOG_TAG, "Failed to set serial number on " + file, e); 2581 } 2582 2583 } else if (foundSerial != serialNumber) { 2584 throw new IOException("Found serial number " + foundSerial 2585 + " doesn't match expected " + serialNumber); 2586 } 2587 } 2588 2589 /** 2590 * Set serial number stored in user directory inode. 2591 * 2592 * @throws IOException if serial number was already set 2593 */ 2594 private static void setSerialNumber(File file, int serialNumber) 2595 throws IOException { 2596 try { 2597 final byte[] buf = Integer.toString(serialNumber).getBytes(StandardCharsets.UTF_8); 2598 Os.setxattr(file.getAbsolutePath(), XATTR_SERIAL, buf, OsConstants.XATTR_CREATE); 2599 } catch (ErrnoException e) { 2600 throw e.rethrowAsIOException(); 2601 } 2602 } 2603 2604 /** 2605 * Return serial number stored in user directory inode. 2606 * 2607 * @return parsed serial number, or -1 if not set 2608 */ 2609 private static int getSerialNumber(File file) throws IOException { 2610 try { 2611 final byte[] buf = new byte[256]; 2612 final int len = Os.getxattr(file.getAbsolutePath(), XATTR_SERIAL, buf); 2613 final String serial = new String(buf, 0, len); 2614 try { 2615 return Integer.parseInt(serial); 2616 } catch (NumberFormatException e) { 2617 throw new IOException("Bad serial number: " + serial); 2618 } 2619 } catch (ErrnoException e) { 2620 if (e.errno == OsConstants.ENODATA) { 2621 return -1; 2622 } else { 2623 throw e.rethrowAsIOException(); 2624 } 2625 } 2626 } 2627 2628 @Override 2629 public void setSeedAccountData(int userId, String accountName, String accountType, 2630 PersistableBundle accountOptions, boolean persist) { 2631 checkManageUsersPermission("Require MANAGE_USERS permission to set user seed data"); 2632 synchronized (mPackagesLock) { 2633 final UserData userData; 2634 synchronized (mUsersLock) { 2635 userData = getUserDataLU(userId); 2636 if (userData == null) { 2637 Slog.e(LOG_TAG, "No such user for settings seed data u=" + userId); 2638 return; 2639 } 2640 userData.seedAccountName = accountName; 2641 userData.seedAccountType = accountType; 2642 userData.seedAccountOptions = accountOptions; 2643 userData.persistSeedData = persist; 2644 } 2645 if (persist) { 2646 writeUserLP(userData); 2647 } 2648 } 2649 } 2650 2651 @Override 2652 public String getSeedAccountName() throws RemoteException { 2653 checkManageUsersPermission("Cannot get seed account information"); 2654 synchronized (mUsersLock) { 2655 UserData userData = getUserDataLU(UserHandle.getCallingUserId()); 2656 return userData.seedAccountName; 2657 } 2658 } 2659 2660 @Override 2661 public String getSeedAccountType() throws RemoteException { 2662 checkManageUsersPermission("Cannot get seed account information"); 2663 synchronized (mUsersLock) { 2664 UserData userData = getUserDataLU(UserHandle.getCallingUserId()); 2665 return userData.seedAccountType; 2666 } 2667 } 2668 2669 @Override 2670 public PersistableBundle getSeedAccountOptions() throws RemoteException { 2671 checkManageUsersPermission("Cannot get seed account information"); 2672 synchronized (mUsersLock) { 2673 UserData userData = getUserDataLU(UserHandle.getCallingUserId()); 2674 return userData.seedAccountOptions; 2675 } 2676 } 2677 2678 @Override 2679 public void clearSeedAccountData() throws RemoteException { 2680 checkManageUsersPermission("Cannot clear seed account information"); 2681 synchronized (mPackagesLock) { 2682 UserData userData; 2683 synchronized (mUsersLock) { 2684 userData = getUserDataLU(UserHandle.getCallingUserId()); 2685 if (userData == null) return; 2686 userData.clearSeedAccountData(); 2687 } 2688 writeUserLP(userData); 2689 } 2690 } 2691 2692 @Override 2693 public boolean someUserHasSeedAccount(String accountName, String accountType) 2694 throws RemoteException { 2695 checkManageUsersPermission("Cannot check seed account information"); 2696 synchronized (mUsersLock) { 2697 final int userSize = mUsers.size(); 2698 for (int i = 0; i < userSize; i++) { 2699 final UserData data = mUsers.valueAt(i); 2700 if (data.info.isInitialized()) continue; 2701 if (data.seedAccountName == null || !data.seedAccountName.equals(accountName)) { 2702 continue; 2703 } 2704 if (data.seedAccountType == null || !data.seedAccountType.equals(accountType)) { 2705 continue; 2706 } 2707 return true; 2708 } 2709 } 2710 return false; 2711 } 2712 2713 @Override 2714 public void onShellCommand(FileDescriptor in, FileDescriptor out, 2715 FileDescriptor err, String[] args, ResultReceiver resultReceiver) { 2716 (new Shell()).exec(this, in, out, err, args, resultReceiver); 2717 } 2718 2719 int onShellCommand(Shell shell, String cmd) { 2720 if (cmd == null) { 2721 return shell.handleDefaultCommands(cmd); 2722 } 2723 2724 final PrintWriter pw = shell.getOutPrintWriter(); 2725 try { 2726 switch(cmd) { 2727 case "list": 2728 return runList(pw); 2729 } 2730 } catch (RemoteException e) { 2731 pw.println("Remote exception: " + e); 2732 } 2733 return -1; 2734 } 2735 2736 private int runList(PrintWriter pw) throws RemoteException { 2737 final IActivityManager am = ActivityManagerNative.getDefault(); 2738 final List<UserInfo> users = getUsers(false); 2739 if (users == null) { 2740 pw.println("Error: couldn't get users"); 2741 return 1; 2742 } else { 2743 pw.println("Users:"); 2744 for (int i = 0; i < users.size(); i++) { 2745 String running = am.isUserRunning(users.get(i).id, 0) ? " running" : ""; 2746 pw.println("\t" + users.get(i).toString() + running); 2747 } 2748 return 0; 2749 } 2750 } 2751 2752 @Override 2753 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2754 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 2755 != PackageManager.PERMISSION_GRANTED) { 2756 pw.println("Permission Denial: can't dump UserManager from from pid=" 2757 + Binder.getCallingPid() 2758 + ", uid=" + Binder.getCallingUid() 2759 + " without permission " 2760 + android.Manifest.permission.DUMP); 2761 return; 2762 } 2763 2764 long now = System.currentTimeMillis(); 2765 StringBuilder sb = new StringBuilder(); 2766 synchronized (mPackagesLock) { 2767 synchronized (mUsersLock) { 2768 pw.println("Users:"); 2769 for (int i = 0; i < mUsers.size(); i++) { 2770 UserData userData = mUsers.valueAt(i); 2771 if (userData == null) { 2772 continue; 2773 } 2774 UserInfo userInfo = userData.info; 2775 final int userId = userInfo.id; 2776 pw.print(" "); pw.print(userInfo); 2777 pw.print(" serialNo="); pw.print(userInfo.serialNumber); 2778 if (mRemovingUserIds.get(userId)) { 2779 pw.print(" <removing> "); 2780 } 2781 if (userInfo.partial) { 2782 pw.print(" <partial>"); 2783 } 2784 pw.println(); 2785 pw.print(" Created: "); 2786 if (userInfo.creationTime == 0) { 2787 pw.println("<unknown>"); 2788 } else { 2789 sb.setLength(0); 2790 TimeUtils.formatDuration(now - userInfo.creationTime, sb); 2791 sb.append(" ago"); 2792 pw.println(sb); 2793 } 2794 pw.print(" Last logged in: "); 2795 if (userInfo.lastLoggedInTime == 0) { 2796 pw.println("<unknown>"); 2797 } else { 2798 sb.setLength(0); 2799 TimeUtils.formatDuration(now - userInfo.lastLoggedInTime, sb); 2800 sb.append(" ago"); 2801 pw.println(sb); 2802 } 2803 pw.print(" Has profile owner: "); 2804 pw.println(mIsUserManaged.get(userId)); 2805 pw.println(" Restrictions:"); 2806 synchronized (mRestrictionsLock) { 2807 UserRestrictionsUtils.dumpRestrictions( 2808 pw, " ", mBaseUserRestrictions.get(userInfo.id)); 2809 pw.println(" Device policy local restrictions:"); 2810 UserRestrictionsUtils.dumpRestrictions( 2811 pw, " ", mDevicePolicyLocalUserRestrictions.get(userInfo.id)); 2812 pw.println(" Effective restrictions:"); 2813 UserRestrictionsUtils.dumpRestrictions( 2814 pw, " ", mCachedEffectiveUserRestrictions.get(userInfo.id)); 2815 } 2816 2817 if (userData.account != null) { 2818 pw.print(" Account name: " + userData.account); 2819 pw.println(); 2820 } 2821 2822 if (userData.seedAccountName != null) { 2823 pw.print(" Seed account name: " + userData.seedAccountName); 2824 pw.println(); 2825 if (userData.seedAccountType != null) { 2826 pw.print(" account type: " + userData.seedAccountType); 2827 pw.println(); 2828 } 2829 if (userData.seedAccountOptions != null) { 2830 pw.print(" account options exist"); 2831 pw.println(); 2832 } 2833 } 2834 } 2835 } 2836 pw.println(); 2837 pw.println(" Device policy global restrictions:"); 2838 synchronized (mRestrictionsLock) { 2839 UserRestrictionsUtils 2840 .dumpRestrictions(pw, " ", mDevicePolicyGlobalUserRestrictions); 2841 } 2842 pw.println(); 2843 pw.println(" Guest restrictions:"); 2844 synchronized (mGuestRestrictions) { 2845 UserRestrictionsUtils.dumpRestrictions(pw, " ", mGuestRestrictions); 2846 } 2847 synchronized (mUsersLock) { 2848 pw.println(); 2849 pw.println(" Device managed: " + mIsDeviceManaged); 2850 } 2851 // Dump some capabilities 2852 pw.println(); 2853 pw.println(" Max users: " + UserManager.getMaxSupportedUsers()); 2854 pw.println(" Supports switchable users: " + UserManager.supportsMultipleUsers()); 2855 pw.println(" All guests ephemeral: " + Resources.getSystem().getBoolean( 2856 com.android.internal.R.bool.config_guestUserEphemeral)); 2857 } 2858 } 2859 2860 final class MainHandler extends Handler { 2861 2862 @Override 2863 public void handleMessage(Message msg) { 2864 switch (msg.what) { 2865 case WRITE_USER_MSG: 2866 removeMessages(WRITE_USER_MSG, msg.obj); 2867 synchronized (mPackagesLock) { 2868 int userId = ((UserData) msg.obj).info.id; 2869 UserData userData = getUserDataNoChecks(userId); 2870 if (userData != null) { 2871 writeUserLP(userData); 2872 } 2873 } 2874 } 2875 } 2876 } 2877 2878 /** 2879 * @param userId 2880 * @return whether the user has been initialized yet 2881 */ 2882 boolean isInitialized(int userId) { 2883 return (getUserInfo(userId).flags & UserInfo.FLAG_INITIALIZED) != 0; 2884 } 2885 2886 private class LocalService extends UserManagerInternal { 2887 @Override 2888 public void setDevicePolicyUserRestrictions(int userId, @NonNull Bundle localRestrictions, 2889 @Nullable Bundle globalRestrictions) { 2890 UserManagerService.this.setDevicePolicyUserRestrictionsInner(userId, localRestrictions, 2891 globalRestrictions); 2892 } 2893 2894 @Override 2895 public Bundle getBaseUserRestrictions(int userId) { 2896 synchronized (mRestrictionsLock) { 2897 return mBaseUserRestrictions.get(userId); 2898 } 2899 } 2900 2901 @Override 2902 public void setBaseUserRestrictionsByDpmsForMigration( 2903 int userId, Bundle baseRestrictions) { 2904 synchronized (mRestrictionsLock) { 2905 mBaseUserRestrictions.put(userId, new Bundle(baseRestrictions)); 2906 invalidateEffectiveUserRestrictionsLR(userId); 2907 } 2908 2909 final UserData userData = getUserDataNoChecks(userId); 2910 synchronized (mPackagesLock) { 2911 if (userData != null) { 2912 writeUserLP(userData); 2913 } else { 2914 Slog.w(LOG_TAG, "UserInfo not found for " + userId); 2915 } 2916 } 2917 } 2918 2919 @Override 2920 public boolean getUserRestriction(int userId, String key) { 2921 return getUserRestrictions(userId).getBoolean(key); 2922 } 2923 2924 @Override 2925 public void addUserRestrictionsListener(UserRestrictionsListener listener) { 2926 synchronized (mUserRestrictionsListeners) { 2927 mUserRestrictionsListeners.add(listener); 2928 } 2929 } 2930 2931 @Override 2932 public void removeUserRestrictionsListener(UserRestrictionsListener listener) { 2933 synchronized (mUserRestrictionsListeners) { 2934 mUserRestrictionsListeners.remove(listener); 2935 } 2936 } 2937 2938 @Override 2939 public void setDeviceManaged(boolean isManaged) { 2940 synchronized (mUsersLock) { 2941 mIsDeviceManaged = isManaged; 2942 } 2943 } 2944 2945 @Override 2946 public void setUserManaged(int userId, boolean isManaged) { 2947 synchronized (mUsersLock) { 2948 mIsUserManaged.put(userId, isManaged); 2949 } 2950 } 2951 2952 @Override 2953 public void setUserIcon(int userId, Bitmap bitmap) { 2954 long ident = Binder.clearCallingIdentity(); 2955 try { 2956 synchronized (mPackagesLock) { 2957 UserData userData = getUserDataNoChecks(userId); 2958 if (userData == null || userData.info.partial) { 2959 Slog.w(LOG_TAG, "setUserIcon: unknown user #" + userId); 2960 return; 2961 } 2962 writeBitmapLP(userData.info, bitmap); 2963 writeUserLP(userData); 2964 } 2965 sendUserInfoChangedBroadcast(userId); 2966 } finally { 2967 Binder.restoreCallingIdentity(ident); 2968 } 2969 } 2970 2971 @Override 2972 public void setForceEphemeralUsers(boolean forceEphemeralUsers) { 2973 synchronized (mUsersLock) { 2974 mForceEphemeralUsers = forceEphemeralUsers; 2975 } 2976 } 2977 2978 @Override 2979 public void removeAllUsers() { 2980 if (UserHandle.USER_SYSTEM == ActivityManager.getCurrentUser()) { 2981 // Remove the non-system users straight away. 2982 removeNonSystemUsers(); 2983 } else { 2984 // Switch to the system user first and then remove the other users. 2985 BroadcastReceiver userSwitchedReceiver = new BroadcastReceiver() { 2986 @Override 2987 public void onReceive(Context context, Intent intent) { 2988 int userId = 2989 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); 2990 if (userId != UserHandle.USER_SYSTEM) { 2991 return; 2992 } 2993 mContext.unregisterReceiver(this); 2994 removeNonSystemUsers(); 2995 } 2996 }; 2997 IntentFilter userSwitchedFilter = new IntentFilter(); 2998 userSwitchedFilter.addAction(Intent.ACTION_USER_SWITCHED); 2999 mContext.registerReceiver( 3000 userSwitchedReceiver, userSwitchedFilter, null, mHandler); 3001 3002 // Switch to the system user. 3003 ActivityManager am = 3004 (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); 3005 am.switchUser(UserHandle.USER_SYSTEM); 3006 } 3007 } 3008 3009 @Override 3010 public void onEphemeralUserStop(int userId) { 3011 synchronized (mUsersLock) { 3012 UserInfo userInfo = getUserInfoLU(userId); 3013 if (userInfo != null && userInfo.isEphemeral()) { 3014 // Do not allow switching back to the ephemeral user again as the user is going 3015 // to be deleted. 3016 userInfo.flags |= UserInfo.FLAG_DISABLED; 3017 if (userInfo.isGuest()) { 3018 // Indicate that the guest will be deleted after it stops. 3019 userInfo.guestToRemove = true; 3020 } 3021 } 3022 } 3023 } 3024 3025 @Override 3026 public UserInfo createUserEvenWhenDisallowed(String name, int flags) { 3027 UserInfo user = createUserInternalUnchecked(name, flags, UserHandle.USER_NULL); 3028 // Keep this in sync with UserManager.createUser 3029 if (user != null && !user.isAdmin()) { 3030 setUserRestriction(UserManager.DISALLOW_SMS, true, user.id); 3031 setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, true, user.id); 3032 } 3033 return user; 3034 } 3035 } 3036 3037 /* Remove all the users except of the system one. */ 3038 private void removeNonSystemUsers() { 3039 ArrayList<UserInfo> usersToRemove = new ArrayList<>(); 3040 synchronized (mUsersLock) { 3041 final int userSize = mUsers.size(); 3042 for (int i = 0; i < userSize; i++) { 3043 UserInfo ui = mUsers.valueAt(i).info; 3044 if (ui.id != UserHandle.USER_SYSTEM) { 3045 usersToRemove.add(ui); 3046 } 3047 } 3048 } 3049 for (UserInfo ui: usersToRemove) { 3050 removeUser(ui.id); 3051 } 3052 } 3053 3054 private class Shell extends ShellCommand { 3055 @Override 3056 public int onCommand(String cmd) { 3057 return onShellCommand(this, cmd); 3058 } 3059 3060 @Override 3061 public void onHelp() { 3062 final PrintWriter pw = getOutPrintWriter(); 3063 pw.println("User manager (user) commands:"); 3064 pw.println(" help"); 3065 pw.println(" Print this help text."); 3066 pw.println(""); 3067 pw.println(" list"); 3068 pw.println(" Prints all users on the system."); 3069 } 3070 } 3071 3072 private static void debug(String message) { 3073 Log.d(LOG_TAG, message + 3074 (DBG_WITH_STACKTRACE ? " called at\n" + Debug.getCallers(10, " ") : "")); 3075 } 3076} 3077