blob: 90d500e53ab38a285c6023bbbe4529f76cfc258e [file] [log] [blame]
Tony Mak8673b282016-03-21 21:10:59 +00001
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002/*
3 * Copyright (C) 2011 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package com.android.server.pm;
19
Xiaohui Chenb3b92582015-12-07 11:22:13 -080020import android.Manifest;
Xiaohui Chen594f2082015-08-18 11:04:20 -070021import android.annotation.NonNull;
Makoto Onuki068c54a2015-10-13 14:34:03 -070022import android.annotation.Nullable;
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -060023import android.annotation.UserIdInt;
Amith Yamasanidb6a14c2012-10-17 21:16:52 -070024import android.app.Activity;
Amith Yamasani2a003292012-08-14 18:25:45 -070025import android.app.ActivityManager;
Amith Yamasani515d4062015-09-28 11:30:06 -070026import android.app.ActivityManagerInternal;
Dianne Hackborn80a4af22012-08-27 19:18:31 -070027import android.app.ActivityManagerNative;
Todd Kennedy60459ab2015-10-30 11:32:16 -070028import android.app.IActivityManager;
Dianne Hackborn80a4af22012-08-27 19:18:31 -070029import android.app.IStopUserCallback;
Amith Yamasanidb6a14c2012-10-17 21:16:52 -070030import android.content.BroadcastReceiver;
Amith Yamasani258848d2012-08-10 17:06:33 -070031import android.content.Context;
32import android.content.Intent;
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +010033import android.content.IntentFilter;
Amith Yamasani0b285492011-04-14 17:35:23 -070034import android.content.pm.PackageManager;
Amith Yamasanidf2e92a2013-03-01 17:04:38 -080035import android.content.pm.PackageManager.NameNotFoundException;
Amith Yamasani4b2e9342011-03-31 12:38:53 -070036import android.content.pm.UserInfo;
Lenka Trochtova02fee152015-12-22 14:26:18 +010037import android.content.res.Resources;
Amith Yamasanie928d7d2012-09-17 21:46:51 -070038import android.graphics.Bitmap;
Amith Yamasani258848d2012-08-10 17:06:33 -070039import android.os.Binder;
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -060040import android.os.Build;
Amith Yamasanie4cf7342012-12-17 11:12:09 -080041import android.os.Bundle;
Makoto Onuki1a2cd742015-11-16 13:51:27 -080042import android.os.Debug;
Amith Yamasani4b2e9342011-03-31 12:38:53 -070043import android.os.Environment;
44import android.os.FileUtils;
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -080045import android.os.Handler;
Svet Ganov9cea80cd2016-02-16 11:47:00 -080046import android.os.IBinder;
Amith Yamasani258848d2012-08-10 17:06:33 -070047import android.os.IUserManager;
Fyodor Kupolov75d0ea82014-12-15 16:21:07 -080048import android.os.Message;
Adrian Roos1bdff912015-02-17 15:51:35 +010049import android.os.ParcelFileDescriptor;
Fyodor Kupolov262f9952015-03-23 18:55:11 -070050import android.os.Parcelable;
Amith Yamasani12747872015-12-07 14:19:49 -080051import android.os.PersistableBundle;
Amith Yamasani258848d2012-08-10 17:06:33 -070052import android.os.Process;
Dianne Hackborn80a4af22012-08-27 19:18:31 -070053import android.os.RemoteException;
Todd Kennedy60459ab2015-10-30 11:32:16 -070054import android.os.ResultReceiver;
Oleksandr Peletskyicd6fa302016-02-25 16:28:39 +010055import android.os.SELinux;
Jason Monk62062992014-05-06 09:55:28 -040056import android.os.ServiceManager;
Todd Kennedy60459ab2015-10-30 11:32:16 -070057import android.os.ShellCommand;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070058import android.os.UserHandle;
Jeff Sharkey27bd34d2012-09-16 12:49:00 -070059import android.os.UserManager;
Makoto Onuki068c54a2015-10-13 14:34:03 -070060import android.os.UserManagerInternal;
Makoto Onukid45a4a22015-11-02 17:17:38 -080061import android.os.UserManagerInternal.UserRestrictionsListener;
Paul Crowley85e4e812015-05-19 12:42:00 +010062import android.os.storage.StorageManager;
Jeff Sharkey6dce4962015-07-03 18:08:41 -070063import android.os.storage.VolumeInfo;
64import android.system.ErrnoException;
65import android.system.Os;
66import android.system.OsConstants;
Amith Yamasani2a003292012-08-14 18:25:45 -070067import android.util.AtomicFile;
Amith Yamasani655d0e22013-06-12 14:19:10 -070068import android.util.Log;
Amith Yamasani4b2e9342011-03-31 12:38:53 -070069import android.util.Slog;
70import android.util.SparseArray;
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -080071import android.util.SparseBooleanArray;
Amith Yamasani920ace02012-09-20 22:15:37 -070072import android.util.TimeUtils;
Amith Yamasani4b2e9342011-03-31 12:38:53 -070073import android.util.Xml;
74
Makoto Onuki068c54a2015-10-13 14:34:03 -070075import com.android.internal.annotations.GuardedBy;
Fyodor Kupolov262f9952015-03-23 18:55:11 -070076import com.android.internal.annotations.VisibleForTesting;
Jason Monk62062992014-05-06 09:55:28 -040077import com.android.internal.app.IAppOpsService;
Fyodor Kupolov8385e4b2015-12-29 18:15:32 -080078import com.android.internal.logging.MetricsLogger;
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -080079import com.android.internal.util.FastXmlSerializer;
Makoto Onuki068c54a2015-10-13 14:34:03 -070080import com.android.internal.util.Preconditions;
Fyodor Kupolov262f9952015-03-23 18:55:11 -070081import com.android.internal.util.XmlUtils;
Clara Bayarri10ad84a2015-12-01 17:38:05 +000082import com.android.internal.widget.LockPatternUtils;
Amith Yamasani515d4062015-09-28 11:30:06 -070083import com.android.server.LocalServices;
Jeff Sharkey47f71082016-02-01 17:03:54 -070084
85import libcore.io.IoUtils;
86import libcore.util.Objects;
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -080087
88import org.xmlpull.v1.XmlPullParser;
89import org.xmlpull.v1.XmlPullParserException;
90import org.xmlpull.v1.XmlSerializer;
91
Amith Yamasani4b2e9342011-03-31 12:38:53 -070092import java.io.BufferedOutputStream;
93import java.io.File;
Amith Yamasani920ace02012-09-20 22:15:37 -070094import java.io.FileDescriptor;
Amith Yamasani4b2e9342011-03-31 12:38:53 -070095import java.io.FileInputStream;
Amith Yamasanib8151ec2012-04-18 18:02:48 -070096import java.io.FileNotFoundException;
Amith Yamasani4b2e9342011-03-31 12:38:53 -070097import java.io.FileOutputStream;
98import java.io.IOException;
Amith Yamasani920ace02012-09-20 22:15:37 -070099import java.io.PrintWriter;
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +0100100import java.nio.charset.StandardCharsets;
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700101import java.util.ArrayList;
102import java.util.List;
103
Makoto Onuki068c54a2015-10-13 14:34:03 -0700104/**
105 * Service for {@link UserManager}.
106 *
107 * Method naming convention:
Fyodor Kupolov82402752015-10-28 14:54:51 -0700108 * <ul>
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800109 * <li> Methods suffixed with "LP" should be called within the {@link #mPackagesLock} lock.
Fyodor Kupolov82402752015-10-28 14:54:51 -0700110 * <li> Methods suffixed with "LR" should be called within the {@link #mRestrictionsLock} lock.
111 * <li> Methods suffixed with "LU" should be called within the {@link #mUsersLock} lock.
112 * </ul>
Makoto Onuki068c54a2015-10-13 14:34:03 -0700113 */
Amith Yamasani258848d2012-08-10 17:06:33 -0700114public class UserManagerService extends IUserManager.Stub {
Amith Yamasani2a003292012-08-14 18:25:45 -0700115 private static final String LOG_TAG = "UserManagerService";
Makoto Onuki81c61ea2016-01-22 11:22:26 -0800116 static final boolean DBG = false; // DO NOT SUBMIT WITH TRUE
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800117 private static final boolean DBG_WITH_STACKTRACE = false; // DO NOT SUBMIT WITH TRUE
Amith Yamasani16389312012-10-17 21:20:14 -0700118
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700119 private static final String TAG_NAME = "name";
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800120 private static final String TAG_ACCOUNT = "account";
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700121 private static final String ATTR_FLAGS = "flags";
Amith Yamasanib8151ec2012-04-18 18:02:48 -0700122 private static final String ATTR_ICON_PATH = "icon";
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700123 private static final String ATTR_ID = "id";
Amith Yamasani920ace02012-09-20 22:15:37 -0700124 private static final String ATTR_CREATION_TIME = "created";
125 private static final String ATTR_LAST_LOGGED_IN_TIME = "lastLoggedIn";
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -0600126 private static final String ATTR_LAST_LOGGED_IN_FINGERPRINT = "lastLoggedInFingerprint";
Amith Yamasani2a003292012-08-14 18:25:45 -0700127 private static final String ATTR_SERIAL_NO = "serialNumber";
128 private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber";
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700129 private static final String ATTR_PARTIAL = "partial";
Adam Lesinskieddeb492014-09-08 17:50:03 -0700130 private static final String ATTR_GUEST_TO_REMOVE = "guestToRemove";
Amith Yamasani6f34b412012-10-22 18:19:27 -0700131 private static final String ATTR_USER_VERSION = "version";
Kenny Guy2a764942014-04-02 13:29:20 +0100132 private static final String ATTR_PROFILE_GROUP_ID = "profileGroupId";
Fyodor Kupolov06a484a2015-08-21 16:33:20 -0700133 private static final String ATTR_RESTRICTED_PROFILE_PARENT_ID = "restrictedProfileParentId";
Amith Yamasani12747872015-12-07 14:19:49 -0800134 private static final String ATTR_SEED_ACCOUNT_NAME = "seedAccountName";
135 private static final String ATTR_SEED_ACCOUNT_TYPE = "seedAccountType";
Amith Yamasanie4afaa32014-06-30 14:55:07 +0530136 private static final String TAG_GUEST_RESTRICTIONS = "guestRestrictions";
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700137 private static final String TAG_USERS = "users";
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700138 private static final String TAG_USER = "user";
Amith Yamasanie4cf7342012-12-17 11:12:09 -0800139 private static final String TAG_RESTRICTIONS = "restrictions";
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800140 private static final String TAG_DEVICE_POLICY_RESTRICTIONS = "device_policy_restrictions";
Amith Yamasanidf2e92a2013-03-01 17:04:38 -0800141 private static final String TAG_ENTRY = "entry";
142 private static final String TAG_VALUE = "value";
Amith Yamasani12747872015-12-07 14:19:49 -0800143 private static final String TAG_SEED_ACCOUNT_OPTIONS = "seedAccountOptions";
Amith Yamasanidf2e92a2013-03-01 17:04:38 -0800144 private static final String ATTR_KEY = "key";
Amith Yamasani7e99bc02013-04-16 18:24:51 -0700145 private static final String ATTR_VALUE_TYPE = "type";
Amith Yamasanidf2e92a2013-03-01 17:04:38 -0800146 private static final String ATTR_MULTIPLE = "m";
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700147
Amith Yamasani7e99bc02013-04-16 18:24:51 -0700148 private static final String ATTR_TYPE_STRING_ARRAY = "sa";
149 private static final String ATTR_TYPE_STRING = "s";
150 private static final String ATTR_TYPE_BOOLEAN = "b";
Amith Yamasani5b5aa402014-06-01 20:10:14 -0700151 private static final String ATTR_TYPE_INTEGER = "i";
Fyodor Kupolov262f9952015-03-23 18:55:11 -0700152 private static final String ATTR_TYPE_BUNDLE = "B";
153 private static final String ATTR_TYPE_BUNDLE_ARRAY = "BA";
Amith Yamasani7e99bc02013-04-16 18:24:51 -0700154
Amith Yamasani0b285492011-04-14 17:35:23 -0700155 private static final String USER_INFO_DIR = "system" + File.separator + "users";
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700156 private static final String USER_LIST_FILENAME = "userlist.xml";
Amith Yamasanib8151ec2012-04-18 18:02:48 -0700157 private static final String USER_PHOTO_FILENAME = "photo.png";
Adrian Roos1bdff912015-02-17 15:51:35 +0100158 private static final String USER_PHOTO_FILENAME_TMP = USER_PHOTO_FILENAME + ".tmp";
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700159
Amith Yamasanidf2e92a2013-03-01 17:04:38 -0800160 private static final String RESTRICTIONS_FILE_PREFIX = "res_";
Amith Yamasanifc95e702013-09-26 13:20:17 -0700161 private static final String XML_SUFFIX = ".xml";
Amith Yamasanidf2e92a2013-03-01 17:04:38 -0800162
Amith Yamasani634cf312012-10-04 17:34:21 -0700163 private static final int MIN_USER_ID = 10;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700164 // We need to keep process uid within Integer.MAX_VALUE.
165 private static final int MAX_USER_ID = Integer.MAX_VALUE / UserHandle.PER_USER_RANGE;
Amith Yamasani634cf312012-10-04 17:34:21 -0700166
Fyodor Kupolov1c363152015-09-02 13:27:21 -0700167 private static final int USER_VERSION = 6;
Amith Yamasani6f34b412012-10-22 18:19:27 -0700168
Amith Yamasani920ace02012-09-20 22:15:37 -0700169 private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // ms
170
Nicolas Prevotb8186812015-08-06 15:00:03 +0100171 // Maximum number of managed profiles permitted per user is 1. This cannot be increased
Amith Yamasani95ab7842014-08-11 17:09:26 -0700172 // without first making sure that the rest of the framework is prepared for it.
173 private static final int MAX_MANAGED_PROFILES = 1;
174
Fyodor Kupolov75d0ea82014-12-15 16:21:07 -0800175 static final int WRITE_USER_MSG = 1;
176 static final int WRITE_USER_DELAY = 2*1000; // 2 seconds
Amith Yamasanie4afaa32014-06-30 14:55:07 +0530177
Jeff Sharkey6dce4962015-07-03 18:08:41 -0700178 private static final String XATTR_SERIAL = "user.serial";
179
Fyodor Kupolov8385e4b2015-12-29 18:15:32 -0800180 // Tron counters
181 private static final String TRON_GUEST_CREATED = "users_guest_created";
182 private static final String TRON_USER_CREATED = "users_user_created";
183
Dianne Hackborn4428e172012-08-24 17:43:05 -0700184 private final Context mContext;
185 private final PackageManagerService mPm;
Dianne Hackborn4428e172012-08-24 17:43:05 -0700186 private final Object mPackagesLock;
Fyodor Kupolov82402752015-10-28 14:54:51 -0700187 // Short-term lock for internal state, when interaction/sync with PM is not required
188 private final Object mUsersLock = new Object();
189 private final Object mRestrictionsLock = new Object();
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700190
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -0800191 private final Handler mHandler;
192
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700193 private final File mUsersDir;
194 private final File mUserListFile;
Dianne Hackborn4428e172012-08-24 17:43:05 -0700195
Svet Ganov9cea80cd2016-02-16 11:47:00 -0800196 private static final IBinder mUserRestriconToken = new Binder();
197
Makoto Onuki068c54a2015-10-13 14:34:03 -0700198 /**
Amith Yamasani12747872015-12-07 14:19:49 -0800199 * User-related information that is used for persisting to flash. Only UserInfo is
200 * directly exposed to other system apps.
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800201 */
Amith Yamasani12747872015-12-07 14:19:49 -0800202 private static class UserData {
203 // Basic user information and properties
204 UserInfo info;
205 // Account name used when there is a strong association between a user and an account
206 String account;
207 // Account information for seeding into a newly created user. This could also be
208 // used for login validation for an existing user, for updating their credentials.
209 // In the latter case, data may not need to be persisted as it is only valid for the
210 // current login session.
211 String seedAccountName;
212 String seedAccountType;
213 PersistableBundle seedAccountOptions;
214 // Whether to perist the seed account information to be available after a boot
215 boolean persistSeedData;
216
217 void clearSeedAccountData() {
218 seedAccountName = null;
219 seedAccountType = null;
220 seedAccountOptions = null;
221 persistSeedData = false;
222 }
223 }
224
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800225 @GuardedBy("mUsersLock")
Amith Yamasani12747872015-12-07 14:19:49 -0800226 private final SparseArray<UserData> mUsers = new SparseArray<>();
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800227
228 /**
Makoto Onuki068c54a2015-10-13 14:34:03 -0700229 * User restrictions set via UserManager. This doesn't include restrictions set by
230 * device owner / profile owners.
231 *
232 * DO NOT Change existing {@link Bundle} in it. When changing a restriction for a user,
233 * a new {@link Bundle} should always be created and set. This is because a {@link Bundle}
234 * maybe shared between {@link #mBaseUserRestrictions} and
235 * {@link #mCachedEffectiveUserRestrictions}, but they should always updated separately.
236 * (Otherwise we won't be able to detect what restrictions have changed in
Fyodor Kupolov82402752015-10-28 14:54:51 -0700237 * {@link #updateUserRestrictionsInternalLR}.
Makoto Onuki068c54a2015-10-13 14:34:03 -0700238 */
239 @GuardedBy("mRestrictionsLock")
240 private final SparseArray<Bundle> mBaseUserRestrictions = new SparseArray<>();
241
242 /**
243 * Cached user restrictions that are in effect -- i.e. {@link #mBaseUserRestrictions} combined
244 * with device / profile owner restrictions. We'll initialize it lazily; use
245 * {@link #getEffectiveUserRestrictions} to access it.
246 *
247 * DO NOT Change existing {@link Bundle} in it. When changing a restriction for a user,
248 * a new {@link Bundle} should always be created and set. This is because a {@link Bundle}
249 * maybe shared between {@link #mBaseUserRestrictions} and
250 * {@link #mCachedEffectiveUserRestrictions}, but they should always updated separately.
251 * (Otherwise we won't be able to detect what restrictions have changed in
Fyodor Kupolov82402752015-10-28 14:54:51 -0700252 * {@link #updateUserRestrictionsInternalLR}.
Makoto Onuki068c54a2015-10-13 14:34:03 -0700253 */
254 @GuardedBy("mRestrictionsLock")
255 private final SparseArray<Bundle> mCachedEffectiveUserRestrictions = new SparseArray<>();
256
Makoto Onuki4f160732015-10-27 17:15:38 -0700257 /**
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800258 * User restrictions that have already been applied in
259 * {@link #updateUserRestrictionsInternalLR(Bundle, int)}. We use it to detect restrictions
260 * that have changed since the last
261 * {@link #updateUserRestrictionsInternalLR(Bundle, int)} call.
Makoto Onuki4f160732015-10-27 17:15:38 -0700262 */
263 @GuardedBy("mRestrictionsLock")
264 private final SparseArray<Bundle> mAppliedUserRestrictions = new SparseArray<>();
265
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800266 /**
Makoto Onukie7927da2015-11-25 10:05:17 -0800267 * User restrictions set by {@link com.android.server.devicepolicy.DevicePolicyManagerService}
268 * that should be applied to all users, including guests.
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800269 */
270 @GuardedBy("mRestrictionsLock")
271 private Bundle mDevicePolicyGlobalUserRestrictions;
272
273 /**
Makoto Onukie7927da2015-11-25 10:05:17 -0800274 * User restrictions set by {@link com.android.server.devicepolicy.DevicePolicyManagerService}
275 * for each user.
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800276 */
277 @GuardedBy("mRestrictionsLock")
278 private final SparseArray<Bundle> mDevicePolicyLocalUserRestrictions = new SparseArray<>();
279
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800280 @GuardedBy("mGuestRestrictions")
Amith Yamasanie4afaa32014-06-30 14:55:07 +0530281 private final Bundle mGuestRestrictions = new Bundle();
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -0800282
283 /**
284 * Set of user IDs being actively removed. Removed IDs linger in this set
285 * for several seconds to work around a VFS caching issue.
286 */
Fyodor Kupolov82402752015-10-28 14:54:51 -0700287 @GuardedBy("mUsersLock")
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -0800288 private final SparseBooleanArray mRemovingUserIds = new SparseBooleanArray();
Dianne Hackborn4428e172012-08-24 17:43:05 -0700289
Fyodor Kupolov82402752015-10-28 14:54:51 -0700290 @GuardedBy("mUsersLock")
Amith Yamasani0b285492011-04-14 17:35:23 -0700291 private int[] mUserIds;
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800292 @GuardedBy("mPackagesLock")
Amith Yamasani2a003292012-08-14 18:25:45 -0700293 private int mNextSerialNumber;
Amith Yamasani6f34b412012-10-22 18:19:27 -0700294 private int mUserVersion = 0;
Amith Yamasani0b285492011-04-14 17:35:23 -0700295
Jason Monk62062992014-05-06 09:55:28 -0400296 private IAppOpsService mAppOpsService;
297
Makoto Onuki068c54a2015-10-13 14:34:03 -0700298 private final LocalService mLocalService;
299
Makoto Onukie7927da2015-11-25 10:05:17 -0800300 @GuardedBy("mUsersLock")
301 private boolean mIsDeviceManaged;
302
303 @GuardedBy("mUsersLock")
304 private final SparseBooleanArray mIsUserManaged = new SparseBooleanArray();
305
Makoto Onukid45a4a22015-11-02 17:17:38 -0800306 @GuardedBy("mUserRestrictionsListeners")
307 private final ArrayList<UserRestrictionsListener> mUserRestrictionsListeners =
308 new ArrayList<>();
309
Clara Bayarria1771112015-12-18 16:29:18 +0000310 private final LockPatternUtils mLockPatternUtils;
311
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +0100312 /**
313 * Whether all users should be created ephemeral.
314 */
315 @GuardedBy("mUsersLock")
316 private boolean mForceEphemeralUsers;
317
Amith Yamasani258848d2012-08-10 17:06:33 -0700318 private static UserManagerService sInstance;
Amith Yamasani258848d2012-08-10 17:06:33 -0700319
Dianne Hackborn4428e172012-08-24 17:43:05 -0700320 public static UserManagerService getInstance() {
321 synchronized (UserManagerService.class) {
322 return sInstance;
Amith Yamasani258848d2012-08-10 17:06:33 -0700323 }
Amith Yamasani258848d2012-08-10 17:06:33 -0700324 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700325
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800326 @VisibleForTesting
327 UserManagerService(File dataDir) {
328 this(null, null, new Object(), dataDir);
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700329 }
330
Dianne Hackborn4428e172012-08-24 17:43:05 -0700331 /**
332 * Called by package manager to create the service. This is closely
333 * associated with the package manager, and the given lock is the
334 * package manager's own lock.
335 */
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800336 UserManagerService(Context context, PackageManagerService pm, Object packagesLock) {
337 this(context, pm, packagesLock, Environment.getDataDirectory());
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700338 }
339
Dianne Hackborn4428e172012-08-24 17:43:05 -0700340 private UserManagerService(Context context, PackageManagerService pm,
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800341 Object packagesLock, File dataDir) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700342 mContext = context;
343 mPm = pm;
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700344 mPackagesLock = packagesLock;
Fyodor Kupolov75d0ea82014-12-15 16:21:07 -0800345 mHandler = new MainHandler();
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800346 synchronized (mPackagesLock) {
347 mUsersDir = new File(dataDir, USER_INFO_DIR);
348 mUsersDir.mkdirs();
349 // Make zeroth user directory, for services to migrate their files to that location
350 File userZeroDir = new File(mUsersDir, String.valueOf(UserHandle.USER_SYSTEM));
351 userZeroDir.mkdirs();
352 FileUtils.setPermissions(mUsersDir.toString(),
353 FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IROTH | FileUtils.S_IXOTH,
354 -1, -1);
355 mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
356 initDefaultGuestRestrictions();
357 readUserListLP();
358 sInstance = this;
Xiaohui Chen4be96e42015-05-06 09:55:43 -0700359 }
Makoto Onuki068c54a2015-10-13 14:34:03 -0700360 mLocalService = new LocalService();
361 LocalServices.addService(UserManagerInternal.class, mLocalService);
Clara Bayarria1771112015-12-18 16:29:18 +0000362 mLockPatternUtils = new LockPatternUtils(mContext);
Xiaohui Chen4be96e42015-05-06 09:55:43 -0700363 }
364
365 void systemReady() {
Lenka Trochtovac4dd0212015-11-18 12:22:06 +0100366 // Prune out any partially created, partially removed and ephemeral users.
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800367 ArrayList<UserInfo> partials = new ArrayList<>();
368 synchronized (mUsersLock) {
369 final int userSize = mUsers.size();
370 for (int i = 0; i < userSize; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -0800371 UserInfo ui = mUsers.valueAt(i).info;
Lenka Trochtovac4dd0212015-11-18 12:22:06 +0100372 if ((ui.partial || ui.guestToRemove || ui.isEphemeral()) && i != 0) {
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800373 partials.add(ui);
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700374 }
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700375 }
Dianne Hackborn4428e172012-08-24 17:43:05 -0700376 }
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800377 final int partialsSize = partials.size();
378 for (int i = 0; i < partialsSize; i++) {
379 UserInfo ui = partials.get(i);
380 Slog.w(LOG_TAG, "Removing partially created user " + ui.id
381 + " (name=" + ui.name + ")");
382 removeUserState(ui.id);
383 }
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800384
Jason Monk62062992014-05-06 09:55:28 -0400385 mAppOpsService = IAppOpsService.Stub.asInterface(
386 ServiceManager.getService(Context.APP_OPS_SERVICE));
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800387
388 synchronized (mRestrictionsLock) {
389 applyUserRestrictionsLR(UserHandle.USER_SYSTEM);
Jason Monk62062992014-05-06 09:55:28 -0400390 }
Samuel Tand9453b82016-03-14 15:57:02 -0700391
392 UserInfo currentGuestUser = findCurrentGuestUser();
393 if (currentGuestUser != null && !hasUserRestriction(
394 UserManager.DISALLOW_CONFIG_WIFI, currentGuestUser.id)) {
395 // If a guest user currently exists, apply the DISALLOW_CONFIG_WIFI option
396 // to it, in case this guest was created in a previous version where this
397 // user restriction was not a default guest restriction.
398 setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true, currentGuestUser.id);
399 }
Amith Yamasani258848d2012-08-10 17:06:33 -0700400 }
401
402 @Override
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800403 public String getUserAccount(int userId) {
404 checkManageUserAndAcrossUsersFullPermission("get user account");
405 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -0800406 return mUsers.get(userId).account;
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800407 }
408 }
409
410 @Override
411 public void setUserAccount(int userId, String accountName) {
412 checkManageUserAndAcrossUsersFullPermission("set user account");
Amith Yamasani12747872015-12-07 14:19:49 -0800413 UserData userToUpdate = null;
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800414 synchronized (mPackagesLock) {
415 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -0800416 final UserData userData = mUsers.get(userId);
417 if (userData == null) {
418 Slog.e(LOG_TAG, "User not found for setting user account: u" + userId);
419 return;
420 }
421 String currentAccount = userData.account;
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800422 if (!Objects.equal(currentAccount, accountName)) {
Amith Yamasani12747872015-12-07 14:19:49 -0800423 userData.account = accountName;
424 userToUpdate = userData;
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800425 }
426 }
427
428 if (userToUpdate != null) {
429 writeUserLP(userToUpdate);
430 }
431 }
432 }
433
434 @Override
Xiaohui Chen70f6c382015-04-28 14:21:43 -0700435 public UserInfo getPrimaryUser() {
436 checkManageUsersPermission("query users");
Fyodor Kupolov82402752015-10-28 14:54:51 -0700437 synchronized (mUsersLock) {
Amith Yamasani515d4062015-09-28 11:30:06 -0700438 final int userSize = mUsers.size();
439 for (int i = 0; i < userSize; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -0800440 UserInfo ui = mUsers.valueAt(i).info;
Xiaohui Chend3e9e182015-11-18 13:37:32 -0800441 if (ui.isPrimary() && !mRemovingUserIds.get(ui.id)) {
Xiaohui Chen70f6c382015-04-28 14:21:43 -0700442 return ui;
443 }
444 }
445 }
446 return null;
447 }
448
449 @Override
Xiaohui Chen594f2082015-08-18 11:04:20 -0700450 public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
Amith Yamasani2a003292012-08-14 18:25:45 -0700451 checkManageUsersPermission("query users");
Fyodor Kupolov82402752015-10-28 14:54:51 -0700452 synchronized (mUsersLock) {
Amith Yamasani13593602012-03-22 16:16:17 -0700453 ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
Amith Yamasani515d4062015-09-28 11:30:06 -0700454 final int userSize = mUsers.size();
455 for (int i = 0; i < userSize; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -0800456 UserInfo ui = mUsers.valueAt(i).info;
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700457 if (ui.partial) {
458 continue;
459 }
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -0800460 if (!excludeDying || !mRemovingUserIds.get(ui.id)) {
Amith Yamasani6f48d6e2016-03-23 14:28:25 -0700461 users.add(userWithName(ui));
Amith Yamasani920ace02012-09-20 22:15:37 -0700462 }
Amith Yamasani13593602012-03-22 16:16:17 -0700463 }
464 return users;
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700465 }
Amith Yamasani13593602012-03-22 16:16:17 -0700466 }
467
Amith Yamasani258848d2012-08-10 17:06:33 -0700468 @Override
Alexandra Gherghina385124d2014-04-03 13:37:39 +0100469 public List<UserInfo> getProfiles(int userId, boolean enabledOnly) {
Amith Yamasani4f582632014-02-19 14:31:52 -0800470 if (userId != UserHandle.getCallingUserId()) {
471 checkManageUsersPermission("getting profiles related to user " + userId);
472 }
Amith Yamasanibe465322014-04-24 13:45:17 -0700473 final long ident = Binder.clearCallingIdentity();
474 try {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700475 synchronized (mUsersLock) {
476 return getProfilesLU(userId, enabledOnly);
Alexandra Gherghina385124d2014-04-03 13:37:39 +0100477 }
Amith Yamasanibe465322014-04-24 13:45:17 -0700478 } finally {
479 Binder.restoreCallingIdentity(ident);
Kenny Guya52dc3e2014-02-11 15:33:14 +0000480 }
481 }
482
Amith Yamasanibe465322014-04-24 13:45:17 -0700483 /** Assume permissions already checked and caller's identity cleared */
Fyodor Kupolov82402752015-10-28 14:54:51 -0700484 private List<UserInfo> getProfilesLU(int userId, boolean enabledOnly) {
485 UserInfo user = getUserInfoLU(userId);
Amith Yamasanibe465322014-04-24 13:45:17 -0700486 ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
Amith Yamasanidda003f2014-08-28 18:06:51 -0700487 if (user == null) {
488 // Probably a dying user
489 return users;
490 }
Amith Yamasani515d4062015-09-28 11:30:06 -0700491 final int userSize = mUsers.size();
492 for (int i = 0; i < userSize; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -0800493 UserInfo profile = mUsers.valueAt(i).info;
Amith Yamasanibe465322014-04-24 13:45:17 -0700494 if (!isProfileOf(user, profile)) {
495 continue;
496 }
Alexandra Gherghinadf35d572014-04-09 13:54:39 +0100497 if (enabledOnly && !profile.isEnabled()) {
498 continue;
Amith Yamasanibe465322014-04-24 13:45:17 -0700499 }
Amith Yamasani70fcf0c2014-07-11 08:40:19 -0700500 if (mRemovingUserIds.get(profile.id)) {
501 continue;
502 }
Amith Yamasani6f48d6e2016-03-23 14:28:25 -0700503 users.add(userWithName(profile));
Amith Yamasanibe465322014-04-24 13:45:17 -0700504 }
505 return users;
506 }
507
Jessica Hummelbe81c802014-04-22 15:49:22 +0100508 @Override
Andres Moralesc5548c02015-08-05 10:23:12 -0700509 public int getCredentialOwnerProfile(int userHandle) {
510 checkManageUsersPermission("get the credential owner");
Clara Bayarria1771112015-12-18 16:29:18 +0000511 if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle)) {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700512 synchronized (mUsersLock) {
513 UserInfo profileParent = getProfileParentLU(userHandle);
Andres Moralesc5548c02015-08-05 10:23:12 -0700514 if (profileParent != null) {
515 return profileParent.id;
516 }
517 }
518 }
519
520 return userHandle;
521 }
522
523 @Override
Xiaohui Chenfd5b7742015-10-14 15:47:04 -0700524 public boolean isSameProfileGroup(int userId, int otherUserId) {
525 if (userId == otherUserId) return true;
526 checkManageUsersPermission("check if in the same profile group");
527 synchronized (mPackagesLock) {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700528 return isSameProfileGroupLP(userId, otherUserId);
Xiaohui Chenfd5b7742015-10-14 15:47:04 -0700529 }
530 }
531
Fyodor Kupolov82402752015-10-28 14:54:51 -0700532 private boolean isSameProfileGroupLP(int userId, int otherUserId) {
533 synchronized (mUsersLock) {
534 UserInfo userInfo = getUserInfoLU(userId);
535 if (userInfo == null || userInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
536 return false;
537 }
538 UserInfo otherUserInfo = getUserInfoLU(otherUserId);
539 if (otherUserInfo == null
540 || otherUserInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
541 return false;
542 }
543 return userInfo.profileGroupId == otherUserInfo.profileGroupId;
Xiaohui Chenfd5b7742015-10-14 15:47:04 -0700544 }
Xiaohui Chenfd5b7742015-10-14 15:47:04 -0700545 }
546
547 @Override
Jessica Hummelbe81c802014-04-22 15:49:22 +0100548 public UserInfo getProfileParent(int userHandle) {
549 checkManageUsersPermission("get the profile parent");
Fyodor Kupolov82402752015-10-28 14:54:51 -0700550 synchronized (mUsersLock) {
551 return getProfileParentLU(userHandle);
Fyodor Kupolovff7233e2015-04-08 11:28:52 -0700552 }
553 }
554
Fyodor Kupolov82402752015-10-28 14:54:51 -0700555 private UserInfo getProfileParentLU(int userHandle) {
556 UserInfo profile = getUserInfoLU(userHandle);
Fyodor Kupolovff7233e2015-04-08 11:28:52 -0700557 if (profile == null) {
558 return null;
559 }
560 int parentUserId = profile.profileGroupId;
561 if (parentUserId == UserInfo.NO_PROFILE_GROUP_ID) {
562 return null;
563 } else {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700564 return getUserInfoLU(parentUserId);
Jessica Hummelbe81c802014-04-22 15:49:22 +0100565 }
566 }
567
Fyodor Kupolov82402752015-10-28 14:54:51 -0700568 private static boolean isProfileOf(UserInfo user, UserInfo profile) {
Kenny Guy2a764942014-04-02 13:29:20 +0100569 return user.id == profile.id ||
570 (user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
571 && user.profileGroupId == profile.profileGroupId);
Kenny Guya52dc3e2014-02-11 15:33:14 +0000572 }
573
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000574 private void broadcastProfileAvailabilityChanges(UserHandle profileHandle,
Rubin Xuf13c9802016-01-21 18:06:00 +0000575 UserHandle parentHandle, boolean inQuietMode) {
Rubin Xue95057a2016-04-01 16:49:25 +0100576 Intent intent = new Intent();
577 if (inQuietMode) {
578 intent.setAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
579 } else {
580 intent.setAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
581 }
Rubin Xuf13c9802016-01-21 18:06:00 +0000582 intent.putExtra(Intent.EXTRA_QUIET_MODE, inQuietMode);
583 intent.putExtra(Intent.EXTRA_USER, profileHandle);
584 intent.putExtra(Intent.EXTRA_USER_HANDLE, profileHandle.getIdentifier());
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000585 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Rubin Xuf13c9802016-01-21 18:06:00 +0000586 mContext.sendBroadcastAsUser(intent, parentHandle);
Rubin Xue95057a2016-04-01 16:49:25 +0100587
588 //TODO: remove once Launcher3 is updated.
589 Intent oldIntent = new Intent(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED);
590 oldIntent.putExtra(Intent.EXTRA_QUIET_MODE, inQuietMode);
591 oldIntent.putExtra(Intent.EXTRA_USER, profileHandle);
592 oldIntent.putExtra(Intent.EXTRA_USER_HANDLE, profileHandle.getIdentifier());
593 oldIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
594 mContext.sendBroadcastAsUser(oldIntent, parentHandle);
595
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000596 }
597
598 @Override
599 public void setQuietModeEnabled(int userHandle, boolean enableQuietMode) {
600 checkManageUsersPermission("silence profile");
601 boolean changed = false;
602 UserInfo profile, parent;
603 synchronized (mPackagesLock) {
604 synchronized (mUsersLock) {
605 profile = getUserInfoLU(userHandle);
606 parent = getProfileParentLU(userHandle);
607
608 }
609 if (profile == null || !profile.isManagedProfile()) {
610 throw new IllegalArgumentException("User " + userHandle + " is not a profile");
611 }
612 if (profile.isQuietModeEnabled() != enableQuietMode) {
613 profile.flags ^= UserInfo.FLAG_QUIET_MODE;
Amith Yamasani12747872015-12-07 14:19:49 -0800614 writeUserLP(getUserDataLU(profile.id));
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000615 changed = true;
616 }
617 }
618 if (changed) {
Rubin Xuf13c9802016-01-21 18:06:00 +0000619 long identity = Binder.clearCallingIdentity();
620 try {
621 if (enableQuietMode) {
622 ActivityManagerNative.getDefault().stopUser(userHandle, /* force */true, null);
623 } else {
624 ActivityManagerNative.getDefault().startUserInBackground(userHandle);
625 }
626 } catch (RemoteException e) {
627 Slog.e(LOG_TAG, "fail to start/stop user for quiet mode", e);
628 } finally {
629 Binder.restoreCallingIdentity(identity);
630 }
631
632 broadcastProfileAvailabilityChanges(profile.getUserHandle(), parent.getUserHandle(),
633 enableQuietMode);
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000634 }
635 }
636
637 @Override
638 public boolean isQuietModeEnabled(int userHandle) {
639 synchronized (mPackagesLock) {
640 UserInfo info;
641 synchronized (mUsersLock) {
642 info = getUserInfoLU(userHandle);
643 }
644 if (info == null || !info.isManagedProfile()) {
Rubin Xuf13c9802016-01-21 18:06:00 +0000645 return false;
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000646 }
647 return info.isQuietModeEnabled();
648 }
649 }
650
Kenny Guya52dc3e2014-02-11 15:33:14 +0000651 @Override
Alexandra Gherghinadf35d572014-04-09 13:54:39 +0100652 public void setUserEnabled(int userId) {
653 checkManageUsersPermission("enable user");
654 synchronized (mPackagesLock) {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700655 UserInfo info;
656 synchronized (mUsersLock) {
657 info = getUserInfoLU(userId);
658 }
Alexandra Gherghinadf35d572014-04-09 13:54:39 +0100659 if (info != null && !info.isEnabled()) {
660 info.flags ^= UserInfo.FLAG_DISABLED;
Amith Yamasani12747872015-12-07 14:19:49 -0800661 writeUserLP(getUserDataLU(info.id));
Alexandra Gherghinadf35d572014-04-09 13:54:39 +0100662 }
663 }
664 }
665
666 @Override
Amith Yamasani258848d2012-08-10 17:06:33 -0700667 public UserInfo getUserInfo(int userId) {
Tony Mak8673b282016-03-21 21:10:59 +0000668 checkManageUsersPermission("query user");
669 synchronized (mUsersLock) {
Amith Yamasani6f48d6e2016-03-23 14:28:25 -0700670 return userWithName(getUserInfoLU(userId));
671 }
672 }
673
674 /**
675 * Returns a UserInfo object with the name filled in, for Owner, or the original
676 * if the name is already set.
677 */
678 private UserInfo userWithName(UserInfo orig) {
679 if (orig != null && orig.name == null && orig.id == UserHandle.USER_SYSTEM) {
680 UserInfo withName = new UserInfo(orig);
681 withName.name = getOwnerName();
682 return withName;
683 } else {
684 return orig;
Tony Mak8673b282016-03-21 21:10:59 +0000685 }
686 }
687
688 @Override
689 public boolean isManagedProfile(int userId) {
Tony Makb531d082016-03-16 14:49:52 +0000690 int callingUserId = UserHandle.getCallingUserId();
691 if (callingUserId != userId && !hasManageUsersPermission()) {
692 synchronized (mPackagesLock) {
693 if (!isSameProfileGroupLP(callingUserId, userId)) {
694 throw new SecurityException(
Tony Mak8673b282016-03-21 21:10:59 +0000695 "You need MANAGE_USERS permission to: check if specified user a " +
696 "managed profile outside your profile group");
Tony Makb531d082016-03-16 14:49:52 +0000697 }
698 }
Tony Mak4dc008c2016-03-16 10:46:49 +0000699 }
Fyodor Kupolov82402752015-10-28 14:54:51 -0700700 synchronized (mUsersLock) {
Tony Mak8673b282016-03-21 21:10:59 +0000701 UserInfo userInfo = getUserInfoLU(userId);
702 return userInfo != null && userInfo.isManagedProfile();
Amith Yamasani13593602012-03-22 16:16:17 -0700703 }
704 }
705
Amith Yamasani71e6c692013-03-24 17:39:28 -0700706 @Override
707 public boolean isRestricted() {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700708 synchronized (mUsersLock) {
709 return getUserInfoLU(UserHandle.getCallingUserId()).isRestricted();
Amith Yamasani71e6c692013-03-24 17:39:28 -0700710 }
711 }
712
Fyodor Kupolov1c363152015-09-02 13:27:21 -0700713 @Override
714 public boolean canHaveRestrictedProfile(int userId) {
715 checkManageUsersPermission("canHaveRestrictedProfile");
Fyodor Kupolov82402752015-10-28 14:54:51 -0700716 synchronized (mUsersLock) {
717 final UserInfo userInfo = getUserInfoLU(userId);
Fyodor Kupolov1c363152015-09-02 13:27:21 -0700718 if (userInfo == null || !userInfo.canHaveProfile()) {
719 return false;
720 }
721 if (!userInfo.isAdmin()) {
722 return false;
723 }
Makoto Onukie7927da2015-11-25 10:05:17 -0800724 // restricted profile can be created if there is no DO set and the admin user has no PO;
725 return !mIsDeviceManaged && !mIsUserManaged.get(userId);
Fyodor Kupolov1c363152015-09-02 13:27:21 -0700726 }
Fyodor Kupolov1c363152015-09-02 13:27:21 -0700727 }
728
Amith Yamasani195263742012-08-21 15:40:12 -0700729 /*
730 * Should be locked on mUsers before calling this.
731 */
Fyodor Kupolov82402752015-10-28 14:54:51 -0700732 private UserInfo getUserInfoLU(int userId) {
Amith Yamasani12747872015-12-07 14:19:49 -0800733 final UserData userData = mUsers.get(userId);
Amith Yamasani16389312012-10-17 21:20:14 -0700734 // If it is partial and not in the process of being removed, return as unknown user.
Amith Yamasani12747872015-12-07 14:19:49 -0800735 if (userData != null && userData.info.partial && !mRemovingUserIds.get(userId)) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700736 Slog.w(LOG_TAG, "getUserInfo: unknown user #" + userId);
737 return null;
738 }
Amith Yamasani12747872015-12-07 14:19:49 -0800739 return userData != null ? userData.info : null;
740 }
741
742 private UserData getUserDataLU(int userId) {
743 final UserData userData = mUsers.get(userId);
744 // If it is partial and not in the process of being removed, return as unknown user.
745 if (userData != null && userData.info.partial && !mRemovingUserIds.get(userId)) {
746 return null;
747 }
748 return userData;
Amith Yamasani195263742012-08-21 15:40:12 -0700749 }
750
Fyodor Kupolov82402752015-10-28 14:54:51 -0700751 /**
752 * Obtains {@link #mUsersLock} and return UserInfo from mUsers.
753 * <p>No permissions checking or any addition checks are made</p>
754 */
755 private UserInfo getUserInfoNoChecks(int userId) {
756 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -0800757 final UserData userData = mUsers.get(userId);
758 return userData != null ? userData.info : null;
759 }
760 }
761
762 /**
763 * Obtains {@link #mUsersLock} and return UserData from mUsers.
764 * <p>No permissions checking or any addition checks are made</p>
765 */
766 private UserData getUserDataNoChecks(int userId) {
767 synchronized (mUsersLock) {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700768 return mUsers.get(userId);
769 }
770 }
771
Amith Yamasani236b2b52015-08-18 14:32:14 -0700772 /** Called by PackageManagerService */
Amith Yamasani13593602012-03-22 16:16:17 -0700773 public boolean exists(int userId) {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700774 return getUserInfoNoChecks(userId) != null;
Amith Yamasani13593602012-03-22 16:16:17 -0700775 }
776
Amith Yamasani258848d2012-08-10 17:06:33 -0700777 @Override
Amith Yamasanib8151ec2012-04-18 18:02:48 -0700778 public void setUserName(int userId, String name) {
Amith Yamasani2a003292012-08-14 18:25:45 -0700779 checkManageUsersPermission("rename users");
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700780 boolean changed = false;
Dianne Hackborn4428e172012-08-24 17:43:05 -0700781 synchronized (mPackagesLock) {
Amith Yamasani12747872015-12-07 14:19:49 -0800782 UserData userData = getUserDataNoChecks(userId);
783 if (userData == null || userData.info.partial) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700784 Slog.w(LOG_TAG, "setUserName: unknown user #" + userId);
785 return;
786 }
Amith Yamasani12747872015-12-07 14:19:49 -0800787 if (name != null && !name.equals(userData.info.name)) {
788 userData.info.name = name;
789 writeUserLP(userData);
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700790 changed = true;
Amith Yamasani13593602012-03-22 16:16:17 -0700791 }
792 }
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700793 if (changed) {
794 sendUserInfoChangedBroadcast(userId);
795 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700796 }
797
Amith Yamasani258848d2012-08-10 17:06:33 -0700798 @Override
Amith Yamasanie928d7d2012-09-17 21:46:51 -0700799 public void setUserIcon(int userId, Bitmap bitmap) {
Amith Yamasani2a003292012-08-14 18:25:45 -0700800 checkManageUsersPermission("update users");
Oleksandr Peletskyi7f1f1df2016-01-18 15:40:21 +0100801 if (hasUserRestriction(UserManager.DISALLOW_SET_USER_ICON, userId)) {
802 Log.w(LOG_TAG, "Cannot set user icon. DISALLOW_SET_USER_ICON is enabled.");
803 return;
Amith Yamasanib8151ec2012-04-18 18:02:48 -0700804 }
Oleksandr Peletskyi7f1f1df2016-01-18 15:40:21 +0100805 mLocalService.setUserIcon(userId, bitmap);
Amith Yamasanie928d7d2012-09-17 21:46:51 -0700806 }
807
Oleksandr Peletskyi7f1f1df2016-01-18 15:40:21 +0100808
809
Amith Yamasanie928d7d2012-09-17 21:46:51 -0700810 private void sendUserInfoChangedBroadcast(int userId) {
811 Intent changedIntent = new Intent(Intent.ACTION_USER_INFO_CHANGED);
812 changedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
813 changedIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700814 mContext.sendBroadcastAsUser(changedIntent, UserHandle.ALL);
Amith Yamasanib8151ec2012-04-18 18:02:48 -0700815 }
816
Amith Yamasani258848d2012-08-10 17:06:33 -0700817 @Override
Oleksandr Peletskyicd6fa302016-02-25 16:28:39 +0100818 public ParcelFileDescriptor getUserIcon(int targetUserId) {
Adrian Roos1bdff912015-02-17 15:51:35 +0100819 String iconPath;
Amith Yamasani3b49f072012-09-17 10:21:43 -0700820 synchronized (mPackagesLock) {
Oleksandr Peletskyicd6fa302016-02-25 16:28:39 +0100821 UserInfo targetUserInfo = getUserInfoNoChecks(targetUserId);
822 if (targetUserInfo == null || targetUserInfo.partial) {
823 Slog.w(LOG_TAG, "getUserIcon: unknown user #" + targetUserId);
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700824 return null;
825 }
Oleksandr Peletskyicd6fa302016-02-25 16:28:39 +0100826
827 final int callingUserId = UserHandle.getCallingUserId();
828 final int callingGroupId = getUserInfoNoChecks(callingUserId).profileGroupId;
829 final int targetGroupId = targetUserInfo.profileGroupId;
830 final boolean sameGroup = (callingGroupId != UserInfo.NO_PROFILE_GROUP_ID
831 && callingGroupId == targetGroupId);
832 if ((callingUserId != targetUserId) && !sameGroup) {
Nicolas Prevot88cc3462014-05-14 14:51:48 +0100833 checkManageUsersPermission("get the icon of a user who is not related");
834 }
Oleksandr Peletskyicd6fa302016-02-25 16:28:39 +0100835
836 if (targetUserInfo.iconPath == null) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700837 return null;
838 }
Oleksandr Peletskyicd6fa302016-02-25 16:28:39 +0100839 iconPath = targetUserInfo.iconPath;
Amith Yamasani3b49f072012-09-17 10:21:43 -0700840 }
Adrian Roos1bdff912015-02-17 15:51:35 +0100841
842 try {
843 return ParcelFileDescriptor.open(
844 new File(iconPath), ParcelFileDescriptor.MODE_READ_ONLY);
845 } catch (FileNotFoundException e) {
846 Log.e(LOG_TAG, "Couldn't find icon file", e);
847 }
848 return null;
Amith Yamasani3b49f072012-09-17 10:21:43 -0700849 }
850
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700851 public void makeInitialized(int userId) {
852 checkManageUsersPermission("makeInitialized");
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800853 boolean scheduleWriteUser = false;
Amith Yamasani12747872015-12-07 14:19:49 -0800854 UserData userData;
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800855 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -0800856 userData = mUsers.get(userId);
857 if (userData == null || userData.info.partial) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700858 Slog.w(LOG_TAG, "makeInitialized: unknown user #" + userId);
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800859 return;
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700860 }
Amith Yamasani12747872015-12-07 14:19:49 -0800861 if ((userData.info.flags & UserInfo.FLAG_INITIALIZED) == 0) {
862 userData.info.flags |= UserInfo.FLAG_INITIALIZED;
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800863 scheduleWriteUser = true;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700864 }
865 }
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800866 if (scheduleWriteUser) {
Amith Yamasani12747872015-12-07 14:19:49 -0800867 scheduleWriteUser(userData);
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800868 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700869 }
870
Amith Yamasaniaa6634e2014-10-06 14:20:28 -0700871 /**
872 * If default guest restrictions haven't been initialized yet, add the basic
873 * restrictions.
874 */
875 private void initDefaultGuestRestrictions() {
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800876 synchronized (mGuestRestrictions) {
877 if (mGuestRestrictions.isEmpty()) {
Samuel Tand9453b82016-03-14 15:57:02 -0700878 mGuestRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_WIFI, true);
Fyodor Kupolove04462c2015-11-30 15:02:53 -0800879 mGuestRestrictions.putBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800880 mGuestRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, true);
881 mGuestRestrictions.putBoolean(UserManager.DISALLOW_SMS, true);
882 }
Amith Yamasaniaa6634e2014-10-06 14:20:28 -0700883 }
884 }
885
Amith Yamasanie4cf7342012-12-17 11:12:09 -0800886 @Override
Amith Yamasanie4afaa32014-06-30 14:55:07 +0530887 public Bundle getDefaultGuestRestrictions() {
888 checkManageUsersPermission("getDefaultGuestRestrictions");
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800889 synchronized (mGuestRestrictions) {
Amith Yamasanie4afaa32014-06-30 14:55:07 +0530890 return new Bundle(mGuestRestrictions);
891 }
892 }
893
894 @Override
895 public void setDefaultGuestRestrictions(Bundle restrictions) {
896 checkManageUsersPermission("setDefaultGuestRestrictions");
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800897 synchronized (mGuestRestrictions) {
898 mGuestRestrictions.clear();
899 mGuestRestrictions.putAll(restrictions);
900 }
901 synchronized (mPackagesLock) {
902 writeUserListLP();
Amith Yamasanie4afaa32014-06-30 14:55:07 +0530903 }
904 }
905
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800906 /**
907 * See {@link UserManagerInternal#setDevicePolicyUserRestrictions(int, Bundle, Bundle)}
908 */
Makoto Onuki2a3c3da2016-02-18 14:25:30 -0800909 void setDevicePolicyUserRestrictionsInner(int userId, @NonNull Bundle local,
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800910 @Nullable Bundle global) {
911 Preconditions.checkNotNull(local);
912 boolean globalChanged = false;
913 boolean localChanged;
914 synchronized (mRestrictionsLock) {
915 if (global != null) {
916 // Update global.
917 globalChanged = !UserRestrictionsUtils.areEqual(
918 mDevicePolicyGlobalUserRestrictions, global);
919 if (globalChanged) {
920 mDevicePolicyGlobalUserRestrictions = global;
921 }
922 }
923 {
924 // Update local.
925 final Bundle prev = mDevicePolicyLocalUserRestrictions.get(userId);
926 localChanged = !UserRestrictionsUtils.areEqual(prev, local);
927 if (localChanged) {
928 mDevicePolicyLocalUserRestrictions.put(userId, local);
929 }
930 }
931 }
932 if (DBG) {
933 Log.d(LOG_TAG, "setDevicePolicyUserRestrictions: userId=" + userId
934 + " global=" + global + (globalChanged ? " (changed)" : "")
935 + " local=" + local + (localChanged ? " (changed)" : "")
936 );
937 }
938 // Don't call them within the mRestrictionsLock.
939 synchronized (mPackagesLock) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800940 if (localChanged) {
Amith Yamasani12747872015-12-07 14:19:49 -0800941 writeUserLP(getUserDataNoChecks(userId));
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800942 }
Jeff Sharkeycd575992016-03-29 14:12:49 -0600943 if (globalChanged) {
944 writeUserListLP();
945 }
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800946 }
947
948 synchronized (mRestrictionsLock) {
949 if (globalChanged) {
950 applyUserRestrictionsForAllUsersLR();
951 } else if (localChanged) {
952 applyUserRestrictionsLR(userId);
953 }
954 }
955 }
956
Makoto Onuki068c54a2015-10-13 14:34:03 -0700957 @GuardedBy("mRestrictionsLock")
Fyodor Kupolov82402752015-10-28 14:54:51 -0700958 private Bundle computeEffectiveUserRestrictionsLR(int userId) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800959 final Bundle baseRestrictions =
960 UserRestrictionsUtils.nonNull(mBaseUserRestrictions.get(userId));
961 final Bundle global = mDevicePolicyGlobalUserRestrictions;
962 final Bundle local = mDevicePolicyLocalUserRestrictions.get(userId);
Makoto Onuki068c54a2015-10-13 14:34:03 -0700963
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800964 if (UserRestrictionsUtils.isEmpty(global) && UserRestrictionsUtils.isEmpty(local)) {
965 // Common case first.
966 return baseRestrictions;
Makoto Onuki068c54a2015-10-13 14:34:03 -0700967 }
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800968 final Bundle effective = UserRestrictionsUtils.clone(baseRestrictions);
969 UserRestrictionsUtils.merge(effective, global);
970 UserRestrictionsUtils.merge(effective, local);
971
Makoto Onuki068c54a2015-10-13 14:34:03 -0700972 return effective;
973 }
974
975 @GuardedBy("mRestrictionsLock")
Fyodor Kupolov82402752015-10-28 14:54:51 -0700976 private void invalidateEffectiveUserRestrictionsLR(int userId) {
Makoto Onuki068c54a2015-10-13 14:34:03 -0700977 if (DBG) {
978 Log.d(LOG_TAG, "invalidateEffectiveUserRestrictions userId=" + userId);
979 }
980 mCachedEffectiveUserRestrictions.remove(userId);
981 }
982
983 private Bundle getEffectiveUserRestrictions(int userId) {
984 synchronized (mRestrictionsLock) {
985 Bundle restrictions = mCachedEffectiveUserRestrictions.get(userId);
986 if (restrictions == null) {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700987 restrictions = computeEffectiveUserRestrictionsLR(userId);
Makoto Onuki068c54a2015-10-13 14:34:03 -0700988 mCachedEffectiveUserRestrictions.put(userId, restrictions);
989 }
990 return restrictions;
Amith Yamasani8cd28b52014-06-08 17:54:27 -0700991 }
992 }
993
Makoto Onuki068c54a2015-10-13 14:34:03 -0700994 /** @return a specific user restriction that's in effect currently. */
995 @Override
996 public boolean hasUserRestriction(String restrictionKey, int userId) {
Makoto Onuki1f1ceef2016-01-28 11:32:32 -0800997 if (!UserRestrictionsUtils.isValidRestriction(restrictionKey)) {
998 return false;
999 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07001000 Bundle restrictions = getEffectiveUserRestrictions(userId);
1001 return restrictions != null && restrictions.getBoolean(restrictionKey);
1002 }
1003
1004 /**
1005 * @return UserRestrictions that are in effect currently. This always returns a new
1006 * {@link Bundle}.
1007 */
Amith Yamasani8cd28b52014-06-08 17:54:27 -07001008 @Override
Amith Yamasanie4cf7342012-12-17 11:12:09 -08001009 public Bundle getUserRestrictions(int userId) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001010 return UserRestrictionsUtils.clone(getEffectiveUserRestrictions(userId));
Amith Yamasanie4cf7342012-12-17 11:12:09 -08001011 }
1012
1013 @Override
Zoltan Szatmary-Ban3bbcedd2015-11-26 13:45:51 +00001014 public boolean hasBaseUserRestriction(String restrictionKey, int userId) {
1015 checkManageUsersPermission("hasBaseUserRestriction");
Makoto Onuki1f1ceef2016-01-28 11:32:32 -08001016 if (!UserRestrictionsUtils.isValidRestriction(restrictionKey)) {
1017 return false;
1018 }
Zoltan Szatmary-Ban3bbcedd2015-11-26 13:45:51 +00001019 synchronized (mRestrictionsLock) {
1020 Bundle bundle = mBaseUserRestrictions.get(userId);
1021 return (bundle != null && bundle.getBoolean(restrictionKey, false));
1022 }
1023 }
1024
1025 @Override
Fyodor Kupolovb5013302015-04-17 17:59:14 -07001026 public void setUserRestriction(String key, boolean value, int userId) {
Fyodor Kupolovd4b26042015-07-27 14:30:59 -07001027 checkManageUsersPermission("setUserRestriction");
Makoto Onuki1f1ceef2016-01-28 11:32:32 -08001028 if (!UserRestrictionsUtils.isValidRestriction(key)) {
1029 return;
1030 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07001031 synchronized (mRestrictionsLock) {
1032 // Note we can't modify Bundles stored in mBaseUserRestrictions directly, so create
1033 // a copy.
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001034 final Bundle newRestrictions = UserRestrictionsUtils.clone(
1035 mBaseUserRestrictions.get(userId));
Makoto Onuki068c54a2015-10-13 14:34:03 -07001036 newRestrictions.putBoolean(key, value);
1037
Fyodor Kupolov82402752015-10-28 14:54:51 -07001038 updateUserRestrictionsInternalLR(newRestrictions, userId);
Fyodor Kupolovb5013302015-04-17 17:59:14 -07001039 }
1040 }
1041
Makoto Onuki068c54a2015-10-13 14:34:03 -07001042 /**
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001043 * Optionally updating user restrictions, calculate the effective user restrictions and also
1044 * propagate to other services and system settings.
Makoto Onuki068c54a2015-10-13 14:34:03 -07001045 *
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001046 * @param newRestrictions User restrictions to set.
1047 * If null, will not update user restrictions and only does the propagation.
Makoto Onuki068c54a2015-10-13 14:34:03 -07001048 * @param userId target user ID.
1049 */
1050 @GuardedBy("mRestrictionsLock")
Fyodor Kupolov82402752015-10-28 14:54:51 -07001051 private void updateUserRestrictionsInternalLR(
Makoto Onuki068c54a2015-10-13 14:34:03 -07001052 @Nullable Bundle newRestrictions, int userId) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001053
1054 final Bundle prevAppliedRestrictions = UserRestrictionsUtils.nonNull(
1055 mAppliedUserRestrictions.get(userId));
1056
1057 // Update base restrictions.
Makoto Onuki068c54a2015-10-13 14:34:03 -07001058 if (newRestrictions != null) {
1059 // If newRestrictions == the current one, it's probably a bug.
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001060 final Bundle prevBaseRestrictions = mBaseUserRestrictions.get(userId);
1061
1062 Preconditions.checkState(prevBaseRestrictions != newRestrictions);
Makoto Onuki068c54a2015-10-13 14:34:03 -07001063 Preconditions.checkState(mCachedEffectiveUserRestrictions.get(userId)
1064 != newRestrictions);
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001065
1066 if (!UserRestrictionsUtils.areEqual(prevBaseRestrictions, newRestrictions)) {
1067 mBaseUserRestrictions.put(userId, newRestrictions);
Amith Yamasani12747872015-12-07 14:19:49 -08001068 scheduleWriteUser(getUserDataNoChecks(userId));
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001069 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07001070 }
1071
Fyodor Kupolov82402752015-10-28 14:54:51 -07001072 final Bundle effective = computeEffectiveUserRestrictionsLR(userId);
Makoto Onuki068c54a2015-10-13 14:34:03 -07001073
Makoto Onuki759a7632015-10-28 16:43:10 -07001074 mCachedEffectiveUserRestrictions.put(userId, effective);
1075
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001076 // Apply the new restrictions.
Makoto Onuki4f160732015-10-27 17:15:38 -07001077 if (DBG) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001078 debug("Applying user restrictions: userId=" + userId
1079 + " new=" + effective + " prev=" + prevAppliedRestrictions);
Makoto Onuki4f160732015-10-27 17:15:38 -07001080 }
1081
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001082 if (mAppOpsService != null) { // We skip it until system-ready.
1083 final long token = Binder.clearCallingIdentity();
1084 try {
Svet Ganov9cea80cd2016-02-16 11:47:00 -08001085 mAppOpsService.setUserRestrictions(effective, mUserRestriconToken, userId);
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001086 } catch (RemoteException e) {
1087 Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
1088 } finally {
1089 Binder.restoreCallingIdentity(token);
1090 }
Fyodor Kupolovb5013302015-04-17 17:59:14 -07001091 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07001092
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001093 propagateUserRestrictionsLR(userId, effective, prevAppliedRestrictions);
Makoto Onuki4f160732015-10-27 17:15:38 -07001094
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001095 mAppliedUserRestrictions.put(userId, new Bundle(effective));
Makoto Onuki068c54a2015-10-13 14:34:03 -07001096 }
1097
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001098 private void propagateUserRestrictionsLR(final int userId,
Makoto Onukid45a4a22015-11-02 17:17:38 -08001099 Bundle newRestrictions, Bundle prevRestrictions) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001100 // Note this method doesn't touch any state, meaning it doesn't require mRestrictionsLock
1101 // actually, but we still need some kind of synchronization otherwise we might end up
1102 // calling listeners out-of-order, thus "LR".
1103
1104 if (UserRestrictionsUtils.areEqual(newRestrictions, prevRestrictions)) {
1105 return;
1106 }
Makoto Onukid45a4a22015-11-02 17:17:38 -08001107
1108 final Bundle newRestrictionsFinal = new Bundle(newRestrictions);
1109 final Bundle prevRestrictionsFinal = new Bundle(prevRestrictions);
1110
1111 mHandler.post(new Runnable() {
1112 @Override
1113 public void run() {
Fyodor Kupolov9cbfc9e2015-10-07 15:52:33 -07001114 UserRestrictionsUtils.applyUserRestrictions(
1115 mContext, userId, newRestrictionsFinal, prevRestrictionsFinal);
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001116
Makoto Onukid45a4a22015-11-02 17:17:38 -08001117 final UserRestrictionsListener[] listeners;
1118 synchronized (mUserRestrictionsListeners) {
1119 listeners = new UserRestrictionsListener[mUserRestrictionsListeners.size()];
1120 mUserRestrictionsListeners.toArray(listeners);
1121 }
1122 for (int i = 0; i < listeners.length; i++) {
1123 listeners[i].onUserRestrictionsChanged(userId,
1124 newRestrictionsFinal, prevRestrictionsFinal);
1125 }
1126 }
1127 });
1128 }
1129
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001130 // Package private for the inner class.
1131 void applyUserRestrictionsLR(int userId) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07001132 updateUserRestrictionsInternalLR(null, userId);
Makoto Onuki068c54a2015-10-13 14:34:03 -07001133 }
1134
1135 @GuardedBy("mRestrictionsLock")
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001136 // Package private for the inner class.
1137 void applyUserRestrictionsForAllUsersLR() {
1138 if (DBG) {
1139 debug("applyUserRestrictionsForAllUsersLR");
1140 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07001141 // First, invalidate all cached values.
Makoto Onuki4f160732015-10-27 17:15:38 -07001142 mCachedEffectiveUserRestrictions.clear();
1143
Makoto Onuki068c54a2015-10-13 14:34:03 -07001144 // We don't want to call into ActivityManagerNative while taking a lock, so we'll call
1145 // it on a handler.
1146 final Runnable r = new Runnable() {
1147 @Override
1148 public void run() {
1149 // Then get the list of running users.
1150 final int[] runningUsers;
1151 try {
1152 runningUsers = ActivityManagerNative.getDefault().getRunningUserIds();
1153 } catch (RemoteException e) {
1154 Log.w(LOG_TAG, "Unable to access ActivityManagerNative");
1155 return;
1156 }
1157 // Then re-calculate the effective restrictions and apply, only for running users.
1158 // It's okay if a new user has started after the getRunningUserIds() call,
1159 // because we'll do the same thing (re-calculate the restrictions and apply)
1160 // when we start a user.
Makoto Onuki068c54a2015-10-13 14:34:03 -07001161 synchronized (mRestrictionsLock) {
1162 for (int i = 0; i < runningUsers.length; i++) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001163 applyUserRestrictionsLR(runningUsers[i]);
Makoto Onuki068c54a2015-10-13 14:34:03 -07001164 }
1165 }
1166 }
1167 };
1168 mHandler.post(r);
Fyodor Kupolovb5013302015-04-17 17:59:14 -07001169 }
1170
Amith Yamasani258848d2012-08-10 17:06:33 -07001171 /**
Amith Yamasanifaea76f2012-09-11 10:59:48 -07001172 * Check if we've hit the limit of how many users can be created.
1173 */
Fyodor Kupolov82402752015-10-28 14:54:51 -07001174 private boolean isUserLimitReached() {
1175 int count;
1176 synchronized (mUsersLock) {
1177 count = getAliveUsersExcludingGuestsCountLU();
1178 }
1179 return count >= UserManager.getMaxSupportedUsers();
Nicolas Prevot12678a92015-05-13 12:15:03 -07001180 }
1181
1182 @Override
Nicolas Prevot07387fe2015-10-30 17:53:30 +00001183 public boolean canAddMoreManagedProfiles(int userId, boolean allowedToRemoveOne) {
Nicolas Prevot12678a92015-05-13 12:15:03 -07001184 checkManageUsersPermission("check if more managed profiles can be added.");
1185 if (ActivityManager.isLowRamDeviceStatic()) {
1186 return false;
1187 }
Fyodor Kupolovb6157992015-06-05 15:32:28 -07001188 if (!mContext.getPackageManager().hasSystemFeature(
1189 PackageManager.FEATURE_MANAGED_USERS)) {
1190 return false;
1191 }
Nicolas Prevotb8186812015-08-06 15:00:03 +01001192 // Limit number of managed profiles that can be created
Nicolas Prevot07387fe2015-10-30 17:53:30 +00001193 final int managedProfilesCount = getProfiles(userId, true).size() - 1;
1194 final int profilesRemovedCount = managedProfilesCount > 0 && allowedToRemoveOne ? 1 : 0;
1195 if (managedProfilesCount - profilesRemovedCount >= MAX_MANAGED_PROFILES) {
Nicolas Prevotb8186812015-08-06 15:00:03 +01001196 return false;
1197 }
Fyodor Kupolov82402752015-10-28 14:54:51 -07001198 synchronized(mUsersLock) {
1199 UserInfo userInfo = getUserInfoLU(userId);
Nicolas Prevotb8186812015-08-06 15:00:03 +01001200 if (!userInfo.canHaveProfile()) {
Nicolas Prevot12678a92015-05-13 12:15:03 -07001201 return false;
1202 }
Nicolas Prevot07387fe2015-10-30 17:53:30 +00001203 int usersCountAfterRemoving = getAliveUsersExcludingGuestsCountLU()
1204 - profilesRemovedCount;
Nicolas Prevot12678a92015-05-13 12:15:03 -07001205 // We allow creating a managed profile in the special case where there is only one user.
Nicolas Prevot07387fe2015-10-30 17:53:30 +00001206 return usersCountAfterRemoving == 1
1207 || usersCountAfterRemoving < UserManager.getMaxSupportedUsers();
Nicolas Prevot12678a92015-05-13 12:15:03 -07001208 }
1209 }
1210
Fyodor Kupolov82402752015-10-28 14:54:51 -07001211 private int getAliveUsersExcludingGuestsCountLU() {
Amith Yamasanif584f012014-05-19 17:57:25 -07001212 int aliveUserCount = 0;
1213 final int totalUserCount = mUsers.size();
1214 // Skip over users being removed
1215 for (int i = 0; i < totalUserCount; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -08001216 UserInfo user = mUsers.valueAt(i).info;
Amith Yamasani95ab7842014-08-11 17:09:26 -07001217 if (!mRemovingUserIds.get(user.id)
Amith Yamasani1df14732014-08-29 21:37:27 -07001218 && !user.isGuest() && !user.partial) {
Amith Yamasanif584f012014-05-19 17:57:25 -07001219 aliveUserCount++;
1220 }
1221 }
Nicolas Prevot12678a92015-05-13 12:15:03 -07001222 return aliveUserCount;
Amith Yamasanifaea76f2012-09-11 10:59:48 -07001223 }
1224
1225 /**
Amith Yamasani195263742012-08-21 15:40:12 -07001226 * Enforces that only the system UID or root's UID or apps that have the
Xiaohui Chenb3b92582015-12-07 11:22:13 -08001227 * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} and
1228 * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL INTERACT_ACROSS_USERS_FULL}
1229 * permissions can make certain calls to the UserManager.
1230 *
1231 * @param message used as message if SecurityException is thrown
1232 * @throws SecurityException if the caller does not have enough privilege.
1233 */
1234 private static final void checkManageUserAndAcrossUsersFullPermission(String message) {
1235 final int uid = Binder.getCallingUid();
1236 if (uid != Process.SYSTEM_UID && uid != 0
1237 && ActivityManager.checkComponentPermission(
1238 Manifest.permission.MANAGE_USERS,
1239 uid, -1, true) != PackageManager.PERMISSION_GRANTED
1240 && ActivityManager.checkComponentPermission(
1241 Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1242 uid, -1, true) != PackageManager.PERMISSION_GRANTED) {
1243 throw new SecurityException(
1244 "You need MANAGE_USERS and INTERACT_ACROSS_USERS_FULL permission to: "
1245 + message);
1246 }
1247 }
1248
1249 /**
1250 * Enforces that only the system UID or root's UID or apps that have the
Dianne Hackborn10ad9822014-03-17 11:28:36 -07001251 * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS}
Amith Yamasani195263742012-08-21 15:40:12 -07001252 * permission can make certain calls to the UserManager.
Amith Yamasani258848d2012-08-10 17:06:33 -07001253 *
1254 * @param message used as message if SecurityException is thrown
1255 * @throws SecurityException if the caller is not system or root
Tony Mak4dc008c2016-03-16 10:46:49 +00001256 * @see #hasManageUsersPermission()
Amith Yamasani258848d2012-08-10 17:06:33 -07001257 */
Amith Yamasanibe465322014-04-24 13:45:17 -07001258 private static final void checkManageUsersPermission(String message) {
Tony Mak4dc008c2016-03-16 10:46:49 +00001259 if (!hasManageUsersPermission()) {
Amith Yamasanibe465322014-04-24 13:45:17 -07001260 throw new SecurityException("You need MANAGE_USERS permission to: " + message);
1261 }
Emily Bernier7a2b4d12014-04-23 12:51:35 -04001262 }
1263
Esteban Talavera5b9f1672015-12-11 15:22:34 +00001264 /**
Tony Mak4dc008c2016-03-16 10:46:49 +00001265 * @return whether the calling UID is system UID or root's UID or the calling app has the
1266 * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS}.
1267 */
1268 private static final boolean hasManageUsersPermission() {
1269 final int callingUid = Binder.getCallingUid();
1270 return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
1271 || callingUid == Process.ROOT_UID
1272 || ActivityManager.checkComponentPermission(
1273 android.Manifest.permission.MANAGE_USERS,
1274 callingUid, -1, true) == PackageManager.PERMISSION_GRANTED;
1275 }
1276
1277 /**
Esteban Talavera5b9f1672015-12-11 15:22:34 +00001278 * Enforces that only the system UID or root's UID (on any user) can make certain calls to the
1279 * UserManager.
1280 *
1281 * @param message used as message if SecurityException is thrown
1282 * @throws SecurityException if the caller is not system or root
1283 */
1284 private static void checkSystemOrRoot(String message) {
1285 final int uid = Binder.getCallingUid();
1286 if (!UserHandle.isSameApp(uid, Process.SYSTEM_UID) && uid != Process.ROOT_UID) {
1287 throw new SecurityException("Only system may: " + message);
1288 }
1289 }
1290
Fyodor Kupolov82402752015-10-28 14:54:51 -07001291 private void writeBitmapLP(UserInfo info, Bitmap bitmap) {
Amith Yamasanib8151ec2012-04-18 18:02:48 -07001292 try {
1293 File dir = new File(mUsersDir, Integer.toString(info.id));
1294 File file = new File(dir, USER_PHOTO_FILENAME);
Adrian Roos1bdff912015-02-17 15:51:35 +01001295 File tmp = new File(dir, USER_PHOTO_FILENAME_TMP);
Amith Yamasanib8151ec2012-04-18 18:02:48 -07001296 if (!dir.exists()) {
1297 dir.mkdir();
1298 FileUtils.setPermissions(
1299 dir.getPath(),
1300 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
1301 -1, -1);
1302 }
Amith Yamasanie928d7d2012-09-17 21:46:51 -07001303 FileOutputStream os;
Adrian Roos1bdff912015-02-17 15:51:35 +01001304 if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, os = new FileOutputStream(tmp))
Oleksandr Peletskyicd6fa302016-02-25 16:28:39 +01001305 && tmp.renameTo(file) && SELinux.restorecon(file)) {
Amith Yamasani3b49f072012-09-17 10:21:43 -07001306 info.iconPath = file.getAbsolutePath();
1307 }
Amith Yamasanie928d7d2012-09-17 21:46:51 -07001308 try {
1309 os.close();
1310 } catch (IOException ioe) {
1311 // What the ... !
1312 }
Adrian Roos1bdff912015-02-17 15:51:35 +01001313 tmp.delete();
Amith Yamasanib8151ec2012-04-18 18:02:48 -07001314 } catch (FileNotFoundException e) {
Amith Yamasani2a003292012-08-14 18:25:45 -07001315 Slog.w(LOG_TAG, "Error setting photo for user ", e);
Amith Yamasanib8151ec2012-04-18 18:02:48 -07001316 }
Amith Yamasanib8151ec2012-04-18 18:02:48 -07001317 }
1318
Amith Yamasani0b285492011-04-14 17:35:23 -07001319 /**
1320 * Returns an array of user ids. This array is cached here for quick access, so do not modify or
1321 * cache it elsewhere.
1322 * @return the array of user ids.
1323 */
Dianne Hackborn1676c852012-09-10 14:52:30 -07001324 public int[] getUserIds() {
Fyodor Kupolov82402752015-10-28 14:54:51 -07001325 synchronized (mUsersLock) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001326 return mUserIds;
1327 }
Amith Yamasani0b285492011-04-14 17:35:23 -07001328 }
1329
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001330 private void readUserListLP() {
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001331 if (!mUserListFile.exists()) {
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001332 fallbackToSingleUserLP();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001333 return;
1334 }
1335 FileInputStream fis = null;
Amith Yamasani2a003292012-08-14 18:25:45 -07001336 AtomicFile userListFile = new AtomicFile(mUserListFile);
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001337 try {
Amith Yamasani2a003292012-08-14 18:25:45 -07001338 fis = userListFile.openRead();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001339 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001340 parser.setInput(fis, StandardCharsets.UTF_8.name());
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001341 int type;
1342 while ((type = parser.next()) != XmlPullParser.START_TAG
1343 && type != XmlPullParser.END_DOCUMENT) {
Amith Yamasani12747872015-12-07 14:19:49 -08001344 // Skip
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001345 }
1346
1347 if (type != XmlPullParser.START_TAG) {
Amith Yamasani0b285492011-04-14 17:35:23 -07001348 Slog.e(LOG_TAG, "Unable to read user list");
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001349 fallbackToSingleUserLP();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001350 return;
1351 }
1352
Amith Yamasani2a003292012-08-14 18:25:45 -07001353 mNextSerialNumber = -1;
1354 if (parser.getName().equals(TAG_USERS)) {
1355 String lastSerialNumber = parser.getAttributeValue(null, ATTR_NEXT_SERIAL_NO);
1356 if (lastSerialNumber != null) {
1357 mNextSerialNumber = Integer.parseInt(lastSerialNumber);
1358 }
Amith Yamasani6f34b412012-10-22 18:19:27 -07001359 String versionNumber = parser.getAttributeValue(null, ATTR_USER_VERSION);
1360 if (versionNumber != null) {
1361 mUserVersion = Integer.parseInt(versionNumber);
1362 }
Amith Yamasani2a003292012-08-14 18:25:45 -07001363 }
1364
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001365 final Bundle newDevicePolicyGlobalUserRestrictions = new Bundle();
1366
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001367 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
Amith Yamasanie4afaa32014-06-30 14:55:07 +05301368 if (type == XmlPullParser.START_TAG) {
1369 final String name = parser.getName();
1370 if (name.equals(TAG_USER)) {
1371 String id = parser.getAttributeValue(null, ATTR_ID);
Amith Yamasani6f34b412012-10-22 18:19:27 -07001372
Amith Yamasani12747872015-12-07 14:19:49 -08001373 UserData userData = readUserLP(Integer.parseInt(id));
1374
1375 if (userData != null) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07001376 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08001377 mUsers.put(userData.info.id, userData);
1378 if (mNextSerialNumber < 0
1379 || mNextSerialNumber <= userData.info.id) {
1380 mNextSerialNumber = userData.info.id + 1;
Fyodor Kupolov82402752015-10-28 14:54:51 -07001381 }
Amith Yamasanie4afaa32014-06-30 14:55:07 +05301382 }
Amith Yamasani2a003292012-08-14 18:25:45 -07001383 }
Amith Yamasanie4afaa32014-06-30 14:55:07 +05301384 } else if (name.equals(TAG_GUEST_RESTRICTIONS)) {
Amith Yamasanida0b1682014-11-21 12:58:17 -08001385 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1386 && type != XmlPullParser.END_TAG) {
1387 if (type == XmlPullParser.START_TAG) {
1388 if (parser.getName().equals(TAG_RESTRICTIONS)) {
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001389 synchronized (mGuestRestrictions) {
1390 UserRestrictionsUtils
1391 .readRestrictions(parser, mGuestRestrictions);
1392 }
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001393 } else if (parser.getName().equals(TAG_DEVICE_POLICY_RESTRICTIONS)
1394 ) {
1395 UserRestrictionsUtils.readRestrictions(parser,
1396 newDevicePolicyGlobalUserRestrictions);
Amith Yamasanida0b1682014-11-21 12:58:17 -08001397 }
1398 break;
1399 }
1400 }
Amith Yamasani258848d2012-08-10 17:06:33 -07001401 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001402 }
1403 }
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001404 synchronized (mRestrictionsLock) {
1405 mDevicePolicyGlobalUserRestrictions = newDevicePolicyGlobalUserRestrictions;
1406 }
Fyodor Kupolov82402752015-10-28 14:54:51 -07001407 updateUserIds();
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001408 upgradeIfNecessaryLP();
1409 } catch (IOException | XmlPullParserException e) {
1410 fallbackToSingleUserLP();
Dianne Hackbornbfd89b32011-12-15 18:22:54 -08001411 } finally {
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001412 IoUtils.closeQuietly(fis);
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001413 }
1414 }
1415
Amith Yamasani6f34b412012-10-22 18:19:27 -07001416 /**
Amith Yamasanibc9625052012-11-15 14:39:18 -08001417 * Upgrade steps between versions, either for fixing bugs or changing the data format.
Amith Yamasani6f34b412012-10-22 18:19:27 -07001418 */
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001419 private void upgradeIfNecessaryLP() {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001420 final int originalVersion = mUserVersion;
Amith Yamasani6f34b412012-10-22 18:19:27 -07001421 int userVersion = mUserVersion;
1422 if (userVersion < 1) {
1423 // Assign a proper name for the owner, if not initialized correctly before
Amith Yamasani12747872015-12-07 14:19:49 -08001424 UserData userData = getUserDataNoChecks(UserHandle.USER_SYSTEM);
1425 if ("Primary".equals(userData.info.name)) {
1426 userData.info.name =
1427 mContext.getResources().getString(com.android.internal.R.string.owner_name);
1428 scheduleWriteUser(userData);
Amith Yamasani6f34b412012-10-22 18:19:27 -07001429 }
1430 userVersion = 1;
1431 }
1432
Amith Yamasanibc9625052012-11-15 14:39:18 -08001433 if (userVersion < 2) {
1434 // Owner should be marked as initialized
Amith Yamasani12747872015-12-07 14:19:49 -08001435 UserData userData = getUserDataNoChecks(UserHandle.USER_SYSTEM);
1436 if ((userData.info.flags & UserInfo.FLAG_INITIALIZED) == 0) {
1437 userData.info.flags |= UserInfo.FLAG_INITIALIZED;
1438 scheduleWriteUser(userData);
Amith Yamasanibc9625052012-11-15 14:39:18 -08001439 }
1440 userVersion = 2;
1441 }
1442
Amith Yamasani350962c2013-08-06 11:18:53 -07001443
Amith Yamasani5e486f52013-08-07 11:06:44 -07001444 if (userVersion < 4) {
Amith Yamasani5e486f52013-08-07 11:06:44 -07001445 userVersion = 4;
1446 }
1447
Amith Yamasaniaa6634e2014-10-06 14:20:28 -07001448 if (userVersion < 5) {
1449 initDefaultGuestRestrictions();
1450 userVersion = 5;
1451 }
1452
Fyodor Kupolov1c363152015-09-02 13:27:21 -07001453 if (userVersion < 6) {
1454 final boolean splitSystemUser = UserManager.isSplitSystemUser();
Fyodor Kupolov82402752015-10-28 14:54:51 -07001455 synchronized (mUsersLock) {
1456 for (int i = 0; i < mUsers.size(); i++) {
Amith Yamasani12747872015-12-07 14:19:49 -08001457 UserData userData = mUsers.valueAt(i);
Fyodor Kupolov82402752015-10-28 14:54:51 -07001458 // In non-split mode, only user 0 can have restricted profiles
Amith Yamasani12747872015-12-07 14:19:49 -08001459 if (!splitSystemUser && userData.info.isRestricted()
1460 && (userData.info.restrictedProfileParentId
1461 == UserInfo.NO_PROFILE_GROUP_ID)) {
1462 userData.info.restrictedProfileParentId = UserHandle.USER_SYSTEM;
1463 scheduleWriteUser(userData);
Fyodor Kupolov82402752015-10-28 14:54:51 -07001464 }
Fyodor Kupolov1c363152015-09-02 13:27:21 -07001465 }
1466 }
1467 userVersion = 6;
1468 }
1469
Amith Yamasani6f34b412012-10-22 18:19:27 -07001470 if (userVersion < USER_VERSION) {
1471 Slog.w(LOG_TAG, "User version " + mUserVersion + " didn't upgrade as expected to "
1472 + USER_VERSION);
1473 } else {
1474 mUserVersion = userVersion;
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001475
1476 if (originalVersion < mUserVersion) {
1477 writeUserListLP();
1478 }
Amith Yamasani6f34b412012-10-22 18:19:27 -07001479 }
1480 }
1481
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001482 private void fallbackToSingleUserLP() {
Xiaohui Chenb31e14a2015-07-13 16:04:55 -07001483 int flags = UserInfo.FLAG_INITIALIZED;
1484 // In split system user mode, the admin and primary flags are assigned to the first human
1485 // user.
1486 if (!UserManager.isSplitSystemUser()) {
1487 flags |= UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY;
1488 }
Xiaohui Chen70f6c382015-04-28 14:21:43 -07001489 // Create the system user
Amith Yamasani6f48d6e2016-03-23 14:28:25 -07001490 UserInfo system = new UserInfo(UserHandle.USER_SYSTEM, null, null, flags);
Amith Yamasani12747872015-12-07 14:19:49 -08001491 UserData userData = new UserData();
1492 userData.info = system;
Fyodor Kupolov82402752015-10-28 14:54:51 -07001493 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08001494 mUsers.put(system.id, userData);
Fyodor Kupolov82402752015-10-28 14:54:51 -07001495 }
Amith Yamasani634cf312012-10-04 17:34:21 -07001496 mNextSerialNumber = MIN_USER_ID;
Geoffrey Borggaard15b8b2c2013-08-28 22:11:10 -04001497 mUserVersion = USER_VERSION;
Amith Yamasani67df64b2012-12-14 12:09:36 -08001498
Geoffrey Borggaarde45e45e32013-01-24 10:03:20 -05001499 Bundle restrictions = new Bundle();
Makoto Onuki068c54a2015-10-13 14:34:03 -07001500 synchronized (mRestrictionsLock) {
1501 mBaseUserRestrictions.append(UserHandle.USER_SYSTEM, restrictions);
1502 }
Amith Yamasani67df64b2012-12-14 12:09:36 -08001503
Fyodor Kupolov82402752015-10-28 14:54:51 -07001504 updateUserIds();
Amith Yamasaniaa6634e2014-10-06 14:20:28 -07001505 initDefaultGuestRestrictions();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001506
Amith Yamasani12747872015-12-07 14:19:49 -08001507 writeUserLP(userData);
Jeff Sharkeycd575992016-03-29 14:12:49 -06001508 writeUserListLP();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001509 }
1510
Amith Yamasani6f48d6e2016-03-23 14:28:25 -07001511 private String getOwnerName() {
1512 return mContext.getResources().getString(com.android.internal.R.string.owner_name);
1513 }
1514
Amith Yamasani12747872015-12-07 14:19:49 -08001515 private void scheduleWriteUser(UserData UserData) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001516 if (DBG) {
1517 debug("scheduleWriteUser");
1518 }
Makoto Onuki9e935a32015-11-06 14:24:24 -08001519 // No need to wrap it within a lock -- worst case, we'll just post the same message
1520 // twice.
Amith Yamasani12747872015-12-07 14:19:49 -08001521 if (!mHandler.hasMessages(WRITE_USER_MSG, UserData)) {
1522 Message msg = mHandler.obtainMessage(WRITE_USER_MSG, UserData);
Fyodor Kupolov75d0ea82014-12-15 16:21:07 -08001523 mHandler.sendMessageDelayed(msg, WRITE_USER_DELAY);
1524 }
1525 }
1526
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001527 /*
1528 * Writes the user file in this format:
1529 *
1530 * <user flags="20039023" id="0">
1531 * <name>Primary</name>
1532 * </user>
1533 */
Amith Yamasani12747872015-12-07 14:19:49 -08001534 private void writeUserLP(UserData userData) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001535 if (DBG) {
Amith Yamasani12747872015-12-07 14:19:49 -08001536 debug("writeUserLP " + userData);
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001537 }
Amith Yamasani742a6712011-05-04 14:49:28 -07001538 FileOutputStream fos = null;
Amith Yamasani12747872015-12-07 14:19:49 -08001539 AtomicFile userFile = new AtomicFile(new File(mUsersDir, userData.info.id + XML_SUFFIX));
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001540 try {
Amith Yamasani2a003292012-08-14 18:25:45 -07001541 fos = userFile.startWrite();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001542 final BufferedOutputStream bos = new BufferedOutputStream(fos);
1543
1544 // XmlSerializer serializer = XmlUtils.serializerInstance();
1545 final XmlSerializer serializer = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001546 serializer.setOutput(bos, StandardCharsets.UTF_8.name());
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001547 serializer.startDocument(null, true);
1548 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
1549
Amith Yamasani12747872015-12-07 14:19:49 -08001550 final UserInfo userInfo = userData.info;
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001551 serializer.startTag(null, TAG_USER);
1552 serializer.attribute(null, ATTR_ID, Integer.toString(userInfo.id));
Amith Yamasani2a003292012-08-14 18:25:45 -07001553 serializer.attribute(null, ATTR_SERIAL_NO, Integer.toString(userInfo.serialNumber));
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001554 serializer.attribute(null, ATTR_FLAGS, Integer.toString(userInfo.flags));
Amith Yamasani920ace02012-09-20 22:15:37 -07001555 serializer.attribute(null, ATTR_CREATION_TIME, Long.toString(userInfo.creationTime));
1556 serializer.attribute(null, ATTR_LAST_LOGGED_IN_TIME,
1557 Long.toString(userInfo.lastLoggedInTime));
Jeff Sharkeycd575992016-03-29 14:12:49 -06001558 if (userInfo.lastLoggedInFingerprint != null) {
1559 serializer.attribute(null, ATTR_LAST_LOGGED_IN_FINGERPRINT,
1560 userInfo.lastLoggedInFingerprint);
1561 }
Amith Yamasanib8151ec2012-04-18 18:02:48 -07001562 if (userInfo.iconPath != null) {
1563 serializer.attribute(null, ATTR_ICON_PATH, userInfo.iconPath);
1564 }
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07001565 if (userInfo.partial) {
1566 serializer.attribute(null, ATTR_PARTIAL, "true");
1567 }
Adam Lesinskieddeb492014-09-08 17:50:03 -07001568 if (userInfo.guestToRemove) {
1569 serializer.attribute(null, ATTR_GUEST_TO_REMOVE, "true");
1570 }
Kenny Guy2a764942014-04-02 13:29:20 +01001571 if (userInfo.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID) {
1572 serializer.attribute(null, ATTR_PROFILE_GROUP_ID,
1573 Integer.toString(userInfo.profileGroupId));
Kenny Guya52dc3e2014-02-11 15:33:14 +00001574 }
Fyodor Kupolov06a484a2015-08-21 16:33:20 -07001575 if (userInfo.restrictedProfileParentId != UserInfo.NO_PROFILE_GROUP_ID) {
1576 serializer.attribute(null, ATTR_RESTRICTED_PROFILE_PARENT_ID,
1577 Integer.toString(userInfo.restrictedProfileParentId));
1578 }
Amith Yamasani12747872015-12-07 14:19:49 -08001579 // Write seed data
1580 if (userData.persistSeedData) {
1581 if (userData.seedAccountName != null) {
1582 serializer.attribute(null, ATTR_SEED_ACCOUNT_NAME, userData.seedAccountName);
1583 }
1584 if (userData.seedAccountType != null) {
1585 serializer.attribute(null, ATTR_SEED_ACCOUNT_TYPE, userData.seedAccountType);
1586 }
1587 }
Amith Yamasani6f48d6e2016-03-23 14:28:25 -07001588 if (userInfo.name != null) {
1589 serializer.startTag(null, TAG_NAME);
1590 serializer.text(userInfo.name);
1591 serializer.endTag(null, TAG_NAME);
1592 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07001593 synchronized (mRestrictionsLock) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001594 UserRestrictionsUtils.writeRestrictions(serializer,
1595 mBaseUserRestrictions.get(userInfo.id), TAG_RESTRICTIONS);
1596 UserRestrictionsUtils.writeRestrictions(serializer,
1597 mDevicePolicyLocalUserRestrictions.get(userInfo.id),
1598 TAG_DEVICE_POLICY_RESTRICTIONS);
Amith Yamasanie4cf7342012-12-17 11:12:09 -08001599 }
Amith Yamasani12747872015-12-07 14:19:49 -08001600
1601 if (userData.account != null) {
Xiaohui Chenb3b92582015-12-07 11:22:13 -08001602 serializer.startTag(null, TAG_ACCOUNT);
Amith Yamasani12747872015-12-07 14:19:49 -08001603 serializer.text(userData.account);
Xiaohui Chenb3b92582015-12-07 11:22:13 -08001604 serializer.endTag(null, TAG_ACCOUNT);
1605 }
1606
Amith Yamasani12747872015-12-07 14:19:49 -08001607 if (userData.persistSeedData && userData.seedAccountOptions != null) {
1608 serializer.startTag(null, TAG_SEED_ACCOUNT_OPTIONS);
1609 userData.seedAccountOptions.saveToXml(serializer);
1610 serializer.endTag(null, TAG_SEED_ACCOUNT_OPTIONS);
1611 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001612 serializer.endTag(null, TAG_USER);
1613
1614 serializer.endDocument();
Amith Yamasani2a003292012-08-14 18:25:45 -07001615 userFile.finishWrite(fos);
1616 } catch (Exception ioe) {
Jeff Sharkeycd575992016-03-29 14:12:49 -06001617 Slog.e(LOG_TAG, "Error writing user info " + userData.info.id, ioe);
Amith Yamasani2a003292012-08-14 18:25:45 -07001618 userFile.failWrite(fos);
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001619 }
1620 }
1621
1622 /*
1623 * Writes the user list file in this format:
1624 *
Amith Yamasani2a003292012-08-14 18:25:45 -07001625 * <users nextSerialNumber="3">
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001626 * <user id="0"></user>
1627 * <user id="2"></user>
1628 * </users>
1629 */
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001630 private void writeUserListLP() {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001631 if (DBG) {
1632 debug("writeUserList");
1633 }
Amith Yamasani742a6712011-05-04 14:49:28 -07001634 FileOutputStream fos = null;
Amith Yamasani2a003292012-08-14 18:25:45 -07001635 AtomicFile userListFile = new AtomicFile(mUserListFile);
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001636 try {
Amith Yamasani2a003292012-08-14 18:25:45 -07001637 fos = userListFile.startWrite();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001638 final BufferedOutputStream bos = new BufferedOutputStream(fos);
1639
1640 // XmlSerializer serializer = XmlUtils.serializerInstance();
1641 final XmlSerializer serializer = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001642 serializer.setOutput(bos, StandardCharsets.UTF_8.name());
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001643 serializer.startDocument(null, true);
1644 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
1645
1646 serializer.startTag(null, TAG_USERS);
Amith Yamasani2a003292012-08-14 18:25:45 -07001647 serializer.attribute(null, ATTR_NEXT_SERIAL_NO, Integer.toString(mNextSerialNumber));
Amith Yamasani6f34b412012-10-22 18:19:27 -07001648 serializer.attribute(null, ATTR_USER_VERSION, Integer.toString(mUserVersion));
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001649
Adam Lesinskieddeb492014-09-08 17:50:03 -07001650 serializer.startTag(null, TAG_GUEST_RESTRICTIONS);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001651 synchronized (mGuestRestrictions) {
1652 UserRestrictionsUtils
1653 .writeRestrictions(serializer, mGuestRestrictions, TAG_RESTRICTIONS);
1654 }
Amith Yamasanie4afaa32014-06-30 14:55:07 +05301655 serializer.endTag(null, TAG_GUEST_RESTRICTIONS);
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001656 synchronized (mRestrictionsLock) {
1657 UserRestrictionsUtils.writeRestrictions(serializer,
1658 mDevicePolicyGlobalUserRestrictions, TAG_DEVICE_POLICY_RESTRICTIONS);
1659 }
Fyodor Kupolov82402752015-10-28 14:54:51 -07001660 int[] userIdsToWrite;
1661 synchronized (mUsersLock) {
1662 userIdsToWrite = new int[mUsers.size()];
1663 for (int i = 0; i < userIdsToWrite.length; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -08001664 UserInfo user = mUsers.valueAt(i).info;
Fyodor Kupolov82402752015-10-28 14:54:51 -07001665 userIdsToWrite[i] = user.id;
1666 }
1667 }
1668 for (int id : userIdsToWrite) {
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001669 serializer.startTag(null, TAG_USER);
Fyodor Kupolov82402752015-10-28 14:54:51 -07001670 serializer.attribute(null, ATTR_ID, Integer.toString(id));
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001671 serializer.endTag(null, TAG_USER);
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001672 }
1673
1674 serializer.endTag(null, TAG_USERS);
1675
1676 serializer.endDocument();
Amith Yamasani2a003292012-08-14 18:25:45 -07001677 userListFile.finishWrite(fos);
1678 } catch (Exception e) {
1679 userListFile.failWrite(fos);
Amith Yamasani0b285492011-04-14 17:35:23 -07001680 Slog.e(LOG_TAG, "Error writing user list");
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001681 }
1682 }
1683
Amith Yamasani12747872015-12-07 14:19:49 -08001684 private UserData readUserLP(int id) {
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001685 int flags = 0;
Amith Yamasani2a003292012-08-14 18:25:45 -07001686 int serialNumber = id;
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001687 String name = null;
Xiaohui Chenb3b92582015-12-07 11:22:13 -08001688 String account = null;
Amith Yamasanib8151ec2012-04-18 18:02:48 -07001689 String iconPath = null;
Amith Yamasani920ace02012-09-20 22:15:37 -07001690 long creationTime = 0L;
1691 long lastLoggedInTime = 0L;
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06001692 String lastLoggedInFingerprint = null;
Kenny Guy2a764942014-04-02 13:29:20 +01001693 int profileGroupId = UserInfo.NO_PROFILE_GROUP_ID;
Fyodor Kupolov06a484a2015-08-21 16:33:20 -07001694 int restrictedProfileParentId = UserInfo.NO_PROFILE_GROUP_ID;
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07001695 boolean partial = false;
Adam Lesinskieddeb492014-09-08 17:50:03 -07001696 boolean guestToRemove = false;
Amith Yamasani12747872015-12-07 14:19:49 -08001697 boolean persistSeedData = false;
1698 String seedAccountName = null;
1699 String seedAccountType = null;
1700 PersistableBundle seedAccountOptions = null;
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001701 Bundle baseRestrictions = new Bundle();
1702 Bundle localRestrictions = new Bundle();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001703
1704 FileInputStream fis = null;
1705 try {
Amith Yamasani2a003292012-08-14 18:25:45 -07001706 AtomicFile userFile =
Amith Yamasanifc95e702013-09-26 13:20:17 -07001707 new AtomicFile(new File(mUsersDir, Integer.toString(id) + XML_SUFFIX));
Amith Yamasani2a003292012-08-14 18:25:45 -07001708 fis = userFile.openRead();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001709 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001710 parser.setInput(fis, StandardCharsets.UTF_8.name());
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001711 int type;
1712 while ((type = parser.next()) != XmlPullParser.START_TAG
1713 && type != XmlPullParser.END_DOCUMENT) {
Amith Yamasani12747872015-12-07 14:19:49 -08001714 // Skip
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001715 }
1716
1717 if (type != XmlPullParser.START_TAG) {
Amith Yamasani0b285492011-04-14 17:35:23 -07001718 Slog.e(LOG_TAG, "Unable to read user " + id);
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001719 return null;
1720 }
1721
1722 if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_USER)) {
Amith Yamasani920ace02012-09-20 22:15:37 -07001723 int storedId = readIntAttribute(parser, ATTR_ID, -1);
1724 if (storedId != id) {
Amith Yamasani0b285492011-04-14 17:35:23 -07001725 Slog.e(LOG_TAG, "User id does not match the file name");
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001726 return null;
1727 }
Amith Yamasani920ace02012-09-20 22:15:37 -07001728 serialNumber = readIntAttribute(parser, ATTR_SERIAL_NO, id);
1729 flags = readIntAttribute(parser, ATTR_FLAGS, 0);
Amith Yamasanib8151ec2012-04-18 18:02:48 -07001730 iconPath = parser.getAttributeValue(null, ATTR_ICON_PATH);
Amith Yamasani920ace02012-09-20 22:15:37 -07001731 creationTime = readLongAttribute(parser, ATTR_CREATION_TIME, 0);
1732 lastLoggedInTime = readLongAttribute(parser, ATTR_LAST_LOGGED_IN_TIME, 0);
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06001733 lastLoggedInFingerprint = parser.getAttributeValue(null,
1734 ATTR_LAST_LOGGED_IN_FINGERPRINT);
Kenny Guy2a764942014-04-02 13:29:20 +01001735 profileGroupId = readIntAttribute(parser, ATTR_PROFILE_GROUP_ID,
1736 UserInfo.NO_PROFILE_GROUP_ID);
Fyodor Kupolov06a484a2015-08-21 16:33:20 -07001737 restrictedProfileParentId = readIntAttribute(parser,
1738 ATTR_RESTRICTED_PROFILE_PARENT_ID, UserInfo.NO_PROFILE_GROUP_ID);
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07001739 String valueString = parser.getAttributeValue(null, ATTR_PARTIAL);
1740 if ("true".equals(valueString)) {
1741 partial = true;
1742 }
Adam Lesinskieddeb492014-09-08 17:50:03 -07001743 valueString = parser.getAttributeValue(null, ATTR_GUEST_TO_REMOVE);
1744 if ("true".equals(valueString)) {
1745 guestToRemove = true;
1746 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001747
Amith Yamasani12747872015-12-07 14:19:49 -08001748 seedAccountName = parser.getAttributeValue(null, ATTR_SEED_ACCOUNT_NAME);
1749 seedAccountType = parser.getAttributeValue(null, ATTR_SEED_ACCOUNT_TYPE);
1750 if (seedAccountName != null || seedAccountType != null) {
1751 persistSeedData = true;
1752 }
1753
Amith Yamasanie4cf7342012-12-17 11:12:09 -08001754 int outerDepth = parser.getDepth();
1755 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1756 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1757 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1758 continue;
1759 }
1760 String tag = parser.getName();
1761 if (TAG_NAME.equals(tag)) {
1762 type = parser.next();
1763 if (type == XmlPullParser.TEXT) {
1764 name = parser.getText();
1765 }
1766 } else if (TAG_RESTRICTIONS.equals(tag)) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001767 UserRestrictionsUtils.readRestrictions(parser, baseRestrictions);
1768 } else if (TAG_DEVICE_POLICY_RESTRICTIONS.equals(tag)) {
1769 UserRestrictionsUtils.readRestrictions(parser, localRestrictions);
Xiaohui Chenb3b92582015-12-07 11:22:13 -08001770 } else if (TAG_ACCOUNT.equals(tag)) {
1771 type = parser.next();
1772 if (type == XmlPullParser.TEXT) {
1773 account = parser.getText();
1774 }
Amith Yamasani12747872015-12-07 14:19:49 -08001775 } else if (TAG_SEED_ACCOUNT_OPTIONS.equals(tag)) {
1776 seedAccountOptions = PersistableBundle.restoreFromXml(parser);
1777 persistSeedData = true;
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001778 }
1779 }
1780 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001781
Amith Yamasani12747872015-12-07 14:19:49 -08001782 // Create the UserInfo object that gets passed around
Amith Yamasanib8151ec2012-04-18 18:02:48 -07001783 UserInfo userInfo = new UserInfo(id, name, iconPath, flags);
Amith Yamasani2a003292012-08-14 18:25:45 -07001784 userInfo.serialNumber = serialNumber;
Amith Yamasani920ace02012-09-20 22:15:37 -07001785 userInfo.creationTime = creationTime;
1786 userInfo.lastLoggedInTime = lastLoggedInTime;
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06001787 userInfo.lastLoggedInFingerprint = lastLoggedInFingerprint;
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07001788 userInfo.partial = partial;
Adam Lesinskieddeb492014-09-08 17:50:03 -07001789 userInfo.guestToRemove = guestToRemove;
Kenny Guy2a764942014-04-02 13:29:20 +01001790 userInfo.profileGroupId = profileGroupId;
Fyodor Kupolov06a484a2015-08-21 16:33:20 -07001791 userInfo.restrictedProfileParentId = restrictedProfileParentId;
Amith Yamasani12747872015-12-07 14:19:49 -08001792
1793 // Create the UserData object that's internal to this class
1794 UserData userData = new UserData();
1795 userData.info = userInfo;
1796 userData.account = account;
1797 userData.seedAccountName = seedAccountName;
1798 userData.seedAccountType = seedAccountType;
1799 userData.persistSeedData = persistSeedData;
1800 userData.seedAccountOptions = seedAccountOptions;
1801
Makoto Onuki068c54a2015-10-13 14:34:03 -07001802 synchronized (mRestrictionsLock) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001803 mBaseUserRestrictions.put(id, baseRestrictions);
1804 mDevicePolicyLocalUserRestrictions.put(id, localRestrictions);
Makoto Onuki068c54a2015-10-13 14:34:03 -07001805 }
Amith Yamasani12747872015-12-07 14:19:49 -08001806 return userData;
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001807 } catch (IOException ioe) {
1808 } catch (XmlPullParserException pe) {
Dianne Hackbornbfd89b32011-12-15 18:22:54 -08001809 } finally {
1810 if (fis != null) {
1811 try {
1812 fis.close();
1813 } catch (IOException e) {
1814 }
1815 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001816 }
1817 return null;
1818 }
1819
Amith Yamasani920ace02012-09-20 22:15:37 -07001820 private int readIntAttribute(XmlPullParser parser, String attr, int defaultValue) {
1821 String valueString = parser.getAttributeValue(null, attr);
1822 if (valueString == null) return defaultValue;
1823 try {
1824 return Integer.parseInt(valueString);
1825 } catch (NumberFormatException nfe) {
1826 return defaultValue;
1827 }
1828 }
1829
1830 private long readLongAttribute(XmlPullParser parser, String attr, long defaultValue) {
1831 String valueString = parser.getAttributeValue(null, attr);
1832 if (valueString == null) return defaultValue;
1833 try {
1834 return Long.parseLong(valueString);
1835 } catch (NumberFormatException nfe) {
1836 return defaultValue;
1837 }
1838 }
1839
Amith Yamasanib82add22013-07-09 11:24:44 -07001840 /**
Amith Yamasani1a7472e2013-07-02 11:17:30 -07001841 * Removes the app restrictions file for a specific package and user id, if it exists.
1842 */
1843 private void cleanAppRestrictionsForPackage(String pkg, int userId) {
1844 synchronized (mPackagesLock) {
1845 File dir = Environment.getUserSystemDirectory(userId);
Amith Yamasanifc95e702013-09-26 13:20:17 -07001846 File resFile = new File(dir, packageToRestrictionsFileName(pkg));
Amith Yamasani1a7472e2013-07-02 11:17:30 -07001847 if (resFile.exists()) {
1848 resFile.delete();
1849 }
1850 }
1851 }
1852
Kenny Guya52dc3e2014-02-11 15:33:14 +00001853 @Override
Kenny Guy2a764942014-04-02 13:29:20 +01001854 public UserInfo createProfileForUser(String name, int flags, int userId) {
Kenny Guya52dc3e2014-02-11 15:33:14 +00001855 checkManageUsersPermission("Only the system can create users");
Kenny Guy2a764942014-04-02 13:29:20 +01001856 return createUserInternal(name, flags, userId);
Kenny Guya52dc3e2014-02-11 15:33:14 +00001857 }
1858
Amith Yamasani258848d2012-08-10 17:06:33 -07001859 @Override
Amith Yamasani13593602012-03-22 16:16:17 -07001860 public UserInfo createUser(String name, int flags) {
Amith Yamasani2a003292012-08-14 18:25:45 -07001861 checkManageUsersPermission("Only the system can create users");
Nicolas Prevotc6d033e2014-02-27 13:11:09 +00001862 return createUserInternal(name, flags, UserHandle.USER_NULL);
Kenny Guya52dc3e2014-02-11 15:33:14 +00001863 }
Amith Yamasanifaea76f2012-09-11 10:59:48 -07001864
Jessica Hummelbe81c802014-04-22 15:49:22 +01001865 private UserInfo createUserInternal(String name, int flags, int parentId) {
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001866 if (hasUserRestriction(UserManager.DISALLOW_ADD_USER, UserHandle.getCallingUserId())) {
Julia Reynolds75175022014-06-26 16:35:00 -04001867 Log.w(LOG_TAG, "Cannot add user. DISALLOW_ADD_USER is enabled.");
1868 return null;
1869 }
phweisse9c44062016-02-10 12:57:38 +01001870 return createUserInternalUnchecked(name, flags, parentId);
1871 }
1872
1873 private UserInfo createUserInternalUnchecked(String name, int flags, int parentId) {
Nicolas Prevot12678a92015-05-13 12:15:03 -07001874 if (ActivityManager.isLowRamDeviceStatic()) {
1875 return null;
1876 }
Amith Yamasani95ab7842014-08-11 17:09:26 -07001877 final boolean isGuest = (flags & UserInfo.FLAG_GUEST) != 0;
Nicolas Prevot12678a92015-05-13 12:15:03 -07001878 final boolean isManagedProfile = (flags & UserInfo.FLAG_MANAGED_PROFILE) != 0;
Fyodor Kupolov06a484a2015-08-21 16:33:20 -07001879 final boolean isRestricted = (flags & UserInfo.FLAG_RESTRICTED) != 0;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001880 final long ident = Binder.clearCallingIdentity();
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001881 UserInfo userInfo;
Amith Yamasani12747872015-12-07 14:19:49 -08001882 UserData userData;
Amith Yamasanibb054c92015-07-09 14:16:27 -07001883 final int userId;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001884 try {
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001885 synchronized (mPackagesLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08001886 UserData parent = null;
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001887 if (parentId != UserHandle.USER_NULL) {
1888 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08001889 parent = getUserDataLU(parentId);
Nicolas Prevotc6d033e2014-02-27 13:11:09 +00001890 }
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001891 if (parent == null) return null;
1892 }
1893 if (isManagedProfile && !canAddMoreManagedProfiles(parentId, false)) {
1894 Log.e(LOG_TAG, "Cannot add more managed profiles for user " + parentId);
1895 return null;
1896 }
1897 if (!isGuest && !isManagedProfile && isUserLimitReached()) {
1898 // If we're not adding a guest user or a managed profile and the limit has
1899 // been reached, cannot add a user.
1900 return null;
1901 }
1902 // If we're adding a guest and there already exists one, bail.
1903 if (isGuest && findCurrentGuestUser() != null) {
1904 return null;
1905 }
1906 // In legacy mode, restricted profile's parent can only be the owner user
1907 if (isRestricted && !UserManager.isSplitSystemUser()
1908 && (parentId != UserHandle.USER_SYSTEM)) {
1909 Log.w(LOG_TAG, "Cannot add restricted profile - parent user must be owner");
1910 return null;
1911 }
1912 if (isRestricted && UserManager.isSplitSystemUser()) {
1913 if (parent == null) {
1914 Log.w(LOG_TAG, "Cannot add restricted profile - parent user must be "
1915 + "specified");
Nicolas Prevot12678a92015-05-13 12:15:03 -07001916 return null;
1917 }
Amith Yamasani12747872015-12-07 14:19:49 -08001918 if (!parent.info.canHaveProfile()) {
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001919 Log.w(LOG_TAG, "Cannot add restricted profile - profiles cannot be "
1920 + "created for the specified parent user id " + parentId);
Amith Yamasani95ab7842014-08-11 17:09:26 -07001921 return null;
1922 }
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001923 }
Lenka Trochtova024f9792016-02-17 13:55:17 +01001924 if (!UserManager.isSplitSystemUser() && (flags & UserInfo.FLAG_EPHEMERAL) != 0) {
1925 Log.e(LOG_TAG,
1926 "Ephemeral users are supported on split-system-user systems only.");
1927 return null;
1928 }
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001929 // In split system user mode, we assign the first human user the primary flag.
1930 // And if there is no device owner, we also assign the admin flag to primary user.
1931 if (UserManager.isSplitSystemUser()
1932 && !isGuest && !isManagedProfile && getPrimaryUser() == null) {
1933 flags |= UserInfo.FLAG_PRIMARY;
Makoto Onukie7927da2015-11-25 10:05:17 -08001934 synchronized (mUsersLock) {
1935 if (!mIsDeviceManaged) {
1936 flags |= UserInfo.FLAG_ADMIN;
1937 }
Amith Yamasani95ab7842014-08-11 17:09:26 -07001938 }
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001939 }
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01001940
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +01001941 userId = getNextAvailableId();
1942 Environment.getUserSystemDirectory(userId).mkdirs();
Lenka Trochtova02fee152015-12-22 14:26:18 +01001943 boolean ephemeralGuests = Resources.getSystem()
1944 .getBoolean(com.android.internal.R.bool.config_guestUserEphemeral);
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +01001945
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001946 synchronized (mUsersLock) {
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +01001947 // Add ephemeral flag to guests/users if required. Also inherit it from parent.
1948 if ((isGuest && ephemeralGuests) || mForceEphemeralUsers
1949 || (parent != null && parent.info.isEphemeral())) {
1950 flags |= UserInfo.FLAG_EPHEMERAL;
1951 }
1952
1953 userInfo = new UserInfo(userId, name, null, flags);
1954 userInfo.serialNumber = mNextSerialNumber++;
1955 long now = System.currentTimeMillis();
1956 userInfo.creationTime = (now > EPOCH_PLUS_30_YEARS) ? now : 0;
1957 userInfo.partial = true;
Fyodor Kupolov83c24242016-03-31 13:30:42 -07001958 userInfo.lastLoggedInFingerprint = Build.FINGERPRINT;
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +01001959 userData = new UserData();
1960 userData.info = userInfo;
Amith Yamasani12747872015-12-07 14:19:49 -08001961 mUsers.put(userId, userData);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001962 }
Jeff Sharkeycd575992016-03-29 14:12:49 -06001963 writeUserLP(userData);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001964 writeUserListLP();
1965 if (parent != null) {
1966 if (isManagedProfile) {
Amith Yamasani12747872015-12-07 14:19:49 -08001967 if (parent.info.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
1968 parent.info.profileGroupId = parent.info.id;
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001969 writeUserLP(parent);
Kenny Guya52dc3e2014-02-11 15:33:14 +00001970 }
Amith Yamasani12747872015-12-07 14:19:49 -08001971 userInfo.profileGroupId = parent.info.profileGroupId;
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001972 } else if (isRestricted) {
Amith Yamasani12747872015-12-07 14:19:49 -08001973 if (parent.info.restrictedProfileParentId == UserInfo.NO_PROFILE_GROUP_ID) {
1974 parent.info.restrictedProfileParentId = parent.info.id;
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001975 writeUserLP(parent);
Jeff Sharkey6dce4962015-07-03 18:08:41 -07001976 }
Amith Yamasani12747872015-12-07 14:19:49 -08001977 userInfo.restrictedProfileParentId = parent.info.restrictedProfileParentId;
Makoto Onuki068c54a2015-10-13 14:34:03 -07001978 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001979 }
Dianne Hackborn4428e172012-08-24 17:43:05 -07001980 }
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001981 final StorageManager storage = mContext.getSystemService(StorageManager.class);
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01001982 storage.createUserKey(userId, userInfo.serialNumber, userInfo.isEphemeral());
Jeff Sharkey47f71082016-02-01 17:03:54 -07001983 prepareUserStorage(userId, userInfo.serialNumber,
1984 StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001985 mPm.createNewUser(userId);
1986 userInfo.partial = false;
1987 synchronized (mPackagesLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08001988 writeUserLP(userData);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001989 }
1990 updateUserIds();
1991 Bundle restrictions = new Bundle();
Fyodor Kupolove04462c2015-11-30 15:02:53 -08001992 if (isGuest) {
1993 synchronized (mGuestRestrictions) {
1994 restrictions.putAll(mGuestRestrictions);
1995 }
1996 }
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001997 synchronized (mRestrictionsLock) {
1998 mBaseUserRestrictions.append(userId, restrictions);
1999 }
2000 mPm.newUserCreated(userId);
2001 Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
2002 addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
2003 mContext.sendBroadcastAsUser(addedIntent, UserHandle.ALL,
2004 android.Manifest.permission.MANAGE_USERS);
Fyodor Kupolov8385e4b2015-12-29 18:15:32 -08002005 MetricsLogger.count(mContext, isGuest ? TRON_GUEST_CREATED : TRON_USER_CREATED, 1);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002006 } finally {
2007 Binder.restoreCallingIdentity(ident);
Amith Yamasani258848d2012-08-10 17:06:33 -07002008 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002009 return userInfo;
2010 }
2011
Amith Yamasani0b285492011-04-14 17:35:23 -07002012 /**
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -07002013 * @hide
2014 */
Amith Yamasani12747872015-12-07 14:19:49 -08002015 @Override
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -07002016 public UserInfo createRestrictedProfile(String name, int parentUserId) {
2017 checkManageUsersPermission("setupRestrictedProfile");
2018 final UserInfo user = createProfileForUser(name, UserInfo.FLAG_RESTRICTED, parentUserId);
2019 if (user == null) {
2020 return null;
2021 }
Fyodor Kupolov9e912ba2016-02-09 18:29:43 -08002022 long identity = Binder.clearCallingIdentity();
2023 try {
2024 setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user.id);
2025 // Change the setting before applying the DISALLOW_SHARE_LOCATION restriction, otherwise
2026 // the putIntForUser() will fail.
2027 android.provider.Settings.Secure.putIntForUser(mContext.getContentResolver(),
2028 android.provider.Settings.Secure.LOCATION_MODE,
2029 android.provider.Settings.Secure.LOCATION_MODE_OFF, user.id);
2030 setUserRestriction(UserManager.DISALLOW_SHARE_LOCATION, true, user.id);
2031 } finally {
2032 Binder.restoreCallingIdentity(identity);
2033 }
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -07002034 return user;
2035 }
2036
2037 /**
Adam Lesinskieddeb492014-09-08 17:50:03 -07002038 * Find the current guest user. If the Guest user is partial,
2039 * then do not include it in the results as it is about to die.
Adam Lesinskieddeb492014-09-08 17:50:03 -07002040 */
Fyodor Kupolov82402752015-10-28 14:54:51 -07002041 private UserInfo findCurrentGuestUser() {
2042 synchronized (mUsersLock) {
2043 final int size = mUsers.size();
2044 for (int i = 0; i < size; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -08002045 final UserInfo user = mUsers.valueAt(i).info;
Fyodor Kupolov82402752015-10-28 14:54:51 -07002046 if (user.isGuest() && !user.guestToRemove && !mRemovingUserIds.get(user.id)) {
2047 return user;
2048 }
Adam Lesinskieddeb492014-09-08 17:50:03 -07002049 }
2050 }
2051 return null;
2052 }
2053
2054 /**
Amith Yamasani1df14732014-08-29 21:37:27 -07002055 * Mark this guest user for deletion to allow us to create another guest
2056 * and switch to that user before actually removing this guest.
2057 * @param userHandle the userid of the current guest
2058 * @return whether the user could be marked for deletion
2059 */
Amith Yamasani12747872015-12-07 14:19:49 -08002060 @Override
Amith Yamasani1df14732014-08-29 21:37:27 -07002061 public boolean markGuestForDeletion(int userHandle) {
2062 checkManageUsersPermission("Only the system can remove users");
2063 if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(
2064 UserManager.DISALLOW_REMOVE_USER, false)) {
2065 Log.w(LOG_TAG, "Cannot remove user. DISALLOW_REMOVE_USER is enabled.");
2066 return false;
2067 }
2068
2069 long ident = Binder.clearCallingIdentity();
2070 try {
Amith Yamasani12747872015-12-07 14:19:49 -08002071 final UserData userData;
Amith Yamasani1df14732014-08-29 21:37:27 -07002072 synchronized (mPackagesLock) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002073 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08002074 userData = mUsers.get(userHandle);
2075 if (userHandle == 0 || userData == null || mRemovingUserIds.get(userHandle)) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002076 return false;
2077 }
Amith Yamasani1df14732014-08-29 21:37:27 -07002078 }
Amith Yamasani12747872015-12-07 14:19:49 -08002079 if (!userData.info.isGuest()) {
Amith Yamasani1df14732014-08-29 21:37:27 -07002080 return false;
2081 }
Adam Lesinskieddeb492014-09-08 17:50:03 -07002082 // We set this to a guest user that is to be removed. This is a temporary state
2083 // where we are allowed to add new Guest users, even if this one is still not
2084 // removed. This user will still show up in getUserInfo() calls.
2085 // If we don't get around to removing this Guest user, it will be purged on next
2086 // startup.
Amith Yamasani12747872015-12-07 14:19:49 -08002087 userData.info.guestToRemove = true;
Amith Yamasani1df14732014-08-29 21:37:27 -07002088 // Mark it as disabled, so that it isn't returned any more when
2089 // profiles are queried.
Amith Yamasani12747872015-12-07 14:19:49 -08002090 userData.info.flags |= UserInfo.FLAG_DISABLED;
2091 writeUserLP(userData);
Amith Yamasani1df14732014-08-29 21:37:27 -07002092 }
2093 } finally {
2094 Binder.restoreCallingIdentity(ident);
2095 }
2096 return true;
2097 }
2098
2099 /**
Amith Yamasani0b285492011-04-14 17:35:23 -07002100 * Removes a user and all data directories created for that user. This method should be called
2101 * after the user's processes have been terminated.
Dianne Hackborn10ad9822014-03-17 11:28:36 -07002102 * @param userHandle the user's id
Amith Yamasani0b285492011-04-14 17:35:23 -07002103 */
Amith Yamasani12747872015-12-07 14:19:49 -08002104 @Override
Amith Yamasani258848d2012-08-10 17:06:33 -07002105 public boolean removeUser(int userHandle) {
Amith Yamasani2a003292012-08-14 18:25:45 -07002106 checkManageUsersPermission("Only the system can remove users");
Julia Reynolds4ac5f852014-06-23 17:38:51 -04002107 if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(
2108 UserManager.DISALLOW_REMOVE_USER, false)) {
2109 Log.w(LOG_TAG, "Cannot remove user. DISALLOW_REMOVE_USER is enabled.");
2110 return false;
2111 }
2112
Kenny Guyee58b4f2014-05-23 15:19:53 +01002113 long ident = Binder.clearCallingIdentity();
2114 try {
Amith Yamasani12747872015-12-07 14:19:49 -08002115 final UserData userData;
Fyodor Kupolov0df68cd2015-10-01 13:54:22 -07002116 int currentUser = ActivityManager.getCurrentUser();
2117 if (currentUser == userHandle) {
2118 Log.w(LOG_TAG, "Current user cannot be removed");
2119 return false;
2120 }
Kenny Guyee58b4f2014-05-23 15:19:53 +01002121 synchronized (mPackagesLock) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002122 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08002123 userData = mUsers.get(userHandle);
2124 if (userHandle == 0 || userData == null || mRemovingUserIds.get(userHandle)) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002125 return false;
2126 }
Jeff Sharkey6eb09392014-11-14 15:57:59 -08002127
Fyodor Kupolov82402752015-10-28 14:54:51 -07002128 // We remember deleted user IDs to prevent them from being
2129 // reused during the current boot; they can still be reused
2130 // after a reboot.
2131 mRemovingUserIds.put(userHandle, true);
2132 }
Jeff Sharkey6eb09392014-11-14 15:57:59 -08002133
Kenny Guyee58b4f2014-05-23 15:19:53 +01002134 try {
2135 mAppOpsService.removeUser(userHandle);
2136 } catch (RemoteException e) {
2137 Log.w(LOG_TAG, "Unable to notify AppOpsService of removing user", e);
2138 }
2139 // Set this to a partially created user, so that the user will be purged
2140 // on next startup, in case the runtime stops now before stopping and
2141 // removing the user completely.
Amith Yamasani12747872015-12-07 14:19:49 -08002142 userData.info.partial = true;
Kenny Guyee58b4f2014-05-23 15:19:53 +01002143 // Mark it as disabled, so that it isn't returned any more when
2144 // profiles are queried.
Amith Yamasani12747872015-12-07 14:19:49 -08002145 userData.info.flags |= UserInfo.FLAG_DISABLED;
2146 writeUserLP(userData);
Kenny Guyee58b4f2014-05-23 15:19:53 +01002147 }
2148
Amith Yamasani12747872015-12-07 14:19:49 -08002149 if (userData.info.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
2150 && userData.info.isManagedProfile()) {
Kenny Guyee58b4f2014-05-23 15:19:53 +01002151 // Send broadcast to notify system that the user removed was a
2152 // managed user.
Amith Yamasani12747872015-12-07 14:19:49 -08002153 sendProfileRemovedBroadcast(userData.info.profileGroupId, userData.info.id);
Kenny Guyee58b4f2014-05-23 15:19:53 +01002154 }
2155
2156 if (DBG) Slog.i(LOG_TAG, "Stopping user " + userHandle);
2157 int res;
2158 try {
Fyodor Kupolov9cbfc9e2015-10-07 15:52:33 -07002159 res = ActivityManagerNative.getDefault().stopUser(userHandle, /* force= */ true,
2160 new IStopUserCallback.Stub() {
Kenny Guyee58b4f2014-05-23 15:19:53 +01002161 @Override
2162 public void userStopped(int userId) {
2163 finishRemoveUser(userId);
2164 }
2165 @Override
2166 public void userStopAborted(int userId) {
2167 }
2168 });
2169 } catch (RemoteException e) {
Dianne Hackborn80a4af22012-08-27 19:18:31 -07002170 return false;
2171 }
Kenny Guyee58b4f2014-05-23 15:19:53 +01002172 return res == ActivityManager.USER_OP_SUCCESS;
2173 } finally {
2174 Binder.restoreCallingIdentity(ident);
Dianne Hackborn80a4af22012-08-27 19:18:31 -07002175 }
Dianne Hackborn80a4af22012-08-27 19:18:31 -07002176 }
2177
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07002178 void finishRemoveUser(final int userHandle) {
Amith Yamasani16389312012-10-17 21:20:14 -07002179 if (DBG) Slog.i(LOG_TAG, "finishRemoveUser " + userHandle);
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07002180 // Let other services shutdown any activity and clean up their state before completely
2181 // wiping the user's system directory and removing from the user list
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002182 long ident = Binder.clearCallingIdentity();
2183 try {
2184 Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
2185 addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle);
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07002186 mContext.sendOrderedBroadcastAsUser(addedIntent, UserHandle.ALL,
2187 android.Manifest.permission.MANAGE_USERS,
2188
2189 new BroadcastReceiver() {
2190 @Override
2191 public void onReceive(Context context, Intent intent) {
2192 if (DBG) {
2193 Slog.i(LOG_TAG,
2194 "USER_REMOVED broadcast sent, cleaning up user data "
2195 + userHandle);
2196 }
2197 new Thread() {
Amith Yamasani12747872015-12-07 14:19:49 -08002198 @Override
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07002199 public void run() {
Amith Yamasani515d4062015-09-28 11:30:06 -07002200 // Clean up any ActivityManager state
2201 LocalServices.getService(ActivityManagerInternal.class)
2202 .onUserRemoved(userHandle);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002203 removeUserState(userHandle);
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07002204 }
2205 }.start();
2206 }
2207 },
2208
2209 null, Activity.RESULT_OK, null, null);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002210 } finally {
2211 Binder.restoreCallingIdentity(ident);
2212 }
Amith Yamasani2a003292012-08-14 18:25:45 -07002213 }
2214
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002215 private void removeUserState(final int userHandle) {
Paul Crowley91293792016-03-25 15:23:07 -07002216 try {
2217 mContext.getSystemService(StorageManager.class).destroyUserKey(userHandle);
2218 } catch (IllegalStateException e) {
2219 // This may be simply because the user was partially created.
2220 Slog.i(LOG_TAG,
2221 "Destroying key for user " + userHandle + " failed, continuing anyway", e);
2222 }
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07002223 // Cleanup package manager settings
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002224 mPm.cleanUpUser(this, userHandle);
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07002225
2226 // Remove this user from the list
Fyodor Kupolov82402752015-10-28 14:54:51 -07002227 synchronized (mUsersLock) {
2228 mUsers.remove(userHandle);
Makoto Onukie7927da2015-11-25 10:05:17 -08002229 mIsUserManaged.delete(userHandle);
2230 }
2231 synchronized (mRestrictionsLock) {
2232 mBaseUserRestrictions.remove(userHandle);
2233 mAppliedUserRestrictions.remove(userHandle);
2234 mCachedEffectiveUserRestrictions.remove(userHandle);
2235 mDevicePolicyLocalUserRestrictions.remove(userHandle);
Fyodor Kupolov82402752015-10-28 14:54:51 -07002236 }
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07002237 // Update the user list
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002238 synchronized (mPackagesLock) {
2239 writeUserListLP();
2240 }
Jeff Sharkeycd575992016-03-29 14:12:49 -06002241 // Remove user file
2242 AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX));
2243 userFile.delete();
Fyodor Kupolov82402752015-10-28 14:54:51 -07002244 updateUserIds();
Amith Yamasani12747872015-12-07 14:19:49 -08002245 File userDir = Environment.getUserSystemDirectory(userHandle);
2246 File renamedUserDir = Environment.getUserSystemDirectory(UserHandle.USER_NULL - userHandle);
2247 if (userDir.renameTo(renamedUserDir)) {
2248 removeDirectoryRecursive(renamedUserDir);
2249 } else {
2250 removeDirectoryRecursive(userDir);
2251 }
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07002252 }
2253
Amith Yamasani61f57372012-08-31 12:12:28 -07002254 private void removeDirectoryRecursive(File parent) {
2255 if (parent.isDirectory()) {
2256 String[] files = parent.list();
2257 for (String filename : files) {
2258 File child = new File(parent, filename);
2259 removeDirectoryRecursive(child);
2260 }
2261 }
2262 parent.delete();
2263 }
2264
Kenny Guyf8d3a232014-05-15 16:09:52 +01002265 private void sendProfileRemovedBroadcast(int parentUserId, int removedUserId) {
Adam Connors7b66ed52014-04-14 11:58:10 +01002266 Intent managedProfileIntent = new Intent(Intent.ACTION_MANAGED_PROFILE_REMOVED);
Adam Connorsd4b584e2014-06-09 13:55:47 +01002267 managedProfileIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY |
2268 Intent.FLAG_RECEIVER_FOREGROUND);
Kenny Guyf8d3a232014-05-15 16:09:52 +01002269 managedProfileIntent.putExtra(Intent.EXTRA_USER, new UserHandle(removedUserId));
Jeff Sharkeyaf6ec292015-12-17 11:19:00 -07002270 managedProfileIntent.putExtra(Intent.EXTRA_USER_HANDLE, removedUserId);
Kenny Guyf8d3a232014-05-15 16:09:52 +01002271 mContext.sendBroadcastAsUser(managedProfileIntent, new UserHandle(parentUserId), null);
Adam Connors7b66ed52014-04-14 11:58:10 +01002272 }
2273
Amith Yamasani2a003292012-08-14 18:25:45 -07002274 @Override
Amith Yamasani7e99bc02013-04-16 18:24:51 -07002275 public Bundle getApplicationRestrictions(String packageName) {
2276 return getApplicationRestrictionsForUser(packageName, UserHandle.getCallingUserId());
2277 }
2278
2279 @Override
2280 public Bundle getApplicationRestrictionsForUser(String packageName, int userId) {
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002281 if (UserHandle.getCallingUserId() != userId
Amith Yamasani9429afb2013-04-10 18:40:51 -07002282 || !UserHandle.isSameApp(Binder.getCallingUid(), getUidForPackage(packageName))) {
Esteban Talavera5b9f1672015-12-11 15:22:34 +00002283 checkSystemOrRoot("get application restrictions for other users/apps");
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002284 }
2285 synchronized (mPackagesLock) {
2286 // Read the restrictions from XML
Fyodor Kupolov82402752015-10-28 14:54:51 -07002287 return readApplicationRestrictionsLP(packageName, userId);
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002288 }
2289 }
2290
2291 @Override
Amith Yamasani7e99bc02013-04-16 18:24:51 -07002292 public void setApplicationRestrictions(String packageName, Bundle restrictions,
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002293 int userId) {
Esteban Talavera5b9f1672015-12-11 15:22:34 +00002294 checkSystemOrRoot("set application restrictions");
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002295 synchronized (mPackagesLock) {
Kenny Guyd21b2182014-07-17 16:38:55 +01002296 if (restrictions == null || restrictions.isEmpty()) {
2297 cleanAppRestrictionsForPackage(packageName, userId);
2298 } else {
Amith Yamasani23879322016-03-30 16:51:26 -07002299 restrictions.setDefusable(true);
Kenny Guyd21b2182014-07-17 16:38:55 +01002300 // Write the restrictions to XML
Fyodor Kupolov82402752015-10-28 14:54:51 -07002301 writeApplicationRestrictionsLP(packageName, restrictions, userId);
Kenny Guyd21b2182014-07-17 16:38:55 +01002302 }
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002303 }
Robin Lee66e5d962014-04-09 16:44:21 +01002304
Fyodor Kupolovd2846122016-02-11 18:06:34 -08002305 // Notify package of changes via an intent - only sent to explicitly registered receivers.
2306 Intent changeIntent = new Intent(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED);
2307 changeIntent.setPackage(packageName);
2308 changeIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
2309 mContext.sendBroadcastAsUser(changeIntent, UserHandle.of(userId));
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002310 }
2311
2312 private int getUidForPackage(String packageName) {
Amith Yamasani9429afb2013-04-10 18:40:51 -07002313 long ident = Binder.clearCallingIdentity();
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002314 try {
2315 return mContext.getPackageManager().getApplicationInfo(packageName,
Fyodor Kupolovd2846122016-02-11 18:06:34 -08002316 PackageManager.MATCH_UNINSTALLED_PACKAGES).uid;
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002317 } catch (NameNotFoundException nnfe) {
2318 return -1;
Amith Yamasani9429afb2013-04-10 18:40:51 -07002319 } finally {
2320 Binder.restoreCallingIdentity(ident);
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002321 }
2322 }
2323
Fyodor Kupolov82402752015-10-28 14:54:51 -07002324 private Bundle readApplicationRestrictionsLP(String packageName, int userId) {
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002325 AtomicFile restrictionsFile =
2326 new AtomicFile(new File(Environment.getUserSystemDirectory(userId),
2327 packageToRestrictionsFileName(packageName)));
Fyodor Kupolov82402752015-10-28 14:54:51 -07002328 return readApplicationRestrictionsLP(restrictionsFile);
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002329 }
2330
2331 @VisibleForTesting
Fyodor Kupolov82402752015-10-28 14:54:51 -07002332 static Bundle readApplicationRestrictionsLP(AtomicFile restrictionsFile) {
Amith Yamasani7e99bc02013-04-16 18:24:51 -07002333 final Bundle restrictions = new Bundle();
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002334 final ArrayList<String> values = new ArrayList<>();
Fyodor Kupolov6f34d362015-04-02 12:42:13 -07002335 if (!restrictionsFile.getBaseFile().exists()) {
Fyodor Kupolovf6ee2242015-04-06 10:15:07 -07002336 return restrictions;
Fyodor Kupolov6f34d362015-04-02 12:42:13 -07002337 }
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002338
2339 FileInputStream fis = null;
2340 try {
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002341 fis = restrictionsFile.openRead();
2342 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01002343 parser.setInput(fis, StandardCharsets.UTF_8.name());
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002344 XmlUtils.nextElement(parser);
2345 if (parser.getEventType() != XmlPullParser.START_TAG) {
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002346 Slog.e(LOG_TAG, "Unable to read restrictions file "
2347 + restrictionsFile.getBaseFile());
Amith Yamasani7e99bc02013-04-16 18:24:51 -07002348 return restrictions;
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002349 }
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002350 while (parser.next() != XmlPullParser.END_DOCUMENT) {
2351 readEntry(restrictions, values, parser);
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002352 }
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002353 } catch (IOException|XmlPullParserException e) {
2354 Log.w(LOG_TAG, "Error parsing " + restrictionsFile.getBaseFile(), e);
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002355 } finally {
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002356 IoUtils.closeQuietly(fis);
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002357 }
Amith Yamasani7e99bc02013-04-16 18:24:51 -07002358 return restrictions;
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002359 }
2360
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002361 private static void readEntry(Bundle restrictions, ArrayList<String> values,
2362 XmlPullParser parser) throws XmlPullParserException, IOException {
2363 int type = parser.getEventType();
2364 if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_ENTRY)) {
2365 String key = parser.getAttributeValue(null, ATTR_KEY);
2366 String valType = parser.getAttributeValue(null, ATTR_VALUE_TYPE);
2367 String multiple = parser.getAttributeValue(null, ATTR_MULTIPLE);
2368 if (multiple != null) {
2369 values.clear();
2370 int count = Integer.parseInt(multiple);
2371 while (count > 0 && (type = parser.next()) != XmlPullParser.END_DOCUMENT) {
2372 if (type == XmlPullParser.START_TAG
2373 && parser.getName().equals(TAG_VALUE)) {
2374 values.add(parser.nextText().trim());
2375 count--;
2376 }
2377 }
2378 String [] valueStrings = new String[values.size()];
2379 values.toArray(valueStrings);
2380 restrictions.putStringArray(key, valueStrings);
2381 } else if (ATTR_TYPE_BUNDLE.equals(valType)) {
2382 restrictions.putBundle(key, readBundleEntry(parser, values));
2383 } else if (ATTR_TYPE_BUNDLE_ARRAY.equals(valType)) {
2384 final int outerDepth = parser.getDepth();
2385 ArrayList<Bundle> bundleList = new ArrayList<>();
2386 while (XmlUtils.nextElementWithin(parser, outerDepth)) {
2387 Bundle childBundle = readBundleEntry(parser, values);
2388 bundleList.add(childBundle);
2389 }
2390 restrictions.putParcelableArray(key,
2391 bundleList.toArray(new Bundle[bundleList.size()]));
2392 } else {
2393 String value = parser.nextText().trim();
2394 if (ATTR_TYPE_BOOLEAN.equals(valType)) {
2395 restrictions.putBoolean(key, Boolean.parseBoolean(value));
2396 } else if (ATTR_TYPE_INTEGER.equals(valType)) {
2397 restrictions.putInt(key, Integer.parseInt(value));
2398 } else {
2399 restrictions.putString(key, value);
2400 }
2401 }
2402 }
2403 }
2404
2405 private static Bundle readBundleEntry(XmlPullParser parser, ArrayList<String> values)
2406 throws IOException, XmlPullParserException {
2407 Bundle childBundle = new Bundle();
2408 final int outerDepth = parser.getDepth();
2409 while (XmlUtils.nextElementWithin(parser, outerDepth)) {
2410 readEntry(childBundle, values, parser);
2411 }
2412 return childBundle;
2413 }
2414
Fyodor Kupolov82402752015-10-28 14:54:51 -07002415 private void writeApplicationRestrictionsLP(String packageName,
Amith Yamasani7e99bc02013-04-16 18:24:51 -07002416 Bundle restrictions, int userId) {
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002417 AtomicFile restrictionsFile = new AtomicFile(
2418 new File(Environment.getUserSystemDirectory(userId),
Amith Yamasanifc95e702013-09-26 13:20:17 -07002419 packageToRestrictionsFileName(packageName)));
Fyodor Kupolov82402752015-10-28 14:54:51 -07002420 writeApplicationRestrictionsLP(restrictions, restrictionsFile);
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002421 }
2422
2423 @VisibleForTesting
Fyodor Kupolov82402752015-10-28 14:54:51 -07002424 static void writeApplicationRestrictionsLP(Bundle restrictions, AtomicFile restrictionsFile) {
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002425 FileOutputStream fos = null;
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002426 try {
2427 fos = restrictionsFile.startWrite();
2428 final BufferedOutputStream bos = new BufferedOutputStream(fos);
2429
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002430 final XmlSerializer serializer = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01002431 serializer.setOutput(bos, StandardCharsets.UTF_8.name());
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002432 serializer.startDocument(null, true);
2433 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
2434
2435 serializer.startTag(null, TAG_RESTRICTIONS);
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002436 writeBundle(restrictions, serializer);
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002437 serializer.endTag(null, TAG_RESTRICTIONS);
2438
2439 serializer.endDocument();
2440 restrictionsFile.finishWrite(fos);
2441 } catch (Exception e) {
2442 restrictionsFile.failWrite(fos);
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002443 Slog.e(LOG_TAG, "Error writing application restrictions list", e);
2444 }
2445 }
2446
2447 private static void writeBundle(Bundle restrictions, XmlSerializer serializer)
2448 throws IOException {
2449 for (String key : restrictions.keySet()) {
2450 Object value = restrictions.get(key);
2451 serializer.startTag(null, TAG_ENTRY);
2452 serializer.attribute(null, ATTR_KEY, key);
2453
2454 if (value instanceof Boolean) {
2455 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BOOLEAN);
2456 serializer.text(value.toString());
2457 } else if (value instanceof Integer) {
2458 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_INTEGER);
2459 serializer.text(value.toString());
2460 } else if (value == null || value instanceof String) {
2461 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_STRING);
2462 serializer.text(value != null ? (String) value : "");
2463 } else if (value instanceof Bundle) {
2464 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BUNDLE);
2465 writeBundle((Bundle) value, serializer);
2466 } else if (value instanceof Parcelable[]) {
2467 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BUNDLE_ARRAY);
2468 Parcelable[] array = (Parcelable[]) value;
2469 for (Parcelable parcelable : array) {
2470 if (!(parcelable instanceof Bundle)) {
2471 throw new IllegalArgumentException("bundle-array can only hold Bundles");
2472 }
2473 serializer.startTag(null, TAG_ENTRY);
2474 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BUNDLE);
2475 writeBundle((Bundle) parcelable, serializer);
2476 serializer.endTag(null, TAG_ENTRY);
2477 }
2478 } else {
2479 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_STRING_ARRAY);
2480 String[] values = (String[]) value;
2481 serializer.attribute(null, ATTR_MULTIPLE, Integer.toString(values.length));
2482 for (String choice : values) {
2483 serializer.startTag(null, TAG_VALUE);
2484 serializer.text(choice != null ? choice : "");
2485 serializer.endTag(null, TAG_VALUE);
2486 }
2487 }
2488 serializer.endTag(null, TAG_ENTRY);
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002489 }
2490 }
2491
2492 @Override
Amith Yamasani2a003292012-08-14 18:25:45 -07002493 public int getUserSerialNumber(int userHandle) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002494 synchronized (mUsersLock) {
Amith Yamasani2a003292012-08-14 18:25:45 -07002495 if (!exists(userHandle)) return -1;
Fyodor Kupolov82402752015-10-28 14:54:51 -07002496 return getUserInfoLU(userHandle).serialNumber;
Amith Yamasani2a003292012-08-14 18:25:45 -07002497 }
2498 }
2499
2500 @Override
2501 public int getUserHandle(int userSerialNumber) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002502 synchronized (mUsersLock) {
Amith Yamasani2a003292012-08-14 18:25:45 -07002503 for (int userId : mUserIds) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002504 UserInfo info = getUserInfoLU(userId);
Kenny Guy945f8832015-02-10 15:17:26 +00002505 if (info != null && info.serialNumber == userSerialNumber) return userId;
Amith Yamasani2a003292012-08-14 18:25:45 -07002506 }
2507 // Not found
2508 return -1;
Amith Yamasani13593602012-03-22 16:16:17 -07002509 }
2510 }
2511
Fyodor Kupolovff7233e2015-04-08 11:28:52 -07002512 @Override
2513 public long getUserCreationTime(int userHandle) {
2514 int callingUserId = UserHandle.getCallingUserId();
2515 UserInfo userInfo = null;
Fyodor Kupolov82402752015-10-28 14:54:51 -07002516 synchronized (mUsersLock) {
Fyodor Kupolovff7233e2015-04-08 11:28:52 -07002517 if (callingUserId == userHandle) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002518 userInfo = getUserInfoLU(userHandle);
Fyodor Kupolovff7233e2015-04-08 11:28:52 -07002519 } else {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002520 UserInfo parent = getProfileParentLU(userHandle);
Fyodor Kupolovff7233e2015-04-08 11:28:52 -07002521 if (parent != null && parent.id == callingUserId) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002522 userInfo = getUserInfoLU(userHandle);
Fyodor Kupolovff7233e2015-04-08 11:28:52 -07002523 }
2524 }
2525 }
2526 if (userInfo == null) {
2527 throw new SecurityException("userHandle can only be the calling user or a managed "
2528 + "profile associated with this user");
2529 }
2530 return userInfo.creationTime;
2531 }
2532
Amith Yamasani0b285492011-04-14 17:35:23 -07002533 /**
2534 * Caches the list of user ids in an array, adjusting the array size when necessary.
2535 */
Fyodor Kupolov82402752015-10-28 14:54:51 -07002536 private void updateUserIds() {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07002537 int num = 0;
Fyodor Kupolov82402752015-10-28 14:54:51 -07002538 synchronized (mUsersLock) {
2539 final int userSize = mUsers.size();
2540 for (int i = 0; i < userSize; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -08002541 if (!mUsers.valueAt(i).info.partial) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002542 num++;
2543 }
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07002544 }
Fyodor Kupolov82402752015-10-28 14:54:51 -07002545 final int[] newUsers = new int[num];
2546 int n = 0;
2547 for (int i = 0; i < userSize; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -08002548 if (!mUsers.valueAt(i).info.partial) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002549 newUsers[n++] = mUsers.keyAt(i);
2550 }
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07002551 }
Fyodor Kupolov82402752015-10-28 14:54:51 -07002552 mUserIds = newUsers;
Amith Yamasani0b285492011-04-14 17:35:23 -07002553 }
2554 }
2555
2556 /**
Jeff Sharkey47f71082016-02-01 17:03:54 -07002557 * Prepare storage areas for given user on all mounted devices.
2558 */
2559 private void prepareUserStorage(int userId, int userSerial, int flags) {
2560 final StorageManager storage = mContext.getSystemService(StorageManager.class);
2561 for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
2562 final String volumeUuid = vol.getFsUuid();
2563 storage.prepareUserStorage(volumeUuid, userId, userSerial, flags);
2564 }
2565 }
2566
2567 /**
Jeff Sharkey0e62384c2016-01-13 18:52:55 -07002568 * Called right before a user is started. This gives us a chance to prepare
2569 * app storage and apply any user restrictions.
Makoto Onuki1a2cd742015-11-16 13:51:27 -08002570 */
2571 public void onBeforeStartUser(int userId) {
Jeff Sharkey47f71082016-02-01 17:03:54 -07002572 final int userSerial = getUserSerialNumber(userId);
2573 prepareUserStorage(userId, userSerial, StorageManager.FLAG_STORAGE_DE);
2574 mPm.reconcileAppsData(userId, StorageManager.FLAG_STORAGE_DE);
Jeff Sharkey0e62384c2016-01-13 18:52:55 -07002575
2576 if (userId != UserHandle.USER_SYSTEM) {
2577 synchronized (mRestrictionsLock) {
2578 applyUserRestrictionsLR(userId);
2579 }
Makoto Onuki1a2cd742015-11-16 13:51:27 -08002580 }
2581 }
2582
2583 /**
Jeff Sharkey0e62384c2016-01-13 18:52:55 -07002584 * Called right before a user is unlocked. This gives us a chance to prepare
2585 * app storage.
2586 */
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06002587 public void onBeforeUnlockUser(@UserIdInt int userId) {
Jeff Sharkey47f71082016-02-01 17:03:54 -07002588 final int userSerial = getUserSerialNumber(userId);
2589 prepareUserStorage(userId, userSerial, StorageManager.FLAG_STORAGE_CE);
2590 mPm.reconcileAppsData(userId, StorageManager.FLAG_STORAGE_CE);
Jeff Sharkey0e62384c2016-01-13 18:52:55 -07002591 }
2592
2593 /**
Amith Yamasani1a7472e2013-07-02 11:17:30 -07002594 * Make a note of the last started time of a user and do some cleanup.
Amith Yamasani920ace02012-09-20 22:15:37 -07002595 * @param userId the user that was just foregrounded
2596 */
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06002597 public void onUserLoggedIn(@UserIdInt int userId) {
Amith Yamasani12747872015-12-07 14:19:49 -08002598 UserData userData = getUserDataNoChecks(userId);
2599 if (userData == null || userData.info.partial) {
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002600 Slog.w(LOG_TAG, "userForeground: unknown user #" + userId);
2601 return;
2602 }
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06002603
2604 final long now = System.currentTimeMillis();
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002605 if (now > EPOCH_PLUS_30_YEARS) {
Amith Yamasani12747872015-12-07 14:19:49 -08002606 userData.info.lastLoggedInTime = now;
Amith Yamasani920ace02012-09-20 22:15:37 -07002607 }
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06002608 userData.info.lastLoggedInFingerprint = Build.FINGERPRINT;
2609 scheduleWriteUser(userData);
Amith Yamasani920ace02012-09-20 22:15:37 -07002610 }
2611
2612 /**
Amith Yamasani0b285492011-04-14 17:35:23 -07002613 * Returns the next available user id, filling in any holes in the ids.
Amith Yamasani742a6712011-05-04 14:49:28 -07002614 * TODO: May not be a good idea to recycle ids, in case it results in confusion
2615 * for data and battery stats collection, or unexpected cross-talk.
Amith Yamasani0b285492011-04-14 17:35:23 -07002616 */
Fyodor Kupolov82402752015-10-28 14:54:51 -07002617 private int getNextAvailableId() {
2618 synchronized (mUsersLock) {
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -08002619 int i = MIN_USER_ID;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07002620 while (i < MAX_USER_ID) {
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -08002621 if (mUsers.indexOfKey(i) < 0 && !mRemovingUserIds.get(i)) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07002622 return i;
Amith Yamasani195263742012-08-21 15:40:12 -07002623 }
2624 i++;
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002625 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002626 }
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07002627 throw new IllegalStateException("No user id available!");
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002628 }
Amith Yamasani920ace02012-09-20 22:15:37 -07002629
Amith Yamasanifc95e702013-09-26 13:20:17 -07002630 private String packageToRestrictionsFileName(String packageName) {
2631 return RESTRICTIONS_FILE_PREFIX + packageName + XML_SUFFIX;
2632 }
2633
Jeff Sharkey6dce4962015-07-03 18:08:41 -07002634 /**
Jeff Sharkey6dce4962015-07-03 18:08:41 -07002635 * Enforce that serial number stored in user directory inode matches the
2636 * given expected value. Gracefully sets the serial number if currently
2637 * undefined.
2638 *
2639 * @throws IOException when problem extracting serial number, or serial
2640 * number is mismatched.
2641 */
2642 public static void enforceSerialNumber(File file, int serialNumber) throws IOException {
2643 final int foundSerial = getSerialNumber(file);
2644 Slog.v(LOG_TAG, "Found " + file + " with serial number " + foundSerial);
2645
2646 if (foundSerial == -1) {
2647 Slog.d(LOG_TAG, "Serial number missing on " + file + "; assuming current is valid");
2648 try {
2649 setSerialNumber(file, serialNumber);
2650 } catch (IOException e) {
2651 Slog.w(LOG_TAG, "Failed to set serial number on " + file, e);
2652 }
2653
2654 } else if (foundSerial != serialNumber) {
2655 throw new IOException("Found serial number " + foundSerial
2656 + " doesn't match expected " + serialNumber);
2657 }
2658 }
2659
2660 /**
2661 * Set serial number stored in user directory inode.
2662 *
2663 * @throws IOException if serial number was already set
2664 */
2665 private static void setSerialNumber(File file, int serialNumber)
2666 throws IOException {
2667 try {
2668 final byte[] buf = Integer.toString(serialNumber).getBytes(StandardCharsets.UTF_8);
2669 Os.setxattr(file.getAbsolutePath(), XATTR_SERIAL, buf, OsConstants.XATTR_CREATE);
2670 } catch (ErrnoException e) {
2671 throw e.rethrowAsIOException();
2672 }
2673 }
2674
2675 /**
2676 * Return serial number stored in user directory inode.
2677 *
2678 * @return parsed serial number, or -1 if not set
2679 */
2680 private static int getSerialNumber(File file) throws IOException {
2681 try {
2682 final byte[] buf = new byte[256];
2683 final int len = Os.getxattr(file.getAbsolutePath(), XATTR_SERIAL, buf);
2684 final String serial = new String(buf, 0, len);
2685 try {
2686 return Integer.parseInt(serial);
2687 } catch (NumberFormatException e) {
2688 throw new IOException("Bad serial number: " + serial);
2689 }
2690 } catch (ErrnoException e) {
2691 if (e.errno == OsConstants.ENODATA) {
2692 return -1;
2693 } else {
2694 throw e.rethrowAsIOException();
2695 }
2696 }
2697 }
2698
Amith Yamasani920ace02012-09-20 22:15:37 -07002699 @Override
Amith Yamasani12747872015-12-07 14:19:49 -08002700 public void setSeedAccountData(int userId, String accountName, String accountType,
2701 PersistableBundle accountOptions, boolean persist) {
2702 checkManageUsersPermission("Require MANAGE_USERS permission to set user seed data");
2703 synchronized (mPackagesLock) {
2704 final UserData userData;
2705 synchronized (mUsersLock) {
2706 userData = getUserDataLU(userId);
2707 if (userData == null) {
2708 Slog.e(LOG_TAG, "No such user for settings seed data u=" + userId);
2709 return;
2710 }
2711 userData.seedAccountName = accountName;
2712 userData.seedAccountType = accountType;
2713 userData.seedAccountOptions = accountOptions;
2714 userData.persistSeedData = persist;
2715 }
2716 if (persist) {
2717 writeUserLP(userData);
2718 }
2719 }
2720 }
2721
2722 @Override
2723 public String getSeedAccountName() throws RemoteException {
2724 checkManageUsersPermission("Cannot get seed account information");
2725 synchronized (mUsersLock) {
2726 UserData userData = getUserDataLU(UserHandle.getCallingUserId());
2727 return userData.seedAccountName;
2728 }
2729 }
2730
2731 @Override
2732 public String getSeedAccountType() throws RemoteException {
2733 checkManageUsersPermission("Cannot get seed account information");
2734 synchronized (mUsersLock) {
2735 UserData userData = getUserDataLU(UserHandle.getCallingUserId());
2736 return userData.seedAccountType;
2737 }
2738 }
2739
2740 @Override
2741 public PersistableBundle getSeedAccountOptions() throws RemoteException {
2742 checkManageUsersPermission("Cannot get seed account information");
2743 synchronized (mUsersLock) {
2744 UserData userData = getUserDataLU(UserHandle.getCallingUserId());
2745 return userData.seedAccountOptions;
2746 }
2747 }
2748
2749 @Override
2750 public void clearSeedAccountData() throws RemoteException {
2751 checkManageUsersPermission("Cannot clear seed account information");
2752 synchronized (mPackagesLock) {
2753 UserData userData;
2754 synchronized (mUsersLock) {
2755 userData = getUserDataLU(UserHandle.getCallingUserId());
2756 if (userData == null) return;
2757 userData.clearSeedAccountData();
2758 }
2759 writeUserLP(userData);
2760 }
2761 }
2762
2763 @Override
2764 public boolean someUserHasSeedAccount(String accountName, String accountType)
2765 throws RemoteException {
2766 checkManageUsersPermission("Cannot check seed account information");
2767 synchronized (mUsersLock) {
2768 final int userSize = mUsers.size();
2769 for (int i = 0; i < userSize; i++) {
2770 final UserData data = mUsers.valueAt(i);
2771 if (data.info.isInitialized()) continue;
2772 if (data.seedAccountName == null || !data.seedAccountName.equals(accountName)) {
2773 continue;
2774 }
2775 if (data.seedAccountType == null || !data.seedAccountType.equals(accountType)) {
2776 continue;
2777 }
2778 return true;
2779 }
2780 }
2781 return false;
2782 }
2783
2784 @Override
Todd Kennedy60459ab2015-10-30 11:32:16 -07002785 public void onShellCommand(FileDescriptor in, FileDescriptor out,
2786 FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
2787 (new Shell()).exec(this, in, out, err, args, resultReceiver);
2788 }
2789
2790 int onShellCommand(Shell shell, String cmd) {
2791 if (cmd == null) {
2792 return shell.handleDefaultCommands(cmd);
2793 }
2794
2795 final PrintWriter pw = shell.getOutPrintWriter();
2796 try {
2797 switch(cmd) {
2798 case "list":
2799 return runList(pw);
2800 }
2801 } catch (RemoteException e) {
2802 pw.println("Remote exception: " + e);
2803 }
2804 return -1;
2805 }
2806
2807 private int runList(PrintWriter pw) throws RemoteException {
2808 final IActivityManager am = ActivityManagerNative.getDefault();
2809 final List<UserInfo> users = getUsers(false);
2810 if (users == null) {
2811 pw.println("Error: couldn't get users");
2812 return 1;
2813 } else {
2814 pw.println("Users:");
2815 for (int i = 0; i < users.size(); i++) {
Jeff Sharkeye17ac152015-11-06 22:40:29 -08002816 String running = am.isUserRunning(users.get(i).id, 0) ? " running" : "";
Todd Kennedy60459ab2015-10-30 11:32:16 -07002817 pw.println("\t" + users.get(i).toString() + running);
2818 }
2819 return 0;
2820 }
2821 }
2822
2823 @Override
Amith Yamasani920ace02012-09-20 22:15:37 -07002824 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2825 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
2826 != PackageManager.PERMISSION_GRANTED) {
2827 pw.println("Permission Denial: can't dump UserManager from from pid="
2828 + Binder.getCallingPid()
2829 + ", uid=" + Binder.getCallingUid()
2830 + " without permission "
2831 + android.Manifest.permission.DUMP);
2832 return;
2833 }
2834
2835 long now = System.currentTimeMillis();
2836 StringBuilder sb = new StringBuilder();
2837 synchronized (mPackagesLock) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002838 synchronized (mUsersLock) {
2839 pw.println("Users:");
2840 for (int i = 0; i < mUsers.size(); i++) {
Amith Yamasani12747872015-12-07 14:19:49 -08002841 UserData userData = mUsers.valueAt(i);
2842 if (userData == null) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002843 continue;
2844 }
Amith Yamasani12747872015-12-07 14:19:49 -08002845 UserInfo userInfo = userData.info;
2846 final int userId = userInfo.id;
2847 pw.print(" "); pw.print(userInfo);
2848 pw.print(" serialNo="); pw.print(userInfo.serialNumber);
Makoto Onukie7927da2015-11-25 10:05:17 -08002849 if (mRemovingUserIds.get(userId)) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002850 pw.print(" <removing> ");
2851 }
Amith Yamasani12747872015-12-07 14:19:49 -08002852 if (userInfo.partial) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002853 pw.print(" <partial>");
2854 }
2855 pw.println();
2856 pw.print(" Created: ");
Amith Yamasani12747872015-12-07 14:19:49 -08002857 if (userInfo.creationTime == 0) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002858 pw.println("<unknown>");
2859 } else {
2860 sb.setLength(0);
Amith Yamasani12747872015-12-07 14:19:49 -08002861 TimeUtils.formatDuration(now - userInfo.creationTime, sb);
Fyodor Kupolov82402752015-10-28 14:54:51 -07002862 sb.append(" ago");
2863 pw.println(sb);
2864 }
2865 pw.print(" Last logged in: ");
Amith Yamasani12747872015-12-07 14:19:49 -08002866 if (userInfo.lastLoggedInTime == 0) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002867 pw.println("<unknown>");
2868 } else {
2869 sb.setLength(0);
Amith Yamasani12747872015-12-07 14:19:49 -08002870 TimeUtils.formatDuration(now - userInfo.lastLoggedInTime, sb);
Fyodor Kupolov82402752015-10-28 14:54:51 -07002871 sb.append(" ago");
2872 pw.println(sb);
2873 }
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06002874 pw.print(" Last logged in fingerprint: ");
2875 pw.println(userInfo.lastLoggedInFingerprint);
Makoto Onukie7927da2015-11-25 10:05:17 -08002876 pw.print(" Has profile owner: ");
2877 pw.println(mIsUserManaged.get(userId));
Fyodor Kupolov82402752015-10-28 14:54:51 -07002878 pw.println(" Restrictions:");
2879 synchronized (mRestrictionsLock) {
2880 UserRestrictionsUtils.dumpRestrictions(
Amith Yamasani12747872015-12-07 14:19:49 -08002881 pw, " ", mBaseUserRestrictions.get(userInfo.id));
Makoto Onuki1a2cd742015-11-16 13:51:27 -08002882 pw.println(" Device policy local restrictions:");
2883 UserRestrictionsUtils.dumpRestrictions(
Amith Yamasani12747872015-12-07 14:19:49 -08002884 pw, " ", mDevicePolicyLocalUserRestrictions.get(userInfo.id));
Fyodor Kupolov82402752015-10-28 14:54:51 -07002885 pw.println(" Effective restrictions:");
2886 UserRestrictionsUtils.dumpRestrictions(
Amith Yamasani12747872015-12-07 14:19:49 -08002887 pw, " ", mCachedEffectiveUserRestrictions.get(userInfo.id));
Fyodor Kupolov82402752015-10-28 14:54:51 -07002888 }
Amith Yamasani12747872015-12-07 14:19:49 -08002889
2890 if (userData.account != null) {
2891 pw.print(" Account name: " + userData.account);
Xiaohui Chenb3b92582015-12-07 11:22:13 -08002892 pw.println();
2893 }
Amith Yamasani12747872015-12-07 14:19:49 -08002894
2895 if (userData.seedAccountName != null) {
2896 pw.print(" Seed account name: " + userData.seedAccountName);
2897 pw.println();
2898 if (userData.seedAccountType != null) {
2899 pw.print(" account type: " + userData.seedAccountType);
2900 pw.println();
2901 }
2902 if (userData.seedAccountOptions != null) {
2903 pw.print(" account options exist");
2904 pw.println();
2905 }
2906 }
Amith Yamasani920ace02012-09-20 22:15:37 -07002907 }
Amith Yamasani920ace02012-09-20 22:15:37 -07002908 }
Amith Yamasani12747872015-12-07 14:19:49 -08002909 pw.println();
Makoto Onuki1a2cd742015-11-16 13:51:27 -08002910 pw.println(" Device policy global restrictions:");
2911 synchronized (mRestrictionsLock) {
2912 UserRestrictionsUtils
2913 .dumpRestrictions(pw, " ", mDevicePolicyGlobalUserRestrictions);
2914 }
Makoto Onukia4f11972015-10-01 13:19:58 -07002915 pw.println();
Makoto Onuki1a2cd742015-11-16 13:51:27 -08002916 pw.println(" Guest restrictions:");
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002917 synchronized (mGuestRestrictions) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08002918 UserRestrictionsUtils.dumpRestrictions(pw, " ", mGuestRestrictions);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002919 }
Makoto Onukie7927da2015-11-25 10:05:17 -08002920 synchronized (mUsersLock) {
2921 pw.println();
2922 pw.println(" Device managed: " + mIsDeviceManaged);
2923 }
Amith Yamasani12747872015-12-07 14:19:49 -08002924 // Dump some capabilities
2925 pw.println();
2926 pw.println(" Max users: " + UserManager.getMaxSupportedUsers());
2927 pw.println(" Supports switchable users: " + UserManager.supportsMultipleUsers());
Lenka Trochtova02fee152015-12-22 14:26:18 +01002928 pw.println(" All guests ephemeral: " + Resources.getSystem().getBoolean(
2929 com.android.internal.R.bool.config_guestUserEphemeral));
Amith Yamasani920ace02012-09-20 22:15:37 -07002930 }
2931 }
Fyodor Kupolov75d0ea82014-12-15 16:21:07 -08002932
2933 final class MainHandler extends Handler {
2934
2935 @Override
2936 public void handleMessage(Message msg) {
2937 switch (msg.what) {
2938 case WRITE_USER_MSG:
2939 removeMessages(WRITE_USER_MSG, msg.obj);
2940 synchronized (mPackagesLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08002941 int userId = ((UserData) msg.obj).info.id;
2942 UserData userData = getUserDataNoChecks(userId);
2943 if (userData != null) {
2944 writeUserLP(userData);
Fyodor Kupolov75d0ea82014-12-15 16:21:07 -08002945 }
2946 }
2947 }
2948 }
2949 }
Amith Yamasanibb054c92015-07-09 14:16:27 -07002950
2951 /**
2952 * @param userId
2953 * @return whether the user has been initialized yet
2954 */
2955 boolean isInitialized(int userId) {
2956 return (getUserInfo(userId).flags & UserInfo.FLAG_INITIALIZED) != 0;
2957 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07002958
2959 private class LocalService extends UserManagerInternal {
Makoto Onuki068c54a2015-10-13 14:34:03 -07002960 @Override
Makoto Onuki1a2cd742015-11-16 13:51:27 -08002961 public void setDevicePolicyUserRestrictions(int userId, @NonNull Bundle localRestrictions,
2962 @Nullable Bundle globalRestrictions) {
Makoto Onuki2a3c3da2016-02-18 14:25:30 -08002963 UserManagerService.this.setDevicePolicyUserRestrictionsInner(userId, localRestrictions,
Makoto Onuki1a2cd742015-11-16 13:51:27 -08002964 globalRestrictions);
Makoto Onuki068c54a2015-10-13 14:34:03 -07002965 }
2966
2967 @Override
2968 public Bundle getBaseUserRestrictions(int userId) {
2969 synchronized (mRestrictionsLock) {
2970 return mBaseUserRestrictions.get(userId);
2971 }
2972 }
2973
2974 @Override
2975 public void setBaseUserRestrictionsByDpmsForMigration(
2976 int userId, Bundle baseRestrictions) {
2977 synchronized (mRestrictionsLock) {
2978 mBaseUserRestrictions.put(userId, new Bundle(baseRestrictions));
Fyodor Kupolov82402752015-10-28 14:54:51 -07002979 invalidateEffectiveUserRestrictionsLR(userId);
Makoto Onuki068c54a2015-10-13 14:34:03 -07002980 }
2981
Amith Yamasani12747872015-12-07 14:19:49 -08002982 final UserData userData = getUserDataNoChecks(userId);
Makoto Onuki068c54a2015-10-13 14:34:03 -07002983 synchronized (mPackagesLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08002984 if (userData != null) {
2985 writeUserLP(userData);
Makoto Onuki068c54a2015-10-13 14:34:03 -07002986 } else {
2987 Slog.w(LOG_TAG, "UserInfo not found for " + userId);
2988 }
2989 }
2990 }
Makoto Onukid45a4a22015-11-02 17:17:38 -08002991
2992 @Override
2993 public boolean getUserRestriction(int userId, String key) {
2994 return getUserRestrictions(userId).getBoolean(key);
2995 }
2996
2997 @Override
2998 public void addUserRestrictionsListener(UserRestrictionsListener listener) {
2999 synchronized (mUserRestrictionsListeners) {
3000 mUserRestrictionsListeners.add(listener);
3001 }
3002 }
3003
3004 @Override
3005 public void removeUserRestrictionsListener(UserRestrictionsListener listener) {
3006 synchronized (mUserRestrictionsListeners) {
3007 mUserRestrictionsListeners.remove(listener);
3008 }
3009 }
Makoto Onukie7927da2015-11-25 10:05:17 -08003010
3011 @Override
3012 public void setDeviceManaged(boolean isManaged) {
3013 synchronized (mUsersLock) {
3014 mIsDeviceManaged = isManaged;
3015 }
3016 }
3017
3018 @Override
3019 public void setUserManaged(int userId, boolean isManaged) {
3020 synchronized (mUsersLock) {
3021 mIsUserManaged.put(userId, isManaged);
3022 }
3023 }
Oleksandr Peletskyi7f1f1df2016-01-18 15:40:21 +01003024
3025 @Override
3026 public void setUserIcon(int userId, Bitmap bitmap) {
3027 long ident = Binder.clearCallingIdentity();
3028 try {
3029 synchronized (mPackagesLock) {
3030 UserData userData = getUserDataNoChecks(userId);
3031 if (userData == null || userData.info.partial) {
3032 Slog.w(LOG_TAG, "setUserIcon: unknown user #" + userId);
3033 return;
3034 }
3035 writeBitmapLP(userData.info, bitmap);
3036 writeUserLP(userData);
3037 }
3038 sendUserInfoChangedBroadcast(userId);
3039 } finally {
3040 Binder.restoreCallingIdentity(ident);
3041 }
3042 }
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +01003043
3044 @Override
3045 public void setForceEphemeralUsers(boolean forceEphemeralUsers) {
3046 synchronized (mUsersLock) {
3047 mForceEphemeralUsers = forceEphemeralUsers;
3048 }
3049 }
3050
3051 @Override
3052 public void removeAllUsers() {
3053 if (UserHandle.USER_SYSTEM == ActivityManager.getCurrentUser()) {
3054 // Remove the non-system users straight away.
3055 removeNonSystemUsers();
3056 } else {
3057 // Switch to the system user first and then remove the other users.
3058 BroadcastReceiver userSwitchedReceiver = new BroadcastReceiver() {
3059 @Override
3060 public void onReceive(Context context, Intent intent) {
3061 int userId =
3062 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
3063 if (userId != UserHandle.USER_SYSTEM) {
3064 return;
3065 }
3066 mContext.unregisterReceiver(this);
3067 removeNonSystemUsers();
3068 }
3069 };
3070 IntentFilter userSwitchedFilter = new IntentFilter();
3071 userSwitchedFilter.addAction(Intent.ACTION_USER_SWITCHED);
3072 mContext.registerReceiver(
3073 userSwitchedReceiver, userSwitchedFilter, null, mHandler);
3074
3075 // Switch to the system user.
3076 ActivityManager am =
3077 (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
3078 am.switchUser(UserHandle.USER_SYSTEM);
3079 }
3080 }
phweisse9c44062016-02-10 12:57:38 +01003081
3082 @Override
Lenka Trochtova1ddda472016-02-12 10:42:12 +01003083 public void onEphemeralUserStop(int userId) {
3084 synchronized (mUsersLock) {
3085 UserInfo userInfo = getUserInfoLU(userId);
3086 if (userInfo != null && userInfo.isEphemeral()) {
3087 // Do not allow switching back to the ephemeral user again as the user is going
3088 // to be deleted.
3089 userInfo.flags |= UserInfo.FLAG_DISABLED;
3090 if (userInfo.isGuest()) {
3091 // Indicate that the guest will be deleted after it stops.
3092 userInfo.guestToRemove = true;
3093 }
3094 }
3095 }
3096 }
3097
3098 @Override
phweisse9c44062016-02-10 12:57:38 +01003099 public UserInfo createUserEvenWhenDisallowed(String name, int flags) {
3100 UserInfo user = createUserInternalUnchecked(name, flags, UserHandle.USER_NULL);
3101 // Keep this in sync with UserManager.createUser
3102 if (user != null && !user.isAdmin()) {
3103 setUserRestriction(UserManager.DISALLOW_SMS, true, user.id);
3104 setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, true, user.id);
3105 }
3106 return user;
3107 }
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +01003108 }
3109
3110 /* Remove all the users except of the system one. */
3111 private void removeNonSystemUsers() {
3112 ArrayList<UserInfo> usersToRemove = new ArrayList<>();
3113 synchronized (mUsersLock) {
3114 final int userSize = mUsers.size();
3115 for (int i = 0; i < userSize; i++) {
3116 UserInfo ui = mUsers.valueAt(i).info;
3117 if (ui.id != UserHandle.USER_SYSTEM) {
3118 usersToRemove.add(ui);
3119 }
3120 }
3121 }
3122 for (UserInfo ui: usersToRemove) {
3123 removeUser(ui.id);
3124 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07003125 }
Todd Kennedy60459ab2015-10-30 11:32:16 -07003126
3127 private class Shell extends ShellCommand {
3128 @Override
3129 public int onCommand(String cmd) {
3130 return onShellCommand(this, cmd);
3131 }
3132
3133 @Override
3134 public void onHelp() {
3135 final PrintWriter pw = getOutPrintWriter();
3136 pw.println("User manager (user) commands:");
3137 pw.println(" help");
3138 pw.println(" Print this help text.");
3139 pw.println("");
3140 pw.println(" list");
3141 pw.println(" Prints all users on the system.");
3142 }
3143 }
Makoto Onuki1a2cd742015-11-16 13:51:27 -08003144
3145 private static void debug(String message) {
3146 Log.d(LOG_TAG, message +
3147 (DBG_WITH_STACKTRACE ? " called at\n" + Debug.getCallers(10, " ") : ""));
3148 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07003149}