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