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