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