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