blob: 8d1abb0c7d1c6df2c2faef2bce2a29e6e26c7665 [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
Benjamin Franzf02420c2016-04-04 18:52:21 +010020import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
21import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
22
Xiaohui Chenb3b92582015-12-07 11:22:13 -080023import android.Manifest;
Xiaohui Chen594f2082015-08-18 11:04:20 -070024import android.annotation.NonNull;
Makoto Onuki068c54a2015-10-13 14:34:03 -070025import android.annotation.Nullable;
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +010026import android.annotation.SystemApi;
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -060027import android.annotation.UserIdInt;
Amith Yamasanidb6a14c2012-10-17 21:16:52 -070028import android.app.Activity;
Amith Yamasani2a003292012-08-14 18:25:45 -070029import android.app.ActivityManager;
Amith Yamasani515d4062015-09-28 11:30:06 -070030import android.app.ActivityManagerInternal;
Dianne Hackborn80a4af22012-08-27 19:18:31 -070031import android.app.ActivityManagerNative;
Todd Kennedy60459ab2015-10-30 11:32:16 -070032import android.app.IActivityManager;
Dianne Hackborn80a4af22012-08-27 19:18:31 -070033import android.app.IStopUserCallback;
Benjamin Franzf02420c2016-04-04 18:52:21 +010034import android.app.KeyguardManager;
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +010035import android.app.admin.DevicePolicyManager;
Amith Yamasanidb6a14c2012-10-17 21:16:52 -070036import android.content.BroadcastReceiver;
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +010037import android.content.ComponentName;
Amith Yamasani258848d2012-08-10 17:06:33 -070038import android.content.Context;
39import android.content.Intent;
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +010040import android.content.IntentFilter;
Benjamin Franzf02420c2016-04-04 18:52:21 +010041import android.content.IntentSender;
Amith Yamasani0b285492011-04-14 17:35:23 -070042import android.content.pm.PackageManager;
Amith Yamasanidf2e92a2013-03-01 17:04:38 -080043import android.content.pm.PackageManager.NameNotFoundException;
Amith Yamasani4b2e9342011-03-31 12:38:53 -070044import android.content.pm.UserInfo;
Lenka Trochtova02fee152015-12-22 14:26:18 +010045import android.content.res.Resources;
Amith Yamasanie928d7d2012-09-17 21:46:51 -070046import android.graphics.Bitmap;
Amith Yamasani258848d2012-08-10 17:06:33 -070047import android.os.Binder;
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -060048import android.os.Build;
Amith Yamasanie4cf7342012-12-17 11:12:09 -080049import android.os.Bundle;
Makoto Onuki1a2cd742015-11-16 13:51:27 -080050import android.os.Debug;
Amith Yamasani4b2e9342011-03-31 12:38:53 -070051import android.os.Environment;
52import android.os.FileUtils;
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -080053import android.os.Handler;
Svet Ganov9cea80cd2016-02-16 11:47:00 -080054import android.os.IBinder;
Amith Yamasani258848d2012-08-10 17:06:33 -070055import android.os.IUserManager;
Fyodor Kupolov75d0ea82014-12-15 16:21:07 -080056import android.os.Message;
Adrian Roos1bdff912015-02-17 15:51:35 +010057import android.os.ParcelFileDescriptor;
Fyodor Kupolov262f9952015-03-23 18:55:11 -070058import android.os.Parcelable;
Amith Yamasani12747872015-12-07 14:19:49 -080059import android.os.PersistableBundle;
Amith Yamasani258848d2012-08-10 17:06:33 -070060import android.os.Process;
Dianne Hackborn80a4af22012-08-27 19:18:31 -070061import android.os.RemoteException;
Todd Kennedy60459ab2015-10-30 11:32:16 -070062import android.os.ResultReceiver;
Oleksandr Peletskyicd6fa302016-02-25 16:28:39 +010063import android.os.SELinux;
Jason Monk62062992014-05-06 09:55:28 -040064import android.os.ServiceManager;
Todd Kennedy60459ab2015-10-30 11:32:16 -070065import android.os.ShellCommand;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070066import android.os.UserHandle;
Jeff Sharkey27bd34d2012-09-16 12:49:00 -070067import android.os.UserManager;
Makoto Onuki068c54a2015-10-13 14:34:03 -070068import android.os.UserManagerInternal;
Makoto Onukid45a4a22015-11-02 17:17:38 -080069import android.os.UserManagerInternal.UserRestrictionsListener;
Paul Crowley85e4e812015-05-19 12:42:00 +010070import android.os.storage.StorageManager;
Jeff Sharkey6dce4962015-07-03 18:08:41 -070071import android.system.ErrnoException;
72import android.system.Os;
73import android.system.OsConstants;
Amith Yamasani2a003292012-08-14 18:25:45 -070074import android.util.AtomicFile;
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -070075import android.util.IntArray;
Amith Yamasani655d0e22013-06-12 14:19:10 -070076import android.util.Log;
Amith Yamasani4b2e9342011-03-31 12:38:53 -070077import android.util.Slog;
78import android.util.SparseArray;
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -080079import android.util.SparseBooleanArray;
Amith Yamasani920ace02012-09-20 22:15:37 -070080import android.util.TimeUtils;
Amith Yamasani4b2e9342011-03-31 12:38:53 -070081import android.util.Xml;
82
Makoto Onuki068c54a2015-10-13 14:34:03 -070083import com.android.internal.annotations.GuardedBy;
Fyodor Kupolov262f9952015-03-23 18:55:11 -070084import com.android.internal.annotations.VisibleForTesting;
Jason Monk62062992014-05-06 09:55:28 -040085import com.android.internal.app.IAppOpsService;
Fyodor Kupolov8385e4b2015-12-29 18:15:32 -080086import com.android.internal.logging.MetricsLogger;
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -080087import com.android.internal.util.FastXmlSerializer;
Makoto Onuki068c54a2015-10-13 14:34:03 -070088import com.android.internal.util.Preconditions;
Fyodor Kupolov262f9952015-03-23 18:55:11 -070089import com.android.internal.util.XmlUtils;
Clara Bayarri10ad84a2015-12-01 17:38:05 +000090import com.android.internal.widget.LockPatternUtils;
Amith Yamasani515d4062015-09-28 11:30:06 -070091import com.android.server.LocalServices;
Jeff Sharkey47f71082016-02-01 17:03:54 -070092
93import libcore.io.IoUtils;
94import libcore.util.Objects;
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -080095
96import org.xmlpull.v1.XmlPullParser;
97import org.xmlpull.v1.XmlPullParserException;
98import org.xmlpull.v1.XmlSerializer;
99
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700100import java.io.BufferedOutputStream;
101import java.io.File;
Amith Yamasani920ace02012-09-20 22:15:37 -0700102import java.io.FileDescriptor;
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700103import java.io.FileInputStream;
Amith Yamasanib8151ec2012-04-18 18:02:48 -0700104import java.io.FileNotFoundException;
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700105import java.io.FileOutputStream;
106import java.io.IOException;
Amith Yamasani920ace02012-09-20 22:15:37 -0700107import java.io.PrintWriter;
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +0100108import java.nio.charset.StandardCharsets;
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700109import java.util.ArrayList;
110import java.util.List;
111
Makoto Onuki068c54a2015-10-13 14:34:03 -0700112/**
113 * Service for {@link UserManager}.
114 *
115 * Method naming convention:
Fyodor Kupolov82402752015-10-28 14:54:51 -0700116 * <ul>
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800117 * <li> Methods suffixed with "LP" should be called within the {@link #mPackagesLock} lock.
Fyodor Kupolov82402752015-10-28 14:54:51 -0700118 * <li> Methods suffixed with "LR" should be called within the {@link #mRestrictionsLock} lock.
119 * <li> Methods suffixed with "LU" should be called within the {@link #mUsersLock} lock.
120 * </ul>
Makoto Onuki068c54a2015-10-13 14:34:03 -0700121 */
Amith Yamasani258848d2012-08-10 17:06:33 -0700122public class UserManagerService extends IUserManager.Stub {
Amith Yamasani2a003292012-08-14 18:25:45 -0700123 private static final String LOG_TAG = "UserManagerService";
Makoto Onuki81c61ea2016-01-22 11:22:26 -0800124 static final boolean DBG = false; // DO NOT SUBMIT WITH TRUE
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800125 private static final boolean DBG_WITH_STACKTRACE = false; // DO NOT SUBMIT WITH TRUE
Amith Yamasani16389312012-10-17 21:20:14 -0700126
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700127 private static final String TAG_NAME = "name";
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800128 private static final String TAG_ACCOUNT = "account";
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700129 private static final String ATTR_FLAGS = "flags";
Amith Yamasanib8151ec2012-04-18 18:02:48 -0700130 private static final String ATTR_ICON_PATH = "icon";
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700131 private static final String ATTR_ID = "id";
Amith Yamasani920ace02012-09-20 22:15:37 -0700132 private static final String ATTR_CREATION_TIME = "created";
133 private static final String ATTR_LAST_LOGGED_IN_TIME = "lastLoggedIn";
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -0600134 private static final String ATTR_LAST_LOGGED_IN_FINGERPRINT = "lastLoggedInFingerprint";
Amith Yamasani2a003292012-08-14 18:25:45 -0700135 private static final String ATTR_SERIAL_NO = "serialNumber";
136 private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber";
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700137 private static final String ATTR_PARTIAL = "partial";
Adam Lesinskieddeb492014-09-08 17:50:03 -0700138 private static final String ATTR_GUEST_TO_REMOVE = "guestToRemove";
Amith Yamasani6f34b412012-10-22 18:19:27 -0700139 private static final String ATTR_USER_VERSION = "version";
Kenny Guy2a764942014-04-02 13:29:20 +0100140 private static final String ATTR_PROFILE_GROUP_ID = "profileGroupId";
Fyodor Kupolov06a484a2015-08-21 16:33:20 -0700141 private static final String ATTR_RESTRICTED_PROFILE_PARENT_ID = "restrictedProfileParentId";
Amith Yamasani12747872015-12-07 14:19:49 -0800142 private static final String ATTR_SEED_ACCOUNT_NAME = "seedAccountName";
143 private static final String ATTR_SEED_ACCOUNT_TYPE = "seedAccountType";
Amith Yamasanie4afaa32014-06-30 14:55:07 +0530144 private static final String TAG_GUEST_RESTRICTIONS = "guestRestrictions";
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700145 private static final String TAG_USERS = "users";
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700146 private static final String TAG_USER = "user";
Amith Yamasanie4cf7342012-12-17 11:12:09 -0800147 private static final String TAG_RESTRICTIONS = "restrictions";
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800148 private static final String TAG_DEVICE_POLICY_RESTRICTIONS = "device_policy_restrictions";
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +0100149 private static final String TAG_GLOBAL_RESTRICTION_OWNER_ID = "globalRestrictionOwnerUserId";
Amith Yamasanidf2e92a2013-03-01 17:04:38 -0800150 private static final String TAG_ENTRY = "entry";
151 private static final String TAG_VALUE = "value";
Amith Yamasani12747872015-12-07 14:19:49 -0800152 private static final String TAG_SEED_ACCOUNT_OPTIONS = "seedAccountOptions";
Amith Yamasanidf2e92a2013-03-01 17:04:38 -0800153 private static final String ATTR_KEY = "key";
Amith Yamasani7e99bc02013-04-16 18:24:51 -0700154 private static final String ATTR_VALUE_TYPE = "type";
Amith Yamasanidf2e92a2013-03-01 17:04:38 -0800155 private static final String ATTR_MULTIPLE = "m";
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700156
Amith Yamasani7e99bc02013-04-16 18:24:51 -0700157 private static final String ATTR_TYPE_STRING_ARRAY = "sa";
158 private static final String ATTR_TYPE_STRING = "s";
159 private static final String ATTR_TYPE_BOOLEAN = "b";
Amith Yamasani5b5aa402014-06-01 20:10:14 -0700160 private static final String ATTR_TYPE_INTEGER = "i";
Fyodor Kupolov262f9952015-03-23 18:55:11 -0700161 private static final String ATTR_TYPE_BUNDLE = "B";
162 private static final String ATTR_TYPE_BUNDLE_ARRAY = "BA";
Amith Yamasani7e99bc02013-04-16 18:24:51 -0700163
Amith Yamasani0b285492011-04-14 17:35:23 -0700164 private static final String USER_INFO_DIR = "system" + File.separator + "users";
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700165 private static final String USER_LIST_FILENAME = "userlist.xml";
Amith Yamasanib8151ec2012-04-18 18:02:48 -0700166 private static final String USER_PHOTO_FILENAME = "photo.png";
Adrian Roos1bdff912015-02-17 15:51:35 +0100167 private static final String USER_PHOTO_FILENAME_TMP = USER_PHOTO_FILENAME + ".tmp";
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700168
Amith Yamasanidf2e92a2013-03-01 17:04:38 -0800169 private static final String RESTRICTIONS_FILE_PREFIX = "res_";
Amith Yamasanifc95e702013-09-26 13:20:17 -0700170 private static final String XML_SUFFIX = ".xml";
Amith Yamasanidf2e92a2013-03-01 17:04:38 -0800171
Amith Yamasani634cf312012-10-04 17:34:21 -0700172 private static final int MIN_USER_ID = 10;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700173 // We need to keep process uid within Integer.MAX_VALUE.
174 private static final int MAX_USER_ID = Integer.MAX_VALUE / UserHandle.PER_USER_RANGE;
Amith Yamasani634cf312012-10-04 17:34:21 -0700175
Fyodor Kupolov1c363152015-09-02 13:27:21 -0700176 private static final int USER_VERSION = 6;
Amith Yamasani6f34b412012-10-22 18:19:27 -0700177
Amith Yamasani920ace02012-09-20 22:15:37 -0700178 private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // ms
179
Nicolas Prevotb8186812015-08-06 15:00:03 +0100180 // Maximum number of managed profiles permitted per user is 1. This cannot be increased
Amith Yamasani95ab7842014-08-11 17:09:26 -0700181 // without first making sure that the rest of the framework is prepared for it.
182 private static final int MAX_MANAGED_PROFILES = 1;
183
Fyodor Kupolov75d0ea82014-12-15 16:21:07 -0800184 static final int WRITE_USER_MSG = 1;
185 static final int WRITE_USER_DELAY = 2*1000; // 2 seconds
Amith Yamasanie4afaa32014-06-30 14:55:07 +0530186
Jeff Sharkey6dce4962015-07-03 18:08:41 -0700187 private static final String XATTR_SERIAL = "user.serial";
188
Fyodor Kupolov8385e4b2015-12-29 18:15:32 -0800189 // Tron counters
190 private static final String TRON_GUEST_CREATED = "users_guest_created";
191 private static final String TRON_USER_CREATED = "users_user_created";
192
Dianne Hackborn4428e172012-08-24 17:43:05 -0700193 private final Context mContext;
194 private final PackageManagerService mPm;
Dianne Hackborn4428e172012-08-24 17:43:05 -0700195 private final Object mPackagesLock;
Fyodor Kupolov82402752015-10-28 14:54:51 -0700196 // Short-term lock for internal state, when interaction/sync with PM is not required
197 private final Object mUsersLock = new Object();
198 private final Object mRestrictionsLock = new Object();
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700199
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -0800200 private final Handler mHandler;
201
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700202 private final File mUsersDir;
203 private final File mUserListFile;
Dianne Hackborn4428e172012-08-24 17:43:05 -0700204
Svet Ganov9cea80cd2016-02-16 11:47:00 -0800205 private static final IBinder mUserRestriconToken = new Binder();
206
Makoto Onuki068c54a2015-10-13 14:34:03 -0700207 /**
Amith Yamasani12747872015-12-07 14:19:49 -0800208 * User-related information that is used for persisting to flash. Only UserInfo is
209 * directly exposed to other system apps.
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800210 */
Amith Yamasani12747872015-12-07 14:19:49 -0800211 private static class UserData {
212 // Basic user information and properties
213 UserInfo info;
214 // Account name used when there is a strong association between a user and an account
215 String account;
216 // Account information for seeding into a newly created user. This could also be
217 // used for login validation for an existing user, for updating their credentials.
218 // In the latter case, data may not need to be persisted as it is only valid for the
219 // current login session.
220 String seedAccountName;
221 String seedAccountType;
222 PersistableBundle seedAccountOptions;
223 // Whether to perist the seed account information to be available after a boot
224 boolean persistSeedData;
225
226 void clearSeedAccountData() {
227 seedAccountName = null;
228 seedAccountType = null;
229 seedAccountOptions = null;
230 persistSeedData = false;
231 }
232 }
233
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800234 @GuardedBy("mUsersLock")
Amith Yamasani12747872015-12-07 14:19:49 -0800235 private final SparseArray<UserData> mUsers = new SparseArray<>();
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800236
237 /**
Makoto Onuki068c54a2015-10-13 14:34:03 -0700238 * User restrictions set via UserManager. This doesn't include restrictions set by
239 * device owner / profile owners.
240 *
241 * DO NOT Change existing {@link Bundle} in it. When changing a restriction for a user,
242 * a new {@link Bundle} should always be created and set. This is because a {@link Bundle}
243 * maybe shared between {@link #mBaseUserRestrictions} and
244 * {@link #mCachedEffectiveUserRestrictions}, but they should always updated separately.
245 * (Otherwise we won't be able to detect what restrictions have changed in
Fyodor Kupolov82402752015-10-28 14:54:51 -0700246 * {@link #updateUserRestrictionsInternalLR}.
Makoto Onuki068c54a2015-10-13 14:34:03 -0700247 */
248 @GuardedBy("mRestrictionsLock")
249 private final SparseArray<Bundle> mBaseUserRestrictions = new SparseArray<>();
250
251 /**
252 * Cached user restrictions that are in effect -- i.e. {@link #mBaseUserRestrictions} combined
253 * with device / profile owner restrictions. We'll initialize it lazily; use
254 * {@link #getEffectiveUserRestrictions} to access it.
255 *
256 * DO NOT Change existing {@link Bundle} in it. When changing a restriction for a user,
257 * a new {@link Bundle} should always be created and set. This is because a {@link Bundle}
258 * maybe shared between {@link #mBaseUserRestrictions} and
259 * {@link #mCachedEffectiveUserRestrictions}, but they should always updated separately.
260 * (Otherwise we won't be able to detect what restrictions have changed in
Fyodor Kupolov82402752015-10-28 14:54:51 -0700261 * {@link #updateUserRestrictionsInternalLR}.
Makoto Onuki068c54a2015-10-13 14:34:03 -0700262 */
263 @GuardedBy("mRestrictionsLock")
264 private final SparseArray<Bundle> mCachedEffectiveUserRestrictions = new SparseArray<>();
265
Makoto Onuki4f160732015-10-27 17:15:38 -0700266 /**
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800267 * User restrictions that have already been applied in
268 * {@link #updateUserRestrictionsInternalLR(Bundle, int)}. We use it to detect restrictions
269 * that have changed since the last
270 * {@link #updateUserRestrictionsInternalLR(Bundle, int)} call.
Makoto Onuki4f160732015-10-27 17:15:38 -0700271 */
272 @GuardedBy("mRestrictionsLock")
273 private final SparseArray<Bundle> mAppliedUserRestrictions = new SparseArray<>();
274
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800275 /**
Makoto Onukie7927da2015-11-25 10:05:17 -0800276 * User restrictions set by {@link com.android.server.devicepolicy.DevicePolicyManagerService}
277 * that should be applied to all users, including guests.
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800278 */
279 @GuardedBy("mRestrictionsLock")
280 private Bundle mDevicePolicyGlobalUserRestrictions;
281
282 /**
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +0100283 * Id of the user that set global restrictions.
284 */
285 @GuardedBy("mRestrictionsLock")
286 private int mGlobalRestrictionOwnerUserId = UserHandle.USER_NULL;
287
288 /**
Makoto Onukie7927da2015-11-25 10:05:17 -0800289 * User restrictions set by {@link com.android.server.devicepolicy.DevicePolicyManagerService}
290 * for each user.
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800291 */
292 @GuardedBy("mRestrictionsLock")
293 private final SparseArray<Bundle> mDevicePolicyLocalUserRestrictions = new SparseArray<>();
294
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800295 @GuardedBy("mGuestRestrictions")
Amith Yamasanie4afaa32014-06-30 14:55:07 +0530296 private final Bundle mGuestRestrictions = new Bundle();
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -0800297
298 /**
299 * Set of user IDs being actively removed. Removed IDs linger in this set
300 * for several seconds to work around a VFS caching issue.
301 */
Fyodor Kupolov82402752015-10-28 14:54:51 -0700302 @GuardedBy("mUsersLock")
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -0800303 private final SparseBooleanArray mRemovingUserIds = new SparseBooleanArray();
Dianne Hackborn4428e172012-08-24 17:43:05 -0700304
Fyodor Kupolov82402752015-10-28 14:54:51 -0700305 @GuardedBy("mUsersLock")
Amith Yamasani0b285492011-04-14 17:35:23 -0700306 private int[] mUserIds;
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800307 @GuardedBy("mPackagesLock")
Amith Yamasani2a003292012-08-14 18:25:45 -0700308 private int mNextSerialNumber;
Amith Yamasani6f34b412012-10-22 18:19:27 -0700309 private int mUserVersion = 0;
Amith Yamasani0b285492011-04-14 17:35:23 -0700310
Jason Monk62062992014-05-06 09:55:28 -0400311 private IAppOpsService mAppOpsService;
312
Makoto Onuki068c54a2015-10-13 14:34:03 -0700313 private final LocalService mLocalService;
314
Makoto Onukie7927da2015-11-25 10:05:17 -0800315 @GuardedBy("mUsersLock")
316 private boolean mIsDeviceManaged;
317
318 @GuardedBy("mUsersLock")
319 private final SparseBooleanArray mIsUserManaged = new SparseBooleanArray();
320
Makoto Onukid45a4a22015-11-02 17:17:38 -0800321 @GuardedBy("mUserRestrictionsListeners")
322 private final ArrayList<UserRestrictionsListener> mUserRestrictionsListeners =
323 new ArrayList<>();
324
Clara Bayarria1771112015-12-18 16:29:18 +0000325 private final LockPatternUtils mLockPatternUtils;
326
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +0100327 /**
328 * Whether all users should be created ephemeral.
329 */
330 @GuardedBy("mUsersLock")
331 private boolean mForceEphemeralUsers;
332
Amith Yamasani258848d2012-08-10 17:06:33 -0700333 private static UserManagerService sInstance;
Amith Yamasani258848d2012-08-10 17:06:33 -0700334
Dianne Hackborn4428e172012-08-24 17:43:05 -0700335 public static UserManagerService getInstance() {
336 synchronized (UserManagerService.class) {
337 return sInstance;
Amith Yamasani258848d2012-08-10 17:06:33 -0700338 }
Amith Yamasani258848d2012-08-10 17:06:33 -0700339 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700340
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800341 @VisibleForTesting
342 UserManagerService(File dataDir) {
343 this(null, null, new Object(), dataDir);
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700344 }
345
Dianne Hackborn4428e172012-08-24 17:43:05 -0700346 /**
347 * Called by package manager to create the service. This is closely
348 * associated with the package manager, and the given lock is the
349 * package manager's own lock.
350 */
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800351 UserManagerService(Context context, PackageManagerService pm, Object packagesLock) {
352 this(context, pm, packagesLock, Environment.getDataDirectory());
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700353 }
354
Dianne Hackborn4428e172012-08-24 17:43:05 -0700355 private UserManagerService(Context context, PackageManagerService pm,
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800356 Object packagesLock, File dataDir) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700357 mContext = context;
358 mPm = pm;
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700359 mPackagesLock = packagesLock;
Fyodor Kupolov75d0ea82014-12-15 16:21:07 -0800360 mHandler = new MainHandler();
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800361 synchronized (mPackagesLock) {
362 mUsersDir = new File(dataDir, USER_INFO_DIR);
363 mUsersDir.mkdirs();
364 // Make zeroth user directory, for services to migrate their files to that location
365 File userZeroDir = new File(mUsersDir, String.valueOf(UserHandle.USER_SYSTEM));
366 userZeroDir.mkdirs();
367 FileUtils.setPermissions(mUsersDir.toString(),
368 FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IROTH | FileUtils.S_IXOTH,
369 -1, -1);
370 mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
371 initDefaultGuestRestrictions();
372 readUserListLP();
373 sInstance = this;
Xiaohui Chen4be96e42015-05-06 09:55:43 -0700374 }
Makoto Onuki068c54a2015-10-13 14:34:03 -0700375 mLocalService = new LocalService();
376 LocalServices.addService(UserManagerInternal.class, mLocalService);
Clara Bayarria1771112015-12-18 16:29:18 +0000377 mLockPatternUtils = new LockPatternUtils(mContext);
Xiaohui Chen4be96e42015-05-06 09:55:43 -0700378 }
379
380 void systemReady() {
Lenka Trochtovac4dd0212015-11-18 12:22:06 +0100381 // Prune out any partially created, partially removed and ephemeral users.
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800382 ArrayList<UserInfo> partials = new ArrayList<>();
383 synchronized (mUsersLock) {
384 final int userSize = mUsers.size();
385 for (int i = 0; i < userSize; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -0800386 UserInfo ui = mUsers.valueAt(i).info;
Lenka Trochtovac4dd0212015-11-18 12:22:06 +0100387 if ((ui.partial || ui.guestToRemove || ui.isEphemeral()) && i != 0) {
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800388 partials.add(ui);
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700389 }
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700390 }
Dianne Hackborn4428e172012-08-24 17:43:05 -0700391 }
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800392 final int partialsSize = partials.size();
393 for (int i = 0; i < partialsSize; i++) {
394 UserInfo ui = partials.get(i);
395 Slog.w(LOG_TAG, "Removing partially created user " + ui.id
396 + " (name=" + ui.name + ")");
397 removeUserState(ui.id);
398 }
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800399
Jason Monk62062992014-05-06 09:55:28 -0400400 mAppOpsService = IAppOpsService.Stub.asInterface(
401 ServiceManager.getService(Context.APP_OPS_SERVICE));
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800402
403 synchronized (mRestrictionsLock) {
404 applyUserRestrictionsLR(UserHandle.USER_SYSTEM);
Jason Monk62062992014-05-06 09:55:28 -0400405 }
Samuel Tand9453b82016-03-14 15:57:02 -0700406
407 UserInfo currentGuestUser = findCurrentGuestUser();
408 if (currentGuestUser != null && !hasUserRestriction(
409 UserManager.DISALLOW_CONFIG_WIFI, currentGuestUser.id)) {
410 // If a guest user currently exists, apply the DISALLOW_CONFIG_WIFI option
411 // to it, in case this guest was created in a previous version where this
412 // user restriction was not a default guest restriction.
413 setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true, currentGuestUser.id);
414 }
Amith Yamasani258848d2012-08-10 17:06:33 -0700415 }
416
417 @Override
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800418 public String getUserAccount(int userId) {
419 checkManageUserAndAcrossUsersFullPermission("get user account");
420 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -0800421 return mUsers.get(userId).account;
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800422 }
423 }
424
425 @Override
426 public void setUserAccount(int userId, String accountName) {
427 checkManageUserAndAcrossUsersFullPermission("set user account");
Amith Yamasani12747872015-12-07 14:19:49 -0800428 UserData userToUpdate = null;
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800429 synchronized (mPackagesLock) {
430 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -0800431 final UserData userData = mUsers.get(userId);
432 if (userData == null) {
433 Slog.e(LOG_TAG, "User not found for setting user account: u" + userId);
434 return;
435 }
436 String currentAccount = userData.account;
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800437 if (!Objects.equal(currentAccount, accountName)) {
Amith Yamasani12747872015-12-07 14:19:49 -0800438 userData.account = accountName;
439 userToUpdate = userData;
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800440 }
441 }
442
443 if (userToUpdate != null) {
444 writeUserLP(userToUpdate);
445 }
446 }
447 }
448
449 @Override
Xiaohui Chen70f6c382015-04-28 14:21:43 -0700450 public UserInfo getPrimaryUser() {
451 checkManageUsersPermission("query users");
Fyodor Kupolov82402752015-10-28 14:54:51 -0700452 synchronized (mUsersLock) {
Amith Yamasani515d4062015-09-28 11:30:06 -0700453 final int userSize = mUsers.size();
454 for (int i = 0; i < userSize; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -0800455 UserInfo ui = mUsers.valueAt(i).info;
Xiaohui Chend3e9e182015-11-18 13:37:32 -0800456 if (ui.isPrimary() && !mRemovingUserIds.get(ui.id)) {
Xiaohui Chen70f6c382015-04-28 14:21:43 -0700457 return ui;
458 }
459 }
460 }
461 return null;
462 }
463
464 @Override
Xiaohui Chen594f2082015-08-18 11:04:20 -0700465 public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
Amith Yamasani2a003292012-08-14 18:25:45 -0700466 checkManageUsersPermission("query users");
Fyodor Kupolov82402752015-10-28 14:54:51 -0700467 synchronized (mUsersLock) {
Amith Yamasani13593602012-03-22 16:16:17 -0700468 ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
Amith Yamasani515d4062015-09-28 11:30:06 -0700469 final int userSize = mUsers.size();
470 for (int i = 0; i < userSize; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -0800471 UserInfo ui = mUsers.valueAt(i).info;
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700472 if (ui.partial) {
473 continue;
474 }
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -0800475 if (!excludeDying || !mRemovingUserIds.get(ui.id)) {
Amith Yamasani6f48d6e2016-03-23 14:28:25 -0700476 users.add(userWithName(ui));
Amith Yamasani920ace02012-09-20 22:15:37 -0700477 }
Amith Yamasani13593602012-03-22 16:16:17 -0700478 }
479 return users;
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700480 }
Amith Yamasani13593602012-03-22 16:16:17 -0700481 }
482
Amith Yamasani258848d2012-08-10 17:06:33 -0700483 @Override
Alexandra Gherghina385124d2014-04-03 13:37:39 +0100484 public List<UserInfo> getProfiles(int userId, boolean enabledOnly) {
Fyodor Kupolovc533b562016-04-01 14:37:07 -0700485 boolean returnFullInfo = true;
Amith Yamasani4f582632014-02-19 14:31:52 -0800486 if (userId != UserHandle.getCallingUserId()) {
487 checkManageUsersPermission("getting profiles related to user " + userId);
Fyodor Kupolovc533b562016-04-01 14:37:07 -0700488 } else {
489 returnFullInfo = hasManageUsersPermission();
Amith Yamasani4f582632014-02-19 14:31:52 -0800490 }
Amith Yamasanibe465322014-04-24 13:45:17 -0700491 final long ident = Binder.clearCallingIdentity();
492 try {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700493 synchronized (mUsersLock) {
Fyodor Kupolovc533b562016-04-01 14:37:07 -0700494 return getProfilesLU(userId, enabledOnly, returnFullInfo);
Alexandra Gherghina385124d2014-04-03 13:37:39 +0100495 }
Amith Yamasanibe465322014-04-24 13:45:17 -0700496 } finally {
497 Binder.restoreCallingIdentity(ident);
Kenny Guya52dc3e2014-02-11 15:33:14 +0000498 }
499 }
500
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700501 @Override
502 public int[] getProfileIds(int userId, boolean enabledOnly) {
503 if (userId != UserHandle.getCallingUserId()) {
504 checkManageUsersPermission("getting profiles related to user " + userId);
505 }
506 final long ident = Binder.clearCallingIdentity();
507 try {
508 synchronized (mUsersLock) {
509 return getProfileIdsLU(userId, enabledOnly).toArray();
510 }
511 } finally {
512 Binder.restoreCallingIdentity(ident);
513 }
514 }
515
Amith Yamasanibe465322014-04-24 13:45:17 -0700516 /** Assume permissions already checked and caller's identity cleared */
Fyodor Kupolovc533b562016-04-01 14:37:07 -0700517 private List<UserInfo> getProfilesLU(int userId, boolean enabledOnly, boolean fullInfo) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700518 IntArray profileIds = getProfileIdsLU(userId, enabledOnly);
519 ArrayList<UserInfo> users = new ArrayList<>(profileIds.size());
520 for (int i = 0; i < profileIds.size(); i++) {
521 int profileId = profileIds.get(i);
522 UserInfo userInfo = mUsers.get(profileId).info;
523 // If full info is not required - clear PII data to prevent 3P apps from reading it
524 if (!fullInfo) {
525 userInfo = new UserInfo(userInfo);
526 userInfo.name = null;
527 userInfo.iconPath = null;
528 } else {
529 userInfo = userWithName(userInfo);
530 }
531 users.add(userInfo);
532 }
533 return users;
534 }
535
536 /**
537 * Assume permissions already checked and caller's identity cleared
538 */
539 private IntArray getProfileIdsLU(int userId, boolean enabledOnly) {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700540 UserInfo user = getUserInfoLU(userId);
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700541 IntArray result = new IntArray(mUsers.size());
Amith Yamasanidda003f2014-08-28 18:06:51 -0700542 if (user == null) {
543 // Probably a dying user
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700544 return result;
Amith Yamasanidda003f2014-08-28 18:06:51 -0700545 }
Amith Yamasani515d4062015-09-28 11:30:06 -0700546 final int userSize = mUsers.size();
547 for (int i = 0; i < userSize; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -0800548 UserInfo profile = mUsers.valueAt(i).info;
Amith Yamasanibe465322014-04-24 13:45:17 -0700549 if (!isProfileOf(user, profile)) {
550 continue;
551 }
Alexandra Gherghinadf35d572014-04-09 13:54:39 +0100552 if (enabledOnly && !profile.isEnabled()) {
553 continue;
Amith Yamasanibe465322014-04-24 13:45:17 -0700554 }
Amith Yamasani70fcf0c2014-07-11 08:40:19 -0700555 if (mRemovingUserIds.get(profile.id)) {
556 continue;
557 }
Tony Mak80189cd2016-04-05 17:21:42 +0100558 if (profile.partial) {
559 continue;
560 }
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700561 result.add(profile.id);
Amith Yamasanibe465322014-04-24 13:45:17 -0700562 }
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700563 return result;
Amith Yamasanibe465322014-04-24 13:45:17 -0700564 }
565
Jessica Hummelbe81c802014-04-22 15:49:22 +0100566 @Override
Andres Moralesc5548c02015-08-05 10:23:12 -0700567 public int getCredentialOwnerProfile(int userHandle) {
568 checkManageUsersPermission("get the credential owner");
Clara Bayarria1771112015-12-18 16:29:18 +0000569 if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle)) {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700570 synchronized (mUsersLock) {
571 UserInfo profileParent = getProfileParentLU(userHandle);
Andres Moralesc5548c02015-08-05 10:23:12 -0700572 if (profileParent != null) {
573 return profileParent.id;
574 }
575 }
576 }
577
578 return userHandle;
579 }
580
581 @Override
Xiaohui Chenfd5b7742015-10-14 15:47:04 -0700582 public boolean isSameProfileGroup(int userId, int otherUserId) {
583 if (userId == otherUserId) return true;
584 checkManageUsersPermission("check if in the same profile group");
585 synchronized (mPackagesLock) {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700586 return isSameProfileGroupLP(userId, otherUserId);
Xiaohui Chenfd5b7742015-10-14 15:47:04 -0700587 }
588 }
589
Fyodor Kupolov82402752015-10-28 14:54:51 -0700590 private boolean isSameProfileGroupLP(int userId, int otherUserId) {
591 synchronized (mUsersLock) {
592 UserInfo userInfo = getUserInfoLU(userId);
593 if (userInfo == null || userInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
594 return false;
595 }
596 UserInfo otherUserInfo = getUserInfoLU(otherUserId);
597 if (otherUserInfo == null
598 || otherUserInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
599 return false;
600 }
601 return userInfo.profileGroupId == otherUserInfo.profileGroupId;
Xiaohui Chenfd5b7742015-10-14 15:47:04 -0700602 }
Xiaohui Chenfd5b7742015-10-14 15:47:04 -0700603 }
604
605 @Override
Jessica Hummelbe81c802014-04-22 15:49:22 +0100606 public UserInfo getProfileParent(int userHandle) {
607 checkManageUsersPermission("get the profile parent");
Fyodor Kupolov82402752015-10-28 14:54:51 -0700608 synchronized (mUsersLock) {
609 return getProfileParentLU(userHandle);
Fyodor Kupolovff7233e2015-04-08 11:28:52 -0700610 }
611 }
612
Fyodor Kupolov82402752015-10-28 14:54:51 -0700613 private UserInfo getProfileParentLU(int userHandle) {
614 UserInfo profile = getUserInfoLU(userHandle);
Fyodor Kupolovff7233e2015-04-08 11:28:52 -0700615 if (profile == null) {
616 return null;
617 }
618 int parentUserId = profile.profileGroupId;
619 if (parentUserId == UserInfo.NO_PROFILE_GROUP_ID) {
620 return null;
621 } else {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700622 return getUserInfoLU(parentUserId);
Jessica Hummelbe81c802014-04-22 15:49:22 +0100623 }
624 }
625
Fyodor Kupolov82402752015-10-28 14:54:51 -0700626 private static boolean isProfileOf(UserInfo user, UserInfo profile) {
Kenny Guy2a764942014-04-02 13:29:20 +0100627 return user.id == profile.id ||
628 (user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
629 && user.profileGroupId == profile.profileGroupId);
Kenny Guya52dc3e2014-02-11 15:33:14 +0000630 }
631
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000632 private void broadcastProfileAvailabilityChanges(UserHandle profileHandle,
Rubin Xuf13c9802016-01-21 18:06:00 +0000633 UserHandle parentHandle, boolean inQuietMode) {
Rubin Xue95057a2016-04-01 16:49:25 +0100634 Intent intent = new Intent();
635 if (inQuietMode) {
636 intent.setAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
637 } else {
638 intent.setAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
639 }
Rubin Xuf13c9802016-01-21 18:06:00 +0000640 intent.putExtra(Intent.EXTRA_QUIET_MODE, inQuietMode);
641 intent.putExtra(Intent.EXTRA_USER, profileHandle);
642 intent.putExtra(Intent.EXTRA_USER_HANDLE, profileHandle.getIdentifier());
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000643 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Rubin Xuf13c9802016-01-21 18:06:00 +0000644 mContext.sendBroadcastAsUser(intent, parentHandle);
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000645 }
646
647 @Override
648 public void setQuietModeEnabled(int userHandle, boolean enableQuietMode) {
649 checkManageUsersPermission("silence profile");
650 boolean changed = false;
651 UserInfo profile, parent;
652 synchronized (mPackagesLock) {
653 synchronized (mUsersLock) {
654 profile = getUserInfoLU(userHandle);
655 parent = getProfileParentLU(userHandle);
656
657 }
658 if (profile == null || !profile.isManagedProfile()) {
659 throw new IllegalArgumentException("User " + userHandle + " is not a profile");
660 }
661 if (profile.isQuietModeEnabled() != enableQuietMode) {
662 profile.flags ^= UserInfo.FLAG_QUIET_MODE;
Amith Yamasani12747872015-12-07 14:19:49 -0800663 writeUserLP(getUserDataLU(profile.id));
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000664 changed = true;
665 }
666 }
667 if (changed) {
Rubin Xuf13c9802016-01-21 18:06:00 +0000668 long identity = Binder.clearCallingIdentity();
669 try {
670 if (enableQuietMode) {
Rubin Xuf8451b92016-04-01 15:50:58 +0100671 LocalServices.getService(ActivityManagerInternal.class)
672 .killForegroundAppsForUser(userHandle);
Rubin Xuf13c9802016-01-21 18:06:00 +0000673 ActivityManagerNative.getDefault().stopUser(userHandle, /* force */true, null);
674 } else {
675 ActivityManagerNative.getDefault().startUserInBackground(userHandle);
676 }
677 } catch (RemoteException e) {
678 Slog.e(LOG_TAG, "fail to start/stop user for quiet mode", e);
679 } finally {
680 Binder.restoreCallingIdentity(identity);
681 }
682
683 broadcastProfileAvailabilityChanges(profile.getUserHandle(), parent.getUserHandle(),
684 enableQuietMode);
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000685 }
686 }
687
688 @Override
689 public boolean isQuietModeEnabled(int userHandle) {
690 synchronized (mPackagesLock) {
691 UserInfo info;
692 synchronized (mUsersLock) {
693 info = getUserInfoLU(userHandle);
694 }
695 if (info == null || !info.isManagedProfile()) {
Rubin Xuf13c9802016-01-21 18:06:00 +0000696 return false;
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000697 }
698 return info.isQuietModeEnabled();
699 }
700 }
701
Kenny Guya52dc3e2014-02-11 15:33:14 +0000702 @Override
Benjamin Franzf02420c2016-04-04 18:52:21 +0100703 public boolean trySetQuietModeDisabled(int userHandle, IntentSender target) {
704 if (mContext.getSystemService(StorageManager.class).isUserKeyUnlocked(userHandle)
705 || !mLockPatternUtils.isSecure(userHandle)
706 || !mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle)) {
707 // if the user is already unlocked, no need to show a profile challenge
708 setQuietModeEnabled(userHandle, false);
709 return true;
710 }
711
712 long identity = Binder.clearCallingIdentity();
713 try {
714 // otherwise, we show a profile challenge to trigger decryption of the user
715 final KeyguardManager km = (KeyguardManager) mContext.getSystemService(
716 Context.KEYGUARD_SERVICE);
717 final Intent unlockIntent = km.createConfirmDeviceCredentialIntent(null, null,
718 userHandle);
719 if (unlockIntent == null) {
720 return false;
721 }
722 if (target != null) {
723 unlockIntent.putExtra(Intent.EXTRA_INTENT, target);
724 }
725 unlockIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
726 mContext.startActivity(unlockIntent);
727 } finally {
728 Binder.restoreCallingIdentity(identity);
729 }
730 return false;
731 }
732
733 @Override
Alexandra Gherghinadf35d572014-04-09 13:54:39 +0100734 public void setUserEnabled(int userId) {
735 checkManageUsersPermission("enable user");
736 synchronized (mPackagesLock) {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700737 UserInfo info;
738 synchronized (mUsersLock) {
739 info = getUserInfoLU(userId);
740 }
Alexandra Gherghinadf35d572014-04-09 13:54:39 +0100741 if (info != null && !info.isEnabled()) {
742 info.flags ^= UserInfo.FLAG_DISABLED;
Amith Yamasani12747872015-12-07 14:19:49 -0800743 writeUserLP(getUserDataLU(info.id));
Alexandra Gherghinadf35d572014-04-09 13:54:39 +0100744 }
745 }
746 }
747
748 @Override
Amith Yamasani258848d2012-08-10 17:06:33 -0700749 public UserInfo getUserInfo(int userId) {
Tony Mak8673b282016-03-21 21:10:59 +0000750 checkManageUsersPermission("query user");
751 synchronized (mUsersLock) {
Amith Yamasani6f48d6e2016-03-23 14:28:25 -0700752 return userWithName(getUserInfoLU(userId));
753 }
754 }
755
756 /**
757 * Returns a UserInfo object with the name filled in, for Owner, or the original
758 * if the name is already set.
759 */
760 private UserInfo userWithName(UserInfo orig) {
761 if (orig != null && orig.name == null && orig.id == UserHandle.USER_SYSTEM) {
762 UserInfo withName = new UserInfo(orig);
763 withName.name = getOwnerName();
764 return withName;
765 } else {
766 return orig;
Tony Mak8673b282016-03-21 21:10:59 +0000767 }
768 }
769
770 @Override
771 public boolean isManagedProfile(int userId) {
Tony Makb531d082016-03-16 14:49:52 +0000772 int callingUserId = UserHandle.getCallingUserId();
773 if (callingUserId != userId && !hasManageUsersPermission()) {
774 synchronized (mPackagesLock) {
775 if (!isSameProfileGroupLP(callingUserId, userId)) {
776 throw new SecurityException(
Tony Mak8673b282016-03-21 21:10:59 +0000777 "You need MANAGE_USERS permission to: check if specified user a " +
778 "managed profile outside your profile group");
Tony Makb531d082016-03-16 14:49:52 +0000779 }
780 }
Tony Mak4dc008c2016-03-16 10:46:49 +0000781 }
Fyodor Kupolov82402752015-10-28 14:54:51 -0700782 synchronized (mUsersLock) {
Tony Mak8673b282016-03-21 21:10:59 +0000783 UserInfo userInfo = getUserInfoLU(userId);
784 return userInfo != null && userInfo.isManagedProfile();
Amith Yamasani13593602012-03-22 16:16:17 -0700785 }
786 }
787
Amith Yamasani71e6c692013-03-24 17:39:28 -0700788 @Override
789 public boolean isRestricted() {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700790 synchronized (mUsersLock) {
791 return getUserInfoLU(UserHandle.getCallingUserId()).isRestricted();
Amith Yamasani71e6c692013-03-24 17:39:28 -0700792 }
793 }
794
Fyodor Kupolov1c363152015-09-02 13:27:21 -0700795 @Override
796 public boolean canHaveRestrictedProfile(int userId) {
797 checkManageUsersPermission("canHaveRestrictedProfile");
Fyodor Kupolov82402752015-10-28 14:54:51 -0700798 synchronized (mUsersLock) {
799 final UserInfo userInfo = getUserInfoLU(userId);
Fyodor Kupolov1c363152015-09-02 13:27:21 -0700800 if (userInfo == null || !userInfo.canHaveProfile()) {
801 return false;
802 }
803 if (!userInfo.isAdmin()) {
804 return false;
805 }
Makoto Onukie7927da2015-11-25 10:05:17 -0800806 // restricted profile can be created if there is no DO set and the admin user has no PO;
807 return !mIsDeviceManaged && !mIsUserManaged.get(userId);
Fyodor Kupolov1c363152015-09-02 13:27:21 -0700808 }
Fyodor Kupolov1c363152015-09-02 13:27:21 -0700809 }
810
Amith Yamasani195263742012-08-21 15:40:12 -0700811 /*
812 * Should be locked on mUsers before calling this.
813 */
Fyodor Kupolov82402752015-10-28 14:54:51 -0700814 private UserInfo getUserInfoLU(int userId) {
Amith Yamasani12747872015-12-07 14:19:49 -0800815 final UserData userData = mUsers.get(userId);
Amith Yamasani16389312012-10-17 21:20:14 -0700816 // If it is partial and not in the process of being removed, return as unknown user.
Amith Yamasani12747872015-12-07 14:19:49 -0800817 if (userData != null && userData.info.partial && !mRemovingUserIds.get(userId)) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700818 Slog.w(LOG_TAG, "getUserInfo: unknown user #" + userId);
819 return null;
820 }
Amith Yamasani12747872015-12-07 14:19:49 -0800821 return userData != null ? userData.info : null;
822 }
823
824 private UserData getUserDataLU(int userId) {
825 final UserData userData = mUsers.get(userId);
826 // If it is partial and not in the process of being removed, return as unknown user.
827 if (userData != null && userData.info.partial && !mRemovingUserIds.get(userId)) {
828 return null;
829 }
830 return userData;
Amith Yamasani195263742012-08-21 15:40:12 -0700831 }
832
Fyodor Kupolov82402752015-10-28 14:54:51 -0700833 /**
834 * Obtains {@link #mUsersLock} and return UserInfo from mUsers.
835 * <p>No permissions checking or any addition checks are made</p>
836 */
837 private UserInfo getUserInfoNoChecks(int userId) {
838 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -0800839 final UserData userData = mUsers.get(userId);
840 return userData != null ? userData.info : null;
841 }
842 }
843
844 /**
845 * Obtains {@link #mUsersLock} and return UserData from mUsers.
846 * <p>No permissions checking or any addition checks are made</p>
847 */
848 private UserData getUserDataNoChecks(int userId) {
849 synchronized (mUsersLock) {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700850 return mUsers.get(userId);
851 }
852 }
853
Amith Yamasani236b2b52015-08-18 14:32:14 -0700854 /** Called by PackageManagerService */
Amith Yamasani13593602012-03-22 16:16:17 -0700855 public boolean exists(int userId) {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700856 return getUserInfoNoChecks(userId) != null;
Amith Yamasani13593602012-03-22 16:16:17 -0700857 }
858
Amith Yamasani258848d2012-08-10 17:06:33 -0700859 @Override
Amith Yamasanib8151ec2012-04-18 18:02:48 -0700860 public void setUserName(int userId, String name) {
Amith Yamasani2a003292012-08-14 18:25:45 -0700861 checkManageUsersPermission("rename users");
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700862 boolean changed = false;
Dianne Hackborn4428e172012-08-24 17:43:05 -0700863 synchronized (mPackagesLock) {
Amith Yamasani12747872015-12-07 14:19:49 -0800864 UserData userData = getUserDataNoChecks(userId);
865 if (userData == null || userData.info.partial) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700866 Slog.w(LOG_TAG, "setUserName: unknown user #" + userId);
867 return;
868 }
Amith Yamasani12747872015-12-07 14:19:49 -0800869 if (name != null && !name.equals(userData.info.name)) {
870 userData.info.name = name;
871 writeUserLP(userData);
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700872 changed = true;
Amith Yamasani13593602012-03-22 16:16:17 -0700873 }
874 }
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700875 if (changed) {
876 sendUserInfoChangedBroadcast(userId);
877 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700878 }
879
Amith Yamasani258848d2012-08-10 17:06:33 -0700880 @Override
Amith Yamasanie928d7d2012-09-17 21:46:51 -0700881 public void setUserIcon(int userId, Bitmap bitmap) {
Amith Yamasani2a003292012-08-14 18:25:45 -0700882 checkManageUsersPermission("update users");
Oleksandr Peletskyi7f1f1df2016-01-18 15:40:21 +0100883 if (hasUserRestriction(UserManager.DISALLOW_SET_USER_ICON, userId)) {
884 Log.w(LOG_TAG, "Cannot set user icon. DISALLOW_SET_USER_ICON is enabled.");
885 return;
Amith Yamasanib8151ec2012-04-18 18:02:48 -0700886 }
Oleksandr Peletskyi7f1f1df2016-01-18 15:40:21 +0100887 mLocalService.setUserIcon(userId, bitmap);
Amith Yamasanie928d7d2012-09-17 21:46:51 -0700888 }
889
Oleksandr Peletskyi7f1f1df2016-01-18 15:40:21 +0100890
891
Amith Yamasanie928d7d2012-09-17 21:46:51 -0700892 private void sendUserInfoChangedBroadcast(int userId) {
893 Intent changedIntent = new Intent(Intent.ACTION_USER_INFO_CHANGED);
894 changedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
895 changedIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700896 mContext.sendBroadcastAsUser(changedIntent, UserHandle.ALL);
Amith Yamasanib8151ec2012-04-18 18:02:48 -0700897 }
898
Amith Yamasani258848d2012-08-10 17:06:33 -0700899 @Override
Oleksandr Peletskyicd6fa302016-02-25 16:28:39 +0100900 public ParcelFileDescriptor getUserIcon(int targetUserId) {
Adrian Roos1bdff912015-02-17 15:51:35 +0100901 String iconPath;
Amith Yamasani3b49f072012-09-17 10:21:43 -0700902 synchronized (mPackagesLock) {
Oleksandr Peletskyicd6fa302016-02-25 16:28:39 +0100903 UserInfo targetUserInfo = getUserInfoNoChecks(targetUserId);
904 if (targetUserInfo == null || targetUserInfo.partial) {
905 Slog.w(LOG_TAG, "getUserIcon: unknown user #" + targetUserId);
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700906 return null;
907 }
Oleksandr Peletskyicd6fa302016-02-25 16:28:39 +0100908
909 final int callingUserId = UserHandle.getCallingUserId();
910 final int callingGroupId = getUserInfoNoChecks(callingUserId).profileGroupId;
911 final int targetGroupId = targetUserInfo.profileGroupId;
912 final boolean sameGroup = (callingGroupId != UserInfo.NO_PROFILE_GROUP_ID
913 && callingGroupId == targetGroupId);
914 if ((callingUserId != targetUserId) && !sameGroup) {
Nicolas Prevot88cc3462014-05-14 14:51:48 +0100915 checkManageUsersPermission("get the icon of a user who is not related");
916 }
Oleksandr Peletskyicd6fa302016-02-25 16:28:39 +0100917
918 if (targetUserInfo.iconPath == null) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700919 return null;
920 }
Oleksandr Peletskyicd6fa302016-02-25 16:28:39 +0100921 iconPath = targetUserInfo.iconPath;
Amith Yamasani3b49f072012-09-17 10:21:43 -0700922 }
Adrian Roos1bdff912015-02-17 15:51:35 +0100923
924 try {
925 return ParcelFileDescriptor.open(
926 new File(iconPath), ParcelFileDescriptor.MODE_READ_ONLY);
927 } catch (FileNotFoundException e) {
928 Log.e(LOG_TAG, "Couldn't find icon file", e);
929 }
930 return null;
Amith Yamasani3b49f072012-09-17 10:21:43 -0700931 }
932
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700933 public void makeInitialized(int userId) {
934 checkManageUsersPermission("makeInitialized");
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800935 boolean scheduleWriteUser = false;
Amith Yamasani12747872015-12-07 14:19:49 -0800936 UserData userData;
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800937 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -0800938 userData = mUsers.get(userId);
939 if (userData == null || userData.info.partial) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700940 Slog.w(LOG_TAG, "makeInitialized: unknown user #" + userId);
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800941 return;
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700942 }
Amith Yamasani12747872015-12-07 14:19:49 -0800943 if ((userData.info.flags & UserInfo.FLAG_INITIALIZED) == 0) {
944 userData.info.flags |= UserInfo.FLAG_INITIALIZED;
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800945 scheduleWriteUser = true;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700946 }
947 }
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800948 if (scheduleWriteUser) {
Amith Yamasani12747872015-12-07 14:19:49 -0800949 scheduleWriteUser(userData);
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800950 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -0700951 }
952
Amith Yamasaniaa6634e2014-10-06 14:20:28 -0700953 /**
954 * If default guest restrictions haven't been initialized yet, add the basic
955 * restrictions.
956 */
957 private void initDefaultGuestRestrictions() {
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800958 synchronized (mGuestRestrictions) {
959 if (mGuestRestrictions.isEmpty()) {
Samuel Tand9453b82016-03-14 15:57:02 -0700960 mGuestRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_WIFI, true);
Fyodor Kupolove04462c2015-11-30 15:02:53 -0800961 mGuestRestrictions.putBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800962 mGuestRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, true);
963 mGuestRestrictions.putBoolean(UserManager.DISALLOW_SMS, true);
964 }
Amith Yamasaniaa6634e2014-10-06 14:20:28 -0700965 }
966 }
967
Amith Yamasanie4cf7342012-12-17 11:12:09 -0800968 @Override
Amith Yamasanie4afaa32014-06-30 14:55:07 +0530969 public Bundle getDefaultGuestRestrictions() {
970 checkManageUsersPermission("getDefaultGuestRestrictions");
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800971 synchronized (mGuestRestrictions) {
Amith Yamasanie4afaa32014-06-30 14:55:07 +0530972 return new Bundle(mGuestRestrictions);
973 }
974 }
975
976 @Override
977 public void setDefaultGuestRestrictions(Bundle restrictions) {
978 checkManageUsersPermission("setDefaultGuestRestrictions");
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800979 synchronized (mGuestRestrictions) {
980 mGuestRestrictions.clear();
981 mGuestRestrictions.putAll(restrictions);
982 }
983 synchronized (mPackagesLock) {
984 writeUserListLP();
Amith Yamasanie4afaa32014-06-30 14:55:07 +0530985 }
986 }
987
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800988 /**
989 * See {@link UserManagerInternal#setDevicePolicyUserRestrictions(int, Bundle, Bundle)}
990 */
Makoto Onuki2a3c3da2016-02-18 14:25:30 -0800991 void setDevicePolicyUserRestrictionsInner(int userId, @NonNull Bundle local,
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800992 @Nullable Bundle global) {
993 Preconditions.checkNotNull(local);
994 boolean globalChanged = false;
995 boolean localChanged;
996 synchronized (mRestrictionsLock) {
997 if (global != null) {
998 // Update global.
999 globalChanged = !UserRestrictionsUtils.areEqual(
1000 mDevicePolicyGlobalUserRestrictions, global);
1001 if (globalChanged) {
1002 mDevicePolicyGlobalUserRestrictions = global;
1003 }
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +01001004 // Remember the global restriction owner userId to be able to make a distinction
1005 // in getUserRestrictionSource on who set local policies.
1006 mGlobalRestrictionOwnerUserId = userId;
1007 } else {
1008 // When profile owner sets restrictions it passes null global bundle and we reset
1009 // global restriction owner userId.
1010 mGlobalRestrictionOwnerUserId = UserHandle.USER_NULL;
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001011 }
1012 {
1013 // Update local.
1014 final Bundle prev = mDevicePolicyLocalUserRestrictions.get(userId);
1015 localChanged = !UserRestrictionsUtils.areEqual(prev, local);
1016 if (localChanged) {
1017 mDevicePolicyLocalUserRestrictions.put(userId, local);
1018 }
1019 }
1020 }
1021 if (DBG) {
1022 Log.d(LOG_TAG, "setDevicePolicyUserRestrictions: userId=" + userId
1023 + " global=" + global + (globalChanged ? " (changed)" : "")
1024 + " local=" + local + (localChanged ? " (changed)" : "")
1025 );
1026 }
1027 // Don't call them within the mRestrictionsLock.
1028 synchronized (mPackagesLock) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001029 if (localChanged) {
Amith Yamasani12747872015-12-07 14:19:49 -08001030 writeUserLP(getUserDataNoChecks(userId));
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001031 }
Jeff Sharkeycd575992016-03-29 14:12:49 -06001032 if (globalChanged) {
1033 writeUserListLP();
1034 }
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001035 }
1036
1037 synchronized (mRestrictionsLock) {
1038 if (globalChanged) {
1039 applyUserRestrictionsForAllUsersLR();
1040 } else if (localChanged) {
1041 applyUserRestrictionsLR(userId);
1042 }
1043 }
1044 }
1045
Makoto Onuki068c54a2015-10-13 14:34:03 -07001046 @GuardedBy("mRestrictionsLock")
Fyodor Kupolov82402752015-10-28 14:54:51 -07001047 private Bundle computeEffectiveUserRestrictionsLR(int userId) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001048 final Bundle baseRestrictions =
1049 UserRestrictionsUtils.nonNull(mBaseUserRestrictions.get(userId));
1050 final Bundle global = mDevicePolicyGlobalUserRestrictions;
1051 final Bundle local = mDevicePolicyLocalUserRestrictions.get(userId);
Makoto Onuki068c54a2015-10-13 14:34:03 -07001052
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001053 if (UserRestrictionsUtils.isEmpty(global) && UserRestrictionsUtils.isEmpty(local)) {
1054 // Common case first.
1055 return baseRestrictions;
Makoto Onuki068c54a2015-10-13 14:34:03 -07001056 }
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001057 final Bundle effective = UserRestrictionsUtils.clone(baseRestrictions);
1058 UserRestrictionsUtils.merge(effective, global);
1059 UserRestrictionsUtils.merge(effective, local);
1060
Makoto Onuki068c54a2015-10-13 14:34:03 -07001061 return effective;
1062 }
1063
1064 @GuardedBy("mRestrictionsLock")
Fyodor Kupolov82402752015-10-28 14:54:51 -07001065 private void invalidateEffectiveUserRestrictionsLR(int userId) {
Makoto Onuki068c54a2015-10-13 14:34:03 -07001066 if (DBG) {
1067 Log.d(LOG_TAG, "invalidateEffectiveUserRestrictions userId=" + userId);
1068 }
1069 mCachedEffectiveUserRestrictions.remove(userId);
1070 }
1071
1072 private Bundle getEffectiveUserRestrictions(int userId) {
1073 synchronized (mRestrictionsLock) {
1074 Bundle restrictions = mCachedEffectiveUserRestrictions.get(userId);
1075 if (restrictions == null) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07001076 restrictions = computeEffectiveUserRestrictionsLR(userId);
Makoto Onuki068c54a2015-10-13 14:34:03 -07001077 mCachedEffectiveUserRestrictions.put(userId, restrictions);
1078 }
1079 return restrictions;
Amith Yamasani8cd28b52014-06-08 17:54:27 -07001080 }
1081 }
1082
Makoto Onuki068c54a2015-10-13 14:34:03 -07001083 /** @return a specific user restriction that's in effect currently. */
1084 @Override
1085 public boolean hasUserRestriction(String restrictionKey, int userId) {
Makoto Onuki1f1ceef2016-01-28 11:32:32 -08001086 if (!UserRestrictionsUtils.isValidRestriction(restrictionKey)) {
1087 return false;
1088 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07001089 Bundle restrictions = getEffectiveUserRestrictions(userId);
1090 return restrictions != null && restrictions.getBoolean(restrictionKey);
1091 }
1092
1093 /**
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +01001094 * @hide
1095 *
1096 * Returns who set a user restriction on a user.
1097 * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
1098 * @param restrictionKey the string key representing the restriction
1099 * @param userId the id of the user for whom to retrieve the restrictions.
1100 * @return The source of user restriction. Any combination of
1101 * {@link UserManager#RESTRICTION_NOT_SET},
1102 * {@link UserManager#RESTRICTION_SOURCE_SYSTEM},
1103 * {@link UserManager#RESTRICTION_SOURCE_DEVICE_OWNER}
1104 * and {@link UserManager#RESTRICTION_SOURCE_PROFILE_OWNER}
1105 */
1106 @Override
1107 public int getUserRestrictionSource(String restrictionKey, int userId) {
1108 checkManageUsersPermission("getUserRestrictionSource");
1109 int result = UserManager.RESTRICTION_NOT_SET;
1110
1111 // Shortcut for the most common case
1112 if (!hasUserRestriction(restrictionKey, userId)) {
1113 return result;
1114 }
1115
1116 if (hasBaseUserRestriction(restrictionKey, userId)) {
1117 result |= UserManager.RESTRICTION_SOURCE_SYSTEM;
1118 }
1119
1120 synchronized(mRestrictionsLock) {
1121 Bundle localRestrictions = mDevicePolicyLocalUserRestrictions.get(userId);
1122 if (!UserRestrictionsUtils.isEmpty(localRestrictions)
1123 && localRestrictions.getBoolean(restrictionKey)) {
1124 // Local restrictions may have been set by device owner the userId of which is
1125 // stored in mGlobalRestrictionOwnerUserId.
1126 if (mGlobalRestrictionOwnerUserId == userId) {
1127 result |= UserManager.RESTRICTION_SOURCE_DEVICE_OWNER;
1128 } else {
1129 result |= UserManager.RESTRICTION_SOURCE_PROFILE_OWNER;
1130 }
1131 }
1132 if (!UserRestrictionsUtils.isEmpty(mDevicePolicyGlobalUserRestrictions)
1133 && mDevicePolicyGlobalUserRestrictions.getBoolean(restrictionKey)) {
1134 result |= UserManager.RESTRICTION_SOURCE_DEVICE_OWNER;
1135 }
1136 }
1137
1138 return result;
1139 }
1140
1141 /**
Makoto Onuki068c54a2015-10-13 14:34:03 -07001142 * @return UserRestrictions that are in effect currently. This always returns a new
1143 * {@link Bundle}.
1144 */
Amith Yamasani8cd28b52014-06-08 17:54:27 -07001145 @Override
Amith Yamasanie4cf7342012-12-17 11:12:09 -08001146 public Bundle getUserRestrictions(int userId) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001147 return UserRestrictionsUtils.clone(getEffectiveUserRestrictions(userId));
Amith Yamasanie4cf7342012-12-17 11:12:09 -08001148 }
1149
1150 @Override
Zoltan Szatmary-Ban3bbcedd2015-11-26 13:45:51 +00001151 public boolean hasBaseUserRestriction(String restrictionKey, int userId) {
1152 checkManageUsersPermission("hasBaseUserRestriction");
Makoto Onuki1f1ceef2016-01-28 11:32:32 -08001153 if (!UserRestrictionsUtils.isValidRestriction(restrictionKey)) {
1154 return false;
1155 }
Zoltan Szatmary-Ban3bbcedd2015-11-26 13:45:51 +00001156 synchronized (mRestrictionsLock) {
1157 Bundle bundle = mBaseUserRestrictions.get(userId);
1158 return (bundle != null && bundle.getBoolean(restrictionKey, false));
1159 }
1160 }
1161
1162 @Override
Fyodor Kupolovb5013302015-04-17 17:59:14 -07001163 public void setUserRestriction(String key, boolean value, int userId) {
Fyodor Kupolovd4b26042015-07-27 14:30:59 -07001164 checkManageUsersPermission("setUserRestriction");
Makoto Onuki1f1ceef2016-01-28 11:32:32 -08001165 if (!UserRestrictionsUtils.isValidRestriction(key)) {
1166 return;
1167 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07001168 synchronized (mRestrictionsLock) {
1169 // Note we can't modify Bundles stored in mBaseUserRestrictions directly, so create
1170 // a copy.
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001171 final Bundle newRestrictions = UserRestrictionsUtils.clone(
1172 mBaseUserRestrictions.get(userId));
Makoto Onuki068c54a2015-10-13 14:34:03 -07001173 newRestrictions.putBoolean(key, value);
1174
Fyodor Kupolov82402752015-10-28 14:54:51 -07001175 updateUserRestrictionsInternalLR(newRestrictions, userId);
Fyodor Kupolovb5013302015-04-17 17:59:14 -07001176 }
1177 }
1178
Makoto Onuki068c54a2015-10-13 14:34:03 -07001179 /**
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001180 * Optionally updating user restrictions, calculate the effective user restrictions and also
1181 * propagate to other services and system settings.
Makoto Onuki068c54a2015-10-13 14:34:03 -07001182 *
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001183 * @param newRestrictions User restrictions to set.
1184 * If null, will not update user restrictions and only does the propagation.
Makoto Onuki068c54a2015-10-13 14:34:03 -07001185 * @param userId target user ID.
1186 */
1187 @GuardedBy("mRestrictionsLock")
Fyodor Kupolov82402752015-10-28 14:54:51 -07001188 private void updateUserRestrictionsInternalLR(
Makoto Onuki068c54a2015-10-13 14:34:03 -07001189 @Nullable Bundle newRestrictions, int userId) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001190
1191 final Bundle prevAppliedRestrictions = UserRestrictionsUtils.nonNull(
1192 mAppliedUserRestrictions.get(userId));
1193
1194 // Update base restrictions.
Makoto Onuki068c54a2015-10-13 14:34:03 -07001195 if (newRestrictions != null) {
1196 // If newRestrictions == the current one, it's probably a bug.
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001197 final Bundle prevBaseRestrictions = mBaseUserRestrictions.get(userId);
1198
1199 Preconditions.checkState(prevBaseRestrictions != newRestrictions);
Makoto Onuki068c54a2015-10-13 14:34:03 -07001200 Preconditions.checkState(mCachedEffectiveUserRestrictions.get(userId)
1201 != newRestrictions);
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001202
1203 if (!UserRestrictionsUtils.areEqual(prevBaseRestrictions, newRestrictions)) {
1204 mBaseUserRestrictions.put(userId, newRestrictions);
Amith Yamasani12747872015-12-07 14:19:49 -08001205 scheduleWriteUser(getUserDataNoChecks(userId));
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001206 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07001207 }
1208
Fyodor Kupolov82402752015-10-28 14:54:51 -07001209 final Bundle effective = computeEffectiveUserRestrictionsLR(userId);
Makoto Onuki068c54a2015-10-13 14:34:03 -07001210
Makoto Onuki759a7632015-10-28 16:43:10 -07001211 mCachedEffectiveUserRestrictions.put(userId, effective);
1212
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001213 // Apply the new restrictions.
Makoto Onuki4f160732015-10-27 17:15:38 -07001214 if (DBG) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001215 debug("Applying user restrictions: userId=" + userId
1216 + " new=" + effective + " prev=" + prevAppliedRestrictions);
Makoto Onuki4f160732015-10-27 17:15:38 -07001217 }
1218
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001219 if (mAppOpsService != null) { // We skip it until system-ready.
1220 final long token = Binder.clearCallingIdentity();
1221 try {
Svet Ganov9cea80cd2016-02-16 11:47:00 -08001222 mAppOpsService.setUserRestrictions(effective, mUserRestriconToken, userId);
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001223 } catch (RemoteException e) {
1224 Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
1225 } finally {
1226 Binder.restoreCallingIdentity(token);
1227 }
Fyodor Kupolovb5013302015-04-17 17:59:14 -07001228 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07001229
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001230 propagateUserRestrictionsLR(userId, effective, prevAppliedRestrictions);
Makoto Onuki4f160732015-10-27 17:15:38 -07001231
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001232 mAppliedUserRestrictions.put(userId, new Bundle(effective));
Makoto Onuki068c54a2015-10-13 14:34:03 -07001233 }
1234
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001235 private void propagateUserRestrictionsLR(final int userId,
Makoto Onukid45a4a22015-11-02 17:17:38 -08001236 Bundle newRestrictions, Bundle prevRestrictions) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001237 // Note this method doesn't touch any state, meaning it doesn't require mRestrictionsLock
1238 // actually, but we still need some kind of synchronization otherwise we might end up
1239 // calling listeners out-of-order, thus "LR".
1240
1241 if (UserRestrictionsUtils.areEqual(newRestrictions, prevRestrictions)) {
1242 return;
1243 }
Makoto Onukid45a4a22015-11-02 17:17:38 -08001244
1245 final Bundle newRestrictionsFinal = new Bundle(newRestrictions);
1246 final Bundle prevRestrictionsFinal = new Bundle(prevRestrictions);
1247
1248 mHandler.post(new Runnable() {
1249 @Override
1250 public void run() {
Fyodor Kupolov9cbfc9e2015-10-07 15:52:33 -07001251 UserRestrictionsUtils.applyUserRestrictions(
1252 mContext, userId, newRestrictionsFinal, prevRestrictionsFinal);
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001253
Makoto Onukid45a4a22015-11-02 17:17:38 -08001254 final UserRestrictionsListener[] listeners;
1255 synchronized (mUserRestrictionsListeners) {
1256 listeners = new UserRestrictionsListener[mUserRestrictionsListeners.size()];
1257 mUserRestrictionsListeners.toArray(listeners);
1258 }
1259 for (int i = 0; i < listeners.length; i++) {
1260 listeners[i].onUserRestrictionsChanged(userId,
1261 newRestrictionsFinal, prevRestrictionsFinal);
1262 }
1263 }
1264 });
1265 }
1266
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001267 // Package private for the inner class.
1268 void applyUserRestrictionsLR(int userId) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07001269 updateUserRestrictionsInternalLR(null, userId);
Makoto Onuki068c54a2015-10-13 14:34:03 -07001270 }
1271
1272 @GuardedBy("mRestrictionsLock")
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001273 // Package private for the inner class.
1274 void applyUserRestrictionsForAllUsersLR() {
1275 if (DBG) {
1276 debug("applyUserRestrictionsForAllUsersLR");
1277 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07001278 // First, invalidate all cached values.
Makoto Onuki4f160732015-10-27 17:15:38 -07001279 mCachedEffectiveUserRestrictions.clear();
1280
Makoto Onuki068c54a2015-10-13 14:34:03 -07001281 // We don't want to call into ActivityManagerNative while taking a lock, so we'll call
1282 // it on a handler.
1283 final Runnable r = new Runnable() {
1284 @Override
1285 public void run() {
1286 // Then get the list of running users.
1287 final int[] runningUsers;
1288 try {
1289 runningUsers = ActivityManagerNative.getDefault().getRunningUserIds();
1290 } catch (RemoteException e) {
1291 Log.w(LOG_TAG, "Unable to access ActivityManagerNative");
1292 return;
1293 }
1294 // Then re-calculate the effective restrictions and apply, only for running users.
1295 // It's okay if a new user has started after the getRunningUserIds() call,
1296 // because we'll do the same thing (re-calculate the restrictions and apply)
1297 // when we start a user.
Makoto Onuki068c54a2015-10-13 14:34:03 -07001298 synchronized (mRestrictionsLock) {
1299 for (int i = 0; i < runningUsers.length; i++) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001300 applyUserRestrictionsLR(runningUsers[i]);
Makoto Onuki068c54a2015-10-13 14:34:03 -07001301 }
1302 }
1303 }
1304 };
1305 mHandler.post(r);
Fyodor Kupolovb5013302015-04-17 17:59:14 -07001306 }
1307
Amith Yamasani258848d2012-08-10 17:06:33 -07001308 /**
Amith Yamasanifaea76f2012-09-11 10:59:48 -07001309 * Check if we've hit the limit of how many users can be created.
1310 */
Fyodor Kupolov82402752015-10-28 14:54:51 -07001311 private boolean isUserLimitReached() {
1312 int count;
1313 synchronized (mUsersLock) {
1314 count = getAliveUsersExcludingGuestsCountLU();
1315 }
1316 return count >= UserManager.getMaxSupportedUsers();
Nicolas Prevot12678a92015-05-13 12:15:03 -07001317 }
1318
1319 @Override
Nicolas Prevot07387fe2015-10-30 17:53:30 +00001320 public boolean canAddMoreManagedProfiles(int userId, boolean allowedToRemoveOne) {
Nicolas Prevot12678a92015-05-13 12:15:03 -07001321 checkManageUsersPermission("check if more managed profiles can be added.");
1322 if (ActivityManager.isLowRamDeviceStatic()) {
1323 return false;
1324 }
Fyodor Kupolovb6157992015-06-05 15:32:28 -07001325 if (!mContext.getPackageManager().hasSystemFeature(
1326 PackageManager.FEATURE_MANAGED_USERS)) {
1327 return false;
1328 }
Nicolas Prevotb8186812015-08-06 15:00:03 +01001329 // Limit number of managed profiles that can be created
Nicolas Prevot07387fe2015-10-30 17:53:30 +00001330 final int managedProfilesCount = getProfiles(userId, true).size() - 1;
1331 final int profilesRemovedCount = managedProfilesCount > 0 && allowedToRemoveOne ? 1 : 0;
1332 if (managedProfilesCount - profilesRemovedCount >= MAX_MANAGED_PROFILES) {
Nicolas Prevotb8186812015-08-06 15:00:03 +01001333 return false;
1334 }
Fyodor Kupolov82402752015-10-28 14:54:51 -07001335 synchronized(mUsersLock) {
1336 UserInfo userInfo = getUserInfoLU(userId);
Nicolas Prevotb8186812015-08-06 15:00:03 +01001337 if (!userInfo.canHaveProfile()) {
Nicolas Prevot12678a92015-05-13 12:15:03 -07001338 return false;
1339 }
Nicolas Prevot07387fe2015-10-30 17:53:30 +00001340 int usersCountAfterRemoving = getAliveUsersExcludingGuestsCountLU()
1341 - profilesRemovedCount;
Nicolas Prevot12678a92015-05-13 12:15:03 -07001342 // We allow creating a managed profile in the special case where there is only one user.
Nicolas Prevot07387fe2015-10-30 17:53:30 +00001343 return usersCountAfterRemoving == 1
1344 || usersCountAfterRemoving < UserManager.getMaxSupportedUsers();
Nicolas Prevot12678a92015-05-13 12:15:03 -07001345 }
1346 }
1347
Fyodor Kupolov82402752015-10-28 14:54:51 -07001348 private int getAliveUsersExcludingGuestsCountLU() {
Amith Yamasanif584f012014-05-19 17:57:25 -07001349 int aliveUserCount = 0;
1350 final int totalUserCount = mUsers.size();
1351 // Skip over users being removed
1352 for (int i = 0; i < totalUserCount; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -08001353 UserInfo user = mUsers.valueAt(i).info;
Amith Yamasani95ab7842014-08-11 17:09:26 -07001354 if (!mRemovingUserIds.get(user.id)
Amith Yamasani1df14732014-08-29 21:37:27 -07001355 && !user.isGuest() && !user.partial) {
Amith Yamasanif584f012014-05-19 17:57:25 -07001356 aliveUserCount++;
1357 }
1358 }
Nicolas Prevot12678a92015-05-13 12:15:03 -07001359 return aliveUserCount;
Amith Yamasanifaea76f2012-09-11 10:59:48 -07001360 }
1361
1362 /**
Amith Yamasani195263742012-08-21 15:40:12 -07001363 * Enforces that only the system UID or root's UID or apps that have the
Xiaohui Chenb3b92582015-12-07 11:22:13 -08001364 * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} and
1365 * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL INTERACT_ACROSS_USERS_FULL}
1366 * permissions can make certain calls to the UserManager.
1367 *
1368 * @param message used as message if SecurityException is thrown
1369 * @throws SecurityException if the caller does not have enough privilege.
1370 */
1371 private static final void checkManageUserAndAcrossUsersFullPermission(String message) {
1372 final int uid = Binder.getCallingUid();
1373 if (uid != Process.SYSTEM_UID && uid != 0
1374 && ActivityManager.checkComponentPermission(
1375 Manifest.permission.MANAGE_USERS,
1376 uid, -1, true) != PackageManager.PERMISSION_GRANTED
1377 && ActivityManager.checkComponentPermission(
1378 Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1379 uid, -1, true) != PackageManager.PERMISSION_GRANTED) {
1380 throw new SecurityException(
1381 "You need MANAGE_USERS and INTERACT_ACROSS_USERS_FULL permission to: "
1382 + message);
1383 }
1384 }
1385
1386 /**
1387 * Enforces that only the system UID or root's UID or apps that have the
Dianne Hackborn10ad9822014-03-17 11:28:36 -07001388 * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS}
Amith Yamasani195263742012-08-21 15:40:12 -07001389 * permission can make certain calls to the UserManager.
Amith Yamasani258848d2012-08-10 17:06:33 -07001390 *
1391 * @param message used as message if SecurityException is thrown
1392 * @throws SecurityException if the caller is not system or root
Tony Mak4dc008c2016-03-16 10:46:49 +00001393 * @see #hasManageUsersPermission()
Amith Yamasani258848d2012-08-10 17:06:33 -07001394 */
Amith Yamasanibe465322014-04-24 13:45:17 -07001395 private static final void checkManageUsersPermission(String message) {
Tony Mak4dc008c2016-03-16 10:46:49 +00001396 if (!hasManageUsersPermission()) {
Amith Yamasanibe465322014-04-24 13:45:17 -07001397 throw new SecurityException("You need MANAGE_USERS permission to: " + message);
1398 }
Emily Bernier7a2b4d12014-04-23 12:51:35 -04001399 }
1400
Esteban Talavera5b9f1672015-12-11 15:22:34 +00001401 /**
Tony Mak4dc008c2016-03-16 10:46:49 +00001402 * @return whether the calling UID is system UID or root's UID or the calling app has the
1403 * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS}.
1404 */
1405 private static final boolean hasManageUsersPermission() {
1406 final int callingUid = Binder.getCallingUid();
1407 return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
1408 || callingUid == Process.ROOT_UID
1409 || ActivityManager.checkComponentPermission(
1410 android.Manifest.permission.MANAGE_USERS,
1411 callingUid, -1, true) == PackageManager.PERMISSION_GRANTED;
1412 }
1413
1414 /**
Esteban Talavera5b9f1672015-12-11 15:22:34 +00001415 * Enforces that only the system UID or root's UID (on any user) can make certain calls to the
1416 * UserManager.
1417 *
1418 * @param message used as message if SecurityException is thrown
1419 * @throws SecurityException if the caller is not system or root
1420 */
1421 private static void checkSystemOrRoot(String message) {
1422 final int uid = Binder.getCallingUid();
1423 if (!UserHandle.isSameApp(uid, Process.SYSTEM_UID) && uid != Process.ROOT_UID) {
1424 throw new SecurityException("Only system may: " + message);
1425 }
1426 }
1427
Fyodor Kupolov82402752015-10-28 14:54:51 -07001428 private void writeBitmapLP(UserInfo info, Bitmap bitmap) {
Amith Yamasanib8151ec2012-04-18 18:02:48 -07001429 try {
1430 File dir = new File(mUsersDir, Integer.toString(info.id));
1431 File file = new File(dir, USER_PHOTO_FILENAME);
Adrian Roos1bdff912015-02-17 15:51:35 +01001432 File tmp = new File(dir, USER_PHOTO_FILENAME_TMP);
Amith Yamasanib8151ec2012-04-18 18:02:48 -07001433 if (!dir.exists()) {
1434 dir.mkdir();
1435 FileUtils.setPermissions(
1436 dir.getPath(),
1437 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
1438 -1, -1);
1439 }
Amith Yamasanie928d7d2012-09-17 21:46:51 -07001440 FileOutputStream os;
Adrian Roos1bdff912015-02-17 15:51:35 +01001441 if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, os = new FileOutputStream(tmp))
Oleksandr Peletskyicd6fa302016-02-25 16:28:39 +01001442 && tmp.renameTo(file) && SELinux.restorecon(file)) {
Amith Yamasani3b49f072012-09-17 10:21:43 -07001443 info.iconPath = file.getAbsolutePath();
1444 }
Amith Yamasanie928d7d2012-09-17 21:46:51 -07001445 try {
1446 os.close();
1447 } catch (IOException ioe) {
1448 // What the ... !
1449 }
Adrian Roos1bdff912015-02-17 15:51:35 +01001450 tmp.delete();
Amith Yamasanib8151ec2012-04-18 18:02:48 -07001451 } catch (FileNotFoundException e) {
Amith Yamasani2a003292012-08-14 18:25:45 -07001452 Slog.w(LOG_TAG, "Error setting photo for user ", e);
Amith Yamasanib8151ec2012-04-18 18:02:48 -07001453 }
Amith Yamasanib8151ec2012-04-18 18:02:48 -07001454 }
1455
Amith Yamasani0b285492011-04-14 17:35:23 -07001456 /**
1457 * Returns an array of user ids. This array is cached here for quick access, so do not modify or
1458 * cache it elsewhere.
1459 * @return the array of user ids.
1460 */
Dianne Hackborn1676c852012-09-10 14:52:30 -07001461 public int[] getUserIds() {
Fyodor Kupolov82402752015-10-28 14:54:51 -07001462 synchronized (mUsersLock) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07001463 return mUserIds;
1464 }
Amith Yamasani0b285492011-04-14 17:35:23 -07001465 }
1466
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001467 private void readUserListLP() {
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001468 if (!mUserListFile.exists()) {
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001469 fallbackToSingleUserLP();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001470 return;
1471 }
1472 FileInputStream fis = null;
Amith Yamasani2a003292012-08-14 18:25:45 -07001473 AtomicFile userListFile = new AtomicFile(mUserListFile);
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001474 try {
Amith Yamasani2a003292012-08-14 18:25:45 -07001475 fis = userListFile.openRead();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001476 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001477 parser.setInput(fis, StandardCharsets.UTF_8.name());
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001478 int type;
1479 while ((type = parser.next()) != XmlPullParser.START_TAG
1480 && type != XmlPullParser.END_DOCUMENT) {
Amith Yamasani12747872015-12-07 14:19:49 -08001481 // Skip
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001482 }
1483
1484 if (type != XmlPullParser.START_TAG) {
Amith Yamasani0b285492011-04-14 17:35:23 -07001485 Slog.e(LOG_TAG, "Unable to read user list");
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001486 fallbackToSingleUserLP();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001487 return;
1488 }
1489
Amith Yamasani2a003292012-08-14 18:25:45 -07001490 mNextSerialNumber = -1;
1491 if (parser.getName().equals(TAG_USERS)) {
1492 String lastSerialNumber = parser.getAttributeValue(null, ATTR_NEXT_SERIAL_NO);
1493 if (lastSerialNumber != null) {
1494 mNextSerialNumber = Integer.parseInt(lastSerialNumber);
1495 }
Amith Yamasani6f34b412012-10-22 18:19:27 -07001496 String versionNumber = parser.getAttributeValue(null, ATTR_USER_VERSION);
1497 if (versionNumber != null) {
1498 mUserVersion = Integer.parseInt(versionNumber);
1499 }
Amith Yamasani2a003292012-08-14 18:25:45 -07001500 }
1501
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001502 final Bundle newDevicePolicyGlobalUserRestrictions = new Bundle();
1503
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001504 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
Amith Yamasanie4afaa32014-06-30 14:55:07 +05301505 if (type == XmlPullParser.START_TAG) {
1506 final String name = parser.getName();
1507 if (name.equals(TAG_USER)) {
1508 String id = parser.getAttributeValue(null, ATTR_ID);
Amith Yamasani6f34b412012-10-22 18:19:27 -07001509
Amith Yamasani12747872015-12-07 14:19:49 -08001510 UserData userData = readUserLP(Integer.parseInt(id));
1511
1512 if (userData != null) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07001513 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08001514 mUsers.put(userData.info.id, userData);
1515 if (mNextSerialNumber < 0
1516 || mNextSerialNumber <= userData.info.id) {
1517 mNextSerialNumber = userData.info.id + 1;
Fyodor Kupolov82402752015-10-28 14:54:51 -07001518 }
Amith Yamasanie4afaa32014-06-30 14:55:07 +05301519 }
Amith Yamasani2a003292012-08-14 18:25:45 -07001520 }
Amith Yamasanie4afaa32014-06-30 14:55:07 +05301521 } else if (name.equals(TAG_GUEST_RESTRICTIONS)) {
Amith Yamasanida0b1682014-11-21 12:58:17 -08001522 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1523 && type != XmlPullParser.END_TAG) {
1524 if (type == XmlPullParser.START_TAG) {
1525 if (parser.getName().equals(TAG_RESTRICTIONS)) {
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001526 synchronized (mGuestRestrictions) {
1527 UserRestrictionsUtils
1528 .readRestrictions(parser, mGuestRestrictions);
1529 }
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001530 } else if (parser.getName().equals(TAG_DEVICE_POLICY_RESTRICTIONS)
1531 ) {
1532 UserRestrictionsUtils.readRestrictions(parser,
1533 newDevicePolicyGlobalUserRestrictions);
Amith Yamasanida0b1682014-11-21 12:58:17 -08001534 }
1535 break;
1536 }
1537 }
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +01001538 } else if (name.equals(TAG_GLOBAL_RESTRICTION_OWNER_ID)) {
1539 String ownerUserId = parser.getAttributeValue(null, ATTR_ID);
1540 if (ownerUserId != null) {
1541 mGlobalRestrictionOwnerUserId = Integer.parseInt(ownerUserId);
1542 }
Amith Yamasani258848d2012-08-10 17:06:33 -07001543 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001544 }
1545 }
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001546 synchronized (mRestrictionsLock) {
1547 mDevicePolicyGlobalUserRestrictions = newDevicePolicyGlobalUserRestrictions;
1548 }
Fyodor Kupolov82402752015-10-28 14:54:51 -07001549 updateUserIds();
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001550 upgradeIfNecessaryLP();
1551 } catch (IOException | XmlPullParserException e) {
1552 fallbackToSingleUserLP();
Dianne Hackbornbfd89b32011-12-15 18:22:54 -08001553 } finally {
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001554 IoUtils.closeQuietly(fis);
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001555 }
1556 }
1557
Amith Yamasani6f34b412012-10-22 18:19:27 -07001558 /**
Amith Yamasanibc9625052012-11-15 14:39:18 -08001559 * Upgrade steps between versions, either for fixing bugs or changing the data format.
Amith Yamasani6f34b412012-10-22 18:19:27 -07001560 */
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001561 private void upgradeIfNecessaryLP() {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001562 final int originalVersion = mUserVersion;
Amith Yamasani6f34b412012-10-22 18:19:27 -07001563 int userVersion = mUserVersion;
1564 if (userVersion < 1) {
1565 // Assign a proper name for the owner, if not initialized correctly before
Amith Yamasani12747872015-12-07 14:19:49 -08001566 UserData userData = getUserDataNoChecks(UserHandle.USER_SYSTEM);
1567 if ("Primary".equals(userData.info.name)) {
1568 userData.info.name =
1569 mContext.getResources().getString(com.android.internal.R.string.owner_name);
1570 scheduleWriteUser(userData);
Amith Yamasani6f34b412012-10-22 18:19:27 -07001571 }
1572 userVersion = 1;
1573 }
1574
Amith Yamasanibc9625052012-11-15 14:39:18 -08001575 if (userVersion < 2) {
1576 // Owner should be marked as initialized
Amith Yamasani12747872015-12-07 14:19:49 -08001577 UserData userData = getUserDataNoChecks(UserHandle.USER_SYSTEM);
1578 if ((userData.info.flags & UserInfo.FLAG_INITIALIZED) == 0) {
1579 userData.info.flags |= UserInfo.FLAG_INITIALIZED;
1580 scheduleWriteUser(userData);
Amith Yamasanibc9625052012-11-15 14:39:18 -08001581 }
1582 userVersion = 2;
1583 }
1584
Amith Yamasani350962c2013-08-06 11:18:53 -07001585
Amith Yamasani5e486f52013-08-07 11:06:44 -07001586 if (userVersion < 4) {
Amith Yamasani5e486f52013-08-07 11:06:44 -07001587 userVersion = 4;
1588 }
1589
Amith Yamasaniaa6634e2014-10-06 14:20:28 -07001590 if (userVersion < 5) {
1591 initDefaultGuestRestrictions();
1592 userVersion = 5;
1593 }
1594
Fyodor Kupolov1c363152015-09-02 13:27:21 -07001595 if (userVersion < 6) {
1596 final boolean splitSystemUser = UserManager.isSplitSystemUser();
Fyodor Kupolov82402752015-10-28 14:54:51 -07001597 synchronized (mUsersLock) {
1598 for (int i = 0; i < mUsers.size(); i++) {
Amith Yamasani12747872015-12-07 14:19:49 -08001599 UserData userData = mUsers.valueAt(i);
Fyodor Kupolov82402752015-10-28 14:54:51 -07001600 // In non-split mode, only user 0 can have restricted profiles
Amith Yamasani12747872015-12-07 14:19:49 -08001601 if (!splitSystemUser && userData.info.isRestricted()
1602 && (userData.info.restrictedProfileParentId
1603 == UserInfo.NO_PROFILE_GROUP_ID)) {
1604 userData.info.restrictedProfileParentId = UserHandle.USER_SYSTEM;
1605 scheduleWriteUser(userData);
Fyodor Kupolov82402752015-10-28 14:54:51 -07001606 }
Fyodor Kupolov1c363152015-09-02 13:27:21 -07001607 }
1608 }
1609 userVersion = 6;
1610 }
1611
Amith Yamasani6f34b412012-10-22 18:19:27 -07001612 if (userVersion < USER_VERSION) {
1613 Slog.w(LOG_TAG, "User version " + mUserVersion + " didn't upgrade as expected to "
1614 + USER_VERSION);
1615 } else {
1616 mUserVersion = userVersion;
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001617
1618 if (originalVersion < mUserVersion) {
1619 writeUserListLP();
1620 }
Amith Yamasani6f34b412012-10-22 18:19:27 -07001621 }
1622 }
1623
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001624 private void fallbackToSingleUserLP() {
Xiaohui Chenb31e14a2015-07-13 16:04:55 -07001625 int flags = UserInfo.FLAG_INITIALIZED;
1626 // In split system user mode, the admin and primary flags are assigned to the first human
1627 // user.
1628 if (!UserManager.isSplitSystemUser()) {
1629 flags |= UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY;
1630 }
Xiaohui Chen70f6c382015-04-28 14:21:43 -07001631 // Create the system user
Amith Yamasani6f48d6e2016-03-23 14:28:25 -07001632 UserInfo system = new UserInfo(UserHandle.USER_SYSTEM, null, null, flags);
Amith Yamasani12747872015-12-07 14:19:49 -08001633 UserData userData = new UserData();
1634 userData.info = system;
Fyodor Kupolov82402752015-10-28 14:54:51 -07001635 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08001636 mUsers.put(system.id, userData);
Fyodor Kupolov82402752015-10-28 14:54:51 -07001637 }
Amith Yamasani634cf312012-10-04 17:34:21 -07001638 mNextSerialNumber = MIN_USER_ID;
Geoffrey Borggaard15b8b2c2013-08-28 22:11:10 -04001639 mUserVersion = USER_VERSION;
Amith Yamasani67df64b2012-12-14 12:09:36 -08001640
Geoffrey Borggaarde45e45e32013-01-24 10:03:20 -05001641 Bundle restrictions = new Bundle();
Makoto Onuki068c54a2015-10-13 14:34:03 -07001642 synchronized (mRestrictionsLock) {
1643 mBaseUserRestrictions.append(UserHandle.USER_SYSTEM, restrictions);
1644 }
Amith Yamasani67df64b2012-12-14 12:09:36 -08001645
Fyodor Kupolov82402752015-10-28 14:54:51 -07001646 updateUserIds();
Amith Yamasaniaa6634e2014-10-06 14:20:28 -07001647 initDefaultGuestRestrictions();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001648
Amith Yamasani12747872015-12-07 14:19:49 -08001649 writeUserLP(userData);
Jeff Sharkeycd575992016-03-29 14:12:49 -06001650 writeUserListLP();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001651 }
1652
Amith Yamasani6f48d6e2016-03-23 14:28:25 -07001653 private String getOwnerName() {
1654 return mContext.getResources().getString(com.android.internal.R.string.owner_name);
1655 }
1656
Amith Yamasani12747872015-12-07 14:19:49 -08001657 private void scheduleWriteUser(UserData UserData) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001658 if (DBG) {
1659 debug("scheduleWriteUser");
1660 }
Makoto Onuki9e935a32015-11-06 14:24:24 -08001661 // No need to wrap it within a lock -- worst case, we'll just post the same message
1662 // twice.
Amith Yamasani12747872015-12-07 14:19:49 -08001663 if (!mHandler.hasMessages(WRITE_USER_MSG, UserData)) {
1664 Message msg = mHandler.obtainMessage(WRITE_USER_MSG, UserData);
Fyodor Kupolov75d0ea82014-12-15 16:21:07 -08001665 mHandler.sendMessageDelayed(msg, WRITE_USER_DELAY);
1666 }
1667 }
1668
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001669 /*
1670 * Writes the user file in this format:
1671 *
1672 * <user flags="20039023" id="0">
1673 * <name>Primary</name>
1674 * </user>
1675 */
Amith Yamasani12747872015-12-07 14:19:49 -08001676 private void writeUserLP(UserData userData) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001677 if (DBG) {
Amith Yamasani12747872015-12-07 14:19:49 -08001678 debug("writeUserLP " + userData);
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001679 }
Amith Yamasani742a6712011-05-04 14:49:28 -07001680 FileOutputStream fos = null;
Amith Yamasani12747872015-12-07 14:19:49 -08001681 AtomicFile userFile = new AtomicFile(new File(mUsersDir, userData.info.id + XML_SUFFIX));
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001682 try {
Amith Yamasani2a003292012-08-14 18:25:45 -07001683 fos = userFile.startWrite();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001684 final BufferedOutputStream bos = new BufferedOutputStream(fos);
1685
1686 // XmlSerializer serializer = XmlUtils.serializerInstance();
1687 final XmlSerializer serializer = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001688 serializer.setOutput(bos, StandardCharsets.UTF_8.name());
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001689 serializer.startDocument(null, true);
1690 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
1691
Amith Yamasani12747872015-12-07 14:19:49 -08001692 final UserInfo userInfo = userData.info;
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001693 serializer.startTag(null, TAG_USER);
1694 serializer.attribute(null, ATTR_ID, Integer.toString(userInfo.id));
Amith Yamasani2a003292012-08-14 18:25:45 -07001695 serializer.attribute(null, ATTR_SERIAL_NO, Integer.toString(userInfo.serialNumber));
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001696 serializer.attribute(null, ATTR_FLAGS, Integer.toString(userInfo.flags));
Amith Yamasani920ace02012-09-20 22:15:37 -07001697 serializer.attribute(null, ATTR_CREATION_TIME, Long.toString(userInfo.creationTime));
1698 serializer.attribute(null, ATTR_LAST_LOGGED_IN_TIME,
1699 Long.toString(userInfo.lastLoggedInTime));
Jeff Sharkeycd575992016-03-29 14:12:49 -06001700 if (userInfo.lastLoggedInFingerprint != null) {
1701 serializer.attribute(null, ATTR_LAST_LOGGED_IN_FINGERPRINT,
1702 userInfo.lastLoggedInFingerprint);
1703 }
Amith Yamasanib8151ec2012-04-18 18:02:48 -07001704 if (userInfo.iconPath != null) {
1705 serializer.attribute(null, ATTR_ICON_PATH, userInfo.iconPath);
1706 }
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07001707 if (userInfo.partial) {
1708 serializer.attribute(null, ATTR_PARTIAL, "true");
1709 }
Adam Lesinskieddeb492014-09-08 17:50:03 -07001710 if (userInfo.guestToRemove) {
1711 serializer.attribute(null, ATTR_GUEST_TO_REMOVE, "true");
1712 }
Kenny Guy2a764942014-04-02 13:29:20 +01001713 if (userInfo.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID) {
1714 serializer.attribute(null, ATTR_PROFILE_GROUP_ID,
1715 Integer.toString(userInfo.profileGroupId));
Kenny Guya52dc3e2014-02-11 15:33:14 +00001716 }
Fyodor Kupolov06a484a2015-08-21 16:33:20 -07001717 if (userInfo.restrictedProfileParentId != UserInfo.NO_PROFILE_GROUP_ID) {
1718 serializer.attribute(null, ATTR_RESTRICTED_PROFILE_PARENT_ID,
1719 Integer.toString(userInfo.restrictedProfileParentId));
1720 }
Amith Yamasani12747872015-12-07 14:19:49 -08001721 // Write seed data
1722 if (userData.persistSeedData) {
1723 if (userData.seedAccountName != null) {
1724 serializer.attribute(null, ATTR_SEED_ACCOUNT_NAME, userData.seedAccountName);
1725 }
1726 if (userData.seedAccountType != null) {
1727 serializer.attribute(null, ATTR_SEED_ACCOUNT_TYPE, userData.seedAccountType);
1728 }
1729 }
Amith Yamasani6f48d6e2016-03-23 14:28:25 -07001730 if (userInfo.name != null) {
1731 serializer.startTag(null, TAG_NAME);
1732 serializer.text(userInfo.name);
1733 serializer.endTag(null, TAG_NAME);
1734 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07001735 synchronized (mRestrictionsLock) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001736 UserRestrictionsUtils.writeRestrictions(serializer,
1737 mBaseUserRestrictions.get(userInfo.id), TAG_RESTRICTIONS);
1738 UserRestrictionsUtils.writeRestrictions(serializer,
1739 mDevicePolicyLocalUserRestrictions.get(userInfo.id),
1740 TAG_DEVICE_POLICY_RESTRICTIONS);
Amith Yamasanie4cf7342012-12-17 11:12:09 -08001741 }
Amith Yamasani12747872015-12-07 14:19:49 -08001742
1743 if (userData.account != null) {
Xiaohui Chenb3b92582015-12-07 11:22:13 -08001744 serializer.startTag(null, TAG_ACCOUNT);
Amith Yamasani12747872015-12-07 14:19:49 -08001745 serializer.text(userData.account);
Xiaohui Chenb3b92582015-12-07 11:22:13 -08001746 serializer.endTag(null, TAG_ACCOUNT);
1747 }
1748
Amith Yamasani12747872015-12-07 14:19:49 -08001749 if (userData.persistSeedData && userData.seedAccountOptions != null) {
1750 serializer.startTag(null, TAG_SEED_ACCOUNT_OPTIONS);
1751 userData.seedAccountOptions.saveToXml(serializer);
1752 serializer.endTag(null, TAG_SEED_ACCOUNT_OPTIONS);
1753 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001754 serializer.endTag(null, TAG_USER);
1755
1756 serializer.endDocument();
Amith Yamasani2a003292012-08-14 18:25:45 -07001757 userFile.finishWrite(fos);
1758 } catch (Exception ioe) {
Jeff Sharkeycd575992016-03-29 14:12:49 -06001759 Slog.e(LOG_TAG, "Error writing user info " + userData.info.id, ioe);
Amith Yamasani2a003292012-08-14 18:25:45 -07001760 userFile.failWrite(fos);
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001761 }
1762 }
1763
1764 /*
1765 * Writes the user list file in this format:
1766 *
Amith Yamasani2a003292012-08-14 18:25:45 -07001767 * <users nextSerialNumber="3">
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001768 * <user id="0"></user>
1769 * <user id="2"></user>
1770 * </users>
1771 */
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001772 private void writeUserListLP() {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001773 if (DBG) {
1774 debug("writeUserList");
1775 }
Amith Yamasani742a6712011-05-04 14:49:28 -07001776 FileOutputStream fos = null;
Amith Yamasani2a003292012-08-14 18:25:45 -07001777 AtomicFile userListFile = new AtomicFile(mUserListFile);
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001778 try {
Amith Yamasani2a003292012-08-14 18:25:45 -07001779 fos = userListFile.startWrite();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001780 final BufferedOutputStream bos = new BufferedOutputStream(fos);
1781
1782 // XmlSerializer serializer = XmlUtils.serializerInstance();
1783 final XmlSerializer serializer = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001784 serializer.setOutput(bos, StandardCharsets.UTF_8.name());
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001785 serializer.startDocument(null, true);
1786 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
1787
1788 serializer.startTag(null, TAG_USERS);
Amith Yamasani2a003292012-08-14 18:25:45 -07001789 serializer.attribute(null, ATTR_NEXT_SERIAL_NO, Integer.toString(mNextSerialNumber));
Amith Yamasani6f34b412012-10-22 18:19:27 -07001790 serializer.attribute(null, ATTR_USER_VERSION, Integer.toString(mUserVersion));
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001791
Adam Lesinskieddeb492014-09-08 17:50:03 -07001792 serializer.startTag(null, TAG_GUEST_RESTRICTIONS);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001793 synchronized (mGuestRestrictions) {
1794 UserRestrictionsUtils
1795 .writeRestrictions(serializer, mGuestRestrictions, TAG_RESTRICTIONS);
1796 }
Amith Yamasanie4afaa32014-06-30 14:55:07 +05301797 serializer.endTag(null, TAG_GUEST_RESTRICTIONS);
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001798 synchronized (mRestrictionsLock) {
1799 UserRestrictionsUtils.writeRestrictions(serializer,
1800 mDevicePolicyGlobalUserRestrictions, TAG_DEVICE_POLICY_RESTRICTIONS);
1801 }
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +01001802 serializer.startTag(null, TAG_GLOBAL_RESTRICTION_OWNER_ID);
1803 serializer.attribute(null, ATTR_ID, Integer.toString(mGlobalRestrictionOwnerUserId));
1804 serializer.endTag(null, TAG_GLOBAL_RESTRICTION_OWNER_ID);
Fyodor Kupolov82402752015-10-28 14:54:51 -07001805 int[] userIdsToWrite;
1806 synchronized (mUsersLock) {
1807 userIdsToWrite = new int[mUsers.size()];
1808 for (int i = 0; i < userIdsToWrite.length; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -08001809 UserInfo user = mUsers.valueAt(i).info;
Fyodor Kupolov82402752015-10-28 14:54:51 -07001810 userIdsToWrite[i] = user.id;
1811 }
1812 }
1813 for (int id : userIdsToWrite) {
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001814 serializer.startTag(null, TAG_USER);
Fyodor Kupolov82402752015-10-28 14:54:51 -07001815 serializer.attribute(null, ATTR_ID, Integer.toString(id));
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001816 serializer.endTag(null, TAG_USER);
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001817 }
1818
1819 serializer.endTag(null, TAG_USERS);
1820
1821 serializer.endDocument();
Amith Yamasani2a003292012-08-14 18:25:45 -07001822 userListFile.finishWrite(fos);
1823 } catch (Exception e) {
1824 userListFile.failWrite(fos);
Amith Yamasani0b285492011-04-14 17:35:23 -07001825 Slog.e(LOG_TAG, "Error writing user list");
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001826 }
1827 }
1828
Amith Yamasani12747872015-12-07 14:19:49 -08001829 private UserData readUserLP(int id) {
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001830 int flags = 0;
Amith Yamasani2a003292012-08-14 18:25:45 -07001831 int serialNumber = id;
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001832 String name = null;
Xiaohui Chenb3b92582015-12-07 11:22:13 -08001833 String account = null;
Amith Yamasanib8151ec2012-04-18 18:02:48 -07001834 String iconPath = null;
Amith Yamasani920ace02012-09-20 22:15:37 -07001835 long creationTime = 0L;
1836 long lastLoggedInTime = 0L;
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06001837 String lastLoggedInFingerprint = null;
Kenny Guy2a764942014-04-02 13:29:20 +01001838 int profileGroupId = UserInfo.NO_PROFILE_GROUP_ID;
Fyodor Kupolov06a484a2015-08-21 16:33:20 -07001839 int restrictedProfileParentId = UserInfo.NO_PROFILE_GROUP_ID;
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07001840 boolean partial = false;
Adam Lesinskieddeb492014-09-08 17:50:03 -07001841 boolean guestToRemove = false;
Amith Yamasani12747872015-12-07 14:19:49 -08001842 boolean persistSeedData = false;
1843 String seedAccountName = null;
1844 String seedAccountType = null;
1845 PersistableBundle seedAccountOptions = null;
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001846 Bundle baseRestrictions = new Bundle();
1847 Bundle localRestrictions = new Bundle();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001848
1849 FileInputStream fis = null;
1850 try {
Amith Yamasani2a003292012-08-14 18:25:45 -07001851 AtomicFile userFile =
Amith Yamasanifc95e702013-09-26 13:20:17 -07001852 new AtomicFile(new File(mUsersDir, Integer.toString(id) + XML_SUFFIX));
Amith Yamasani2a003292012-08-14 18:25:45 -07001853 fis = userFile.openRead();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001854 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01001855 parser.setInput(fis, StandardCharsets.UTF_8.name());
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001856 int type;
1857 while ((type = parser.next()) != XmlPullParser.START_TAG
1858 && type != XmlPullParser.END_DOCUMENT) {
Amith Yamasani12747872015-12-07 14:19:49 -08001859 // Skip
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001860 }
1861
1862 if (type != XmlPullParser.START_TAG) {
Amith Yamasani0b285492011-04-14 17:35:23 -07001863 Slog.e(LOG_TAG, "Unable to read user " + id);
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001864 return null;
1865 }
1866
1867 if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_USER)) {
Amith Yamasani920ace02012-09-20 22:15:37 -07001868 int storedId = readIntAttribute(parser, ATTR_ID, -1);
1869 if (storedId != id) {
Amith Yamasani0b285492011-04-14 17:35:23 -07001870 Slog.e(LOG_TAG, "User id does not match the file name");
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001871 return null;
1872 }
Amith Yamasani920ace02012-09-20 22:15:37 -07001873 serialNumber = readIntAttribute(parser, ATTR_SERIAL_NO, id);
1874 flags = readIntAttribute(parser, ATTR_FLAGS, 0);
Amith Yamasanib8151ec2012-04-18 18:02:48 -07001875 iconPath = parser.getAttributeValue(null, ATTR_ICON_PATH);
Amith Yamasani920ace02012-09-20 22:15:37 -07001876 creationTime = readLongAttribute(parser, ATTR_CREATION_TIME, 0);
1877 lastLoggedInTime = readLongAttribute(parser, ATTR_LAST_LOGGED_IN_TIME, 0);
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06001878 lastLoggedInFingerprint = parser.getAttributeValue(null,
1879 ATTR_LAST_LOGGED_IN_FINGERPRINT);
Kenny Guy2a764942014-04-02 13:29:20 +01001880 profileGroupId = readIntAttribute(parser, ATTR_PROFILE_GROUP_ID,
1881 UserInfo.NO_PROFILE_GROUP_ID);
Fyodor Kupolov06a484a2015-08-21 16:33:20 -07001882 restrictedProfileParentId = readIntAttribute(parser,
1883 ATTR_RESTRICTED_PROFILE_PARENT_ID, UserInfo.NO_PROFILE_GROUP_ID);
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07001884 String valueString = parser.getAttributeValue(null, ATTR_PARTIAL);
1885 if ("true".equals(valueString)) {
1886 partial = true;
1887 }
Adam Lesinskieddeb492014-09-08 17:50:03 -07001888 valueString = parser.getAttributeValue(null, ATTR_GUEST_TO_REMOVE);
1889 if ("true".equals(valueString)) {
1890 guestToRemove = true;
1891 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001892
Amith Yamasani12747872015-12-07 14:19:49 -08001893 seedAccountName = parser.getAttributeValue(null, ATTR_SEED_ACCOUNT_NAME);
1894 seedAccountType = parser.getAttributeValue(null, ATTR_SEED_ACCOUNT_TYPE);
1895 if (seedAccountName != null || seedAccountType != null) {
1896 persistSeedData = true;
1897 }
1898
Amith Yamasanie4cf7342012-12-17 11:12:09 -08001899 int outerDepth = parser.getDepth();
1900 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1901 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1902 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1903 continue;
1904 }
1905 String tag = parser.getName();
1906 if (TAG_NAME.equals(tag)) {
1907 type = parser.next();
1908 if (type == XmlPullParser.TEXT) {
1909 name = parser.getText();
1910 }
1911 } else if (TAG_RESTRICTIONS.equals(tag)) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001912 UserRestrictionsUtils.readRestrictions(parser, baseRestrictions);
1913 } else if (TAG_DEVICE_POLICY_RESTRICTIONS.equals(tag)) {
1914 UserRestrictionsUtils.readRestrictions(parser, localRestrictions);
Xiaohui Chenb3b92582015-12-07 11:22:13 -08001915 } else if (TAG_ACCOUNT.equals(tag)) {
1916 type = parser.next();
1917 if (type == XmlPullParser.TEXT) {
1918 account = parser.getText();
1919 }
Amith Yamasani12747872015-12-07 14:19:49 -08001920 } else if (TAG_SEED_ACCOUNT_OPTIONS.equals(tag)) {
1921 seedAccountOptions = PersistableBundle.restoreFromXml(parser);
1922 persistSeedData = true;
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001923 }
1924 }
1925 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001926
Amith Yamasani12747872015-12-07 14:19:49 -08001927 // Create the UserInfo object that gets passed around
Amith Yamasanib8151ec2012-04-18 18:02:48 -07001928 UserInfo userInfo = new UserInfo(id, name, iconPath, flags);
Amith Yamasani2a003292012-08-14 18:25:45 -07001929 userInfo.serialNumber = serialNumber;
Amith Yamasani920ace02012-09-20 22:15:37 -07001930 userInfo.creationTime = creationTime;
1931 userInfo.lastLoggedInTime = lastLoggedInTime;
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06001932 userInfo.lastLoggedInFingerprint = lastLoggedInFingerprint;
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07001933 userInfo.partial = partial;
Adam Lesinskieddeb492014-09-08 17:50:03 -07001934 userInfo.guestToRemove = guestToRemove;
Kenny Guy2a764942014-04-02 13:29:20 +01001935 userInfo.profileGroupId = profileGroupId;
Fyodor Kupolov06a484a2015-08-21 16:33:20 -07001936 userInfo.restrictedProfileParentId = restrictedProfileParentId;
Amith Yamasani12747872015-12-07 14:19:49 -08001937
1938 // Create the UserData object that's internal to this class
1939 UserData userData = new UserData();
1940 userData.info = userInfo;
1941 userData.account = account;
1942 userData.seedAccountName = seedAccountName;
1943 userData.seedAccountType = seedAccountType;
1944 userData.persistSeedData = persistSeedData;
1945 userData.seedAccountOptions = seedAccountOptions;
1946
Makoto Onuki068c54a2015-10-13 14:34:03 -07001947 synchronized (mRestrictionsLock) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001948 mBaseUserRestrictions.put(id, baseRestrictions);
1949 mDevicePolicyLocalUserRestrictions.put(id, localRestrictions);
Makoto Onuki068c54a2015-10-13 14:34:03 -07001950 }
Amith Yamasani12747872015-12-07 14:19:49 -08001951 return userData;
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001952 } catch (IOException ioe) {
1953 } catch (XmlPullParserException pe) {
Dianne Hackbornbfd89b32011-12-15 18:22:54 -08001954 } finally {
1955 if (fis != null) {
1956 try {
1957 fis.close();
1958 } catch (IOException e) {
1959 }
1960 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001961 }
1962 return null;
1963 }
1964
Amith Yamasani920ace02012-09-20 22:15:37 -07001965 private int readIntAttribute(XmlPullParser parser, String attr, int defaultValue) {
1966 String valueString = parser.getAttributeValue(null, attr);
1967 if (valueString == null) return defaultValue;
1968 try {
1969 return Integer.parseInt(valueString);
1970 } catch (NumberFormatException nfe) {
1971 return defaultValue;
1972 }
1973 }
1974
1975 private long readLongAttribute(XmlPullParser parser, String attr, long defaultValue) {
1976 String valueString = parser.getAttributeValue(null, attr);
1977 if (valueString == null) return defaultValue;
1978 try {
1979 return Long.parseLong(valueString);
1980 } catch (NumberFormatException nfe) {
1981 return defaultValue;
1982 }
1983 }
1984
Amith Yamasanib82add22013-07-09 11:24:44 -07001985 /**
Amith Yamasani1a7472e2013-07-02 11:17:30 -07001986 * Removes the app restrictions file for a specific package and user id, if it exists.
1987 */
1988 private void cleanAppRestrictionsForPackage(String pkg, int userId) {
1989 synchronized (mPackagesLock) {
1990 File dir = Environment.getUserSystemDirectory(userId);
Amith Yamasanifc95e702013-09-26 13:20:17 -07001991 File resFile = new File(dir, packageToRestrictionsFileName(pkg));
Amith Yamasani1a7472e2013-07-02 11:17:30 -07001992 if (resFile.exists()) {
1993 resFile.delete();
1994 }
1995 }
1996 }
1997
Kenny Guya52dc3e2014-02-11 15:33:14 +00001998 @Override
Kenny Guy2a764942014-04-02 13:29:20 +01001999 public UserInfo createProfileForUser(String name, int flags, int userId) {
Kenny Guya52dc3e2014-02-11 15:33:14 +00002000 checkManageUsersPermission("Only the system can create users");
Kenny Guy2a764942014-04-02 13:29:20 +01002001 return createUserInternal(name, flags, userId);
Kenny Guya52dc3e2014-02-11 15:33:14 +00002002 }
2003
Amith Yamasani258848d2012-08-10 17:06:33 -07002004 @Override
Amith Yamasani13593602012-03-22 16:16:17 -07002005 public UserInfo createUser(String name, int flags) {
Amith Yamasani2a003292012-08-14 18:25:45 -07002006 checkManageUsersPermission("Only the system can create users");
Nicolas Prevotc6d033e2014-02-27 13:11:09 +00002007 return createUserInternal(name, flags, UserHandle.USER_NULL);
Kenny Guya52dc3e2014-02-11 15:33:14 +00002008 }
Amith Yamasanifaea76f2012-09-11 10:59:48 -07002009
Jessica Hummelbe81c802014-04-22 15:49:22 +01002010 private UserInfo createUserInternal(String name, int flags, int parentId) {
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002011 if (hasUserRestriction(UserManager.DISALLOW_ADD_USER, UserHandle.getCallingUserId())) {
Julia Reynolds75175022014-06-26 16:35:00 -04002012 Log.w(LOG_TAG, "Cannot add user. DISALLOW_ADD_USER is enabled.");
2013 return null;
2014 }
phweisse9c44062016-02-10 12:57:38 +01002015 return createUserInternalUnchecked(name, flags, parentId);
2016 }
2017
2018 private UserInfo createUserInternalUnchecked(String name, int flags, int parentId) {
Nicolas Prevot12678a92015-05-13 12:15:03 -07002019 if (ActivityManager.isLowRamDeviceStatic()) {
2020 return null;
2021 }
Amith Yamasani95ab7842014-08-11 17:09:26 -07002022 final boolean isGuest = (flags & UserInfo.FLAG_GUEST) != 0;
Nicolas Prevot12678a92015-05-13 12:15:03 -07002023 final boolean isManagedProfile = (flags & UserInfo.FLAG_MANAGED_PROFILE) != 0;
Fyodor Kupolov06a484a2015-08-21 16:33:20 -07002024 final boolean isRestricted = (flags & UserInfo.FLAG_RESTRICTED) != 0;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002025 final long ident = Binder.clearCallingIdentity();
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002026 UserInfo userInfo;
Amith Yamasani12747872015-12-07 14:19:49 -08002027 UserData userData;
Amith Yamasanibb054c92015-07-09 14:16:27 -07002028 final int userId;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002029 try {
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002030 synchronized (mPackagesLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08002031 UserData parent = null;
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002032 if (parentId != UserHandle.USER_NULL) {
2033 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08002034 parent = getUserDataLU(parentId);
Nicolas Prevotc6d033e2014-02-27 13:11:09 +00002035 }
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002036 if (parent == null) return null;
2037 }
2038 if (isManagedProfile && !canAddMoreManagedProfiles(parentId, false)) {
2039 Log.e(LOG_TAG, "Cannot add more managed profiles for user " + parentId);
2040 return null;
2041 }
2042 if (!isGuest && !isManagedProfile && isUserLimitReached()) {
2043 // If we're not adding a guest user or a managed profile and the limit has
2044 // been reached, cannot add a user.
2045 return null;
2046 }
2047 // If we're adding a guest and there already exists one, bail.
2048 if (isGuest && findCurrentGuestUser() != null) {
2049 return null;
2050 }
2051 // In legacy mode, restricted profile's parent can only be the owner user
2052 if (isRestricted && !UserManager.isSplitSystemUser()
2053 && (parentId != UserHandle.USER_SYSTEM)) {
2054 Log.w(LOG_TAG, "Cannot add restricted profile - parent user must be owner");
2055 return null;
2056 }
2057 if (isRestricted && UserManager.isSplitSystemUser()) {
2058 if (parent == null) {
2059 Log.w(LOG_TAG, "Cannot add restricted profile - parent user must be "
2060 + "specified");
Nicolas Prevot12678a92015-05-13 12:15:03 -07002061 return null;
2062 }
Amith Yamasani12747872015-12-07 14:19:49 -08002063 if (!parent.info.canHaveProfile()) {
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002064 Log.w(LOG_TAG, "Cannot add restricted profile - profiles cannot be "
2065 + "created for the specified parent user id " + parentId);
Amith Yamasani95ab7842014-08-11 17:09:26 -07002066 return null;
2067 }
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002068 }
Lenka Trochtova024f9792016-02-17 13:55:17 +01002069 if (!UserManager.isSplitSystemUser() && (flags & UserInfo.FLAG_EPHEMERAL) != 0) {
2070 Log.e(LOG_TAG,
2071 "Ephemeral users are supported on split-system-user systems only.");
2072 return null;
2073 }
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002074 // In split system user mode, we assign the first human user the primary flag.
2075 // And if there is no device owner, we also assign the admin flag to primary user.
2076 if (UserManager.isSplitSystemUser()
2077 && !isGuest && !isManagedProfile && getPrimaryUser() == null) {
2078 flags |= UserInfo.FLAG_PRIMARY;
Makoto Onukie7927da2015-11-25 10:05:17 -08002079 synchronized (mUsersLock) {
2080 if (!mIsDeviceManaged) {
2081 flags |= UserInfo.FLAG_ADMIN;
2082 }
Amith Yamasani95ab7842014-08-11 17:09:26 -07002083 }
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002084 }
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01002085
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +01002086 userId = getNextAvailableId();
2087 Environment.getUserSystemDirectory(userId).mkdirs();
Lenka Trochtova02fee152015-12-22 14:26:18 +01002088 boolean ephemeralGuests = Resources.getSystem()
2089 .getBoolean(com.android.internal.R.bool.config_guestUserEphemeral);
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +01002090
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002091 synchronized (mUsersLock) {
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +01002092 // Add ephemeral flag to guests/users if required. Also inherit it from parent.
2093 if ((isGuest && ephemeralGuests) || mForceEphemeralUsers
2094 || (parent != null && parent.info.isEphemeral())) {
2095 flags |= UserInfo.FLAG_EPHEMERAL;
2096 }
2097
2098 userInfo = new UserInfo(userId, name, null, flags);
2099 userInfo.serialNumber = mNextSerialNumber++;
2100 long now = System.currentTimeMillis();
2101 userInfo.creationTime = (now > EPOCH_PLUS_30_YEARS) ? now : 0;
2102 userInfo.partial = true;
Fyodor Kupolov83c24242016-03-31 13:30:42 -07002103 userInfo.lastLoggedInFingerprint = Build.FINGERPRINT;
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +01002104 userData = new UserData();
2105 userData.info = userInfo;
Amith Yamasani12747872015-12-07 14:19:49 -08002106 mUsers.put(userId, userData);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002107 }
Jeff Sharkeycd575992016-03-29 14:12:49 -06002108 writeUserLP(userData);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002109 writeUserListLP();
2110 if (parent != null) {
2111 if (isManagedProfile) {
Amith Yamasani12747872015-12-07 14:19:49 -08002112 if (parent.info.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
2113 parent.info.profileGroupId = parent.info.id;
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002114 writeUserLP(parent);
Kenny Guya52dc3e2014-02-11 15:33:14 +00002115 }
Amith Yamasani12747872015-12-07 14:19:49 -08002116 userInfo.profileGroupId = parent.info.profileGroupId;
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002117 } else if (isRestricted) {
Amith Yamasani12747872015-12-07 14:19:49 -08002118 if (parent.info.restrictedProfileParentId == UserInfo.NO_PROFILE_GROUP_ID) {
2119 parent.info.restrictedProfileParentId = parent.info.id;
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002120 writeUserLP(parent);
Jeff Sharkey6dce4962015-07-03 18:08:41 -07002121 }
Amith Yamasani12747872015-12-07 14:19:49 -08002122 userInfo.restrictedProfileParentId = parent.info.restrictedProfileParentId;
Makoto Onuki068c54a2015-10-13 14:34:03 -07002123 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002124 }
Dianne Hackborn4428e172012-08-24 17:43:05 -07002125 }
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002126 final StorageManager storage = mContext.getSystemService(StorageManager.class);
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01002127 storage.createUserKey(userId, userInfo.serialNumber, userInfo.isEphemeral());
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002128 mPm.prepareUserData(userId, userInfo.serialNumber,
Jeff Sharkey47f71082016-02-01 17:03:54 -07002129 StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002130 mPm.createNewUser(userId);
2131 userInfo.partial = false;
2132 synchronized (mPackagesLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08002133 writeUserLP(userData);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002134 }
2135 updateUserIds();
2136 Bundle restrictions = new Bundle();
Fyodor Kupolove04462c2015-11-30 15:02:53 -08002137 if (isGuest) {
2138 synchronized (mGuestRestrictions) {
2139 restrictions.putAll(mGuestRestrictions);
2140 }
2141 }
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002142 synchronized (mRestrictionsLock) {
2143 mBaseUserRestrictions.append(userId, restrictions);
2144 }
2145 mPm.newUserCreated(userId);
2146 Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
2147 addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
2148 mContext.sendBroadcastAsUser(addedIntent, UserHandle.ALL,
2149 android.Manifest.permission.MANAGE_USERS);
Fyodor Kupolov8385e4b2015-12-29 18:15:32 -08002150 MetricsLogger.count(mContext, isGuest ? TRON_GUEST_CREATED : TRON_USER_CREATED, 1);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002151 } finally {
2152 Binder.restoreCallingIdentity(ident);
Amith Yamasani258848d2012-08-10 17:06:33 -07002153 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002154 return userInfo;
2155 }
2156
Amith Yamasani0b285492011-04-14 17:35:23 -07002157 /**
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -07002158 * @hide
2159 */
Amith Yamasani12747872015-12-07 14:19:49 -08002160 @Override
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -07002161 public UserInfo createRestrictedProfile(String name, int parentUserId) {
2162 checkManageUsersPermission("setupRestrictedProfile");
2163 final UserInfo user = createProfileForUser(name, UserInfo.FLAG_RESTRICTED, parentUserId);
2164 if (user == null) {
2165 return null;
2166 }
Fyodor Kupolov9e912ba2016-02-09 18:29:43 -08002167 long identity = Binder.clearCallingIdentity();
2168 try {
2169 setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user.id);
2170 // Change the setting before applying the DISALLOW_SHARE_LOCATION restriction, otherwise
2171 // the putIntForUser() will fail.
2172 android.provider.Settings.Secure.putIntForUser(mContext.getContentResolver(),
2173 android.provider.Settings.Secure.LOCATION_MODE,
2174 android.provider.Settings.Secure.LOCATION_MODE_OFF, user.id);
2175 setUserRestriction(UserManager.DISALLOW_SHARE_LOCATION, true, user.id);
2176 } finally {
2177 Binder.restoreCallingIdentity(identity);
2178 }
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -07002179 return user;
2180 }
2181
2182 /**
Adam Lesinskieddeb492014-09-08 17:50:03 -07002183 * Find the current guest user. If the Guest user is partial,
2184 * then do not include it in the results as it is about to die.
Adam Lesinskieddeb492014-09-08 17:50:03 -07002185 */
Fyodor Kupolov82402752015-10-28 14:54:51 -07002186 private UserInfo findCurrentGuestUser() {
2187 synchronized (mUsersLock) {
2188 final int size = mUsers.size();
2189 for (int i = 0; i < size; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -08002190 final UserInfo user = mUsers.valueAt(i).info;
Fyodor Kupolov82402752015-10-28 14:54:51 -07002191 if (user.isGuest() && !user.guestToRemove && !mRemovingUserIds.get(user.id)) {
2192 return user;
2193 }
Adam Lesinskieddeb492014-09-08 17:50:03 -07002194 }
2195 }
2196 return null;
2197 }
2198
2199 /**
Amith Yamasani1df14732014-08-29 21:37:27 -07002200 * Mark this guest user for deletion to allow us to create another guest
2201 * and switch to that user before actually removing this guest.
2202 * @param userHandle the userid of the current guest
2203 * @return whether the user could be marked for deletion
2204 */
Amith Yamasani12747872015-12-07 14:19:49 -08002205 @Override
Amith Yamasani1df14732014-08-29 21:37:27 -07002206 public boolean markGuestForDeletion(int userHandle) {
2207 checkManageUsersPermission("Only the system can remove users");
2208 if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(
2209 UserManager.DISALLOW_REMOVE_USER, false)) {
2210 Log.w(LOG_TAG, "Cannot remove user. DISALLOW_REMOVE_USER is enabled.");
2211 return false;
2212 }
2213
2214 long ident = Binder.clearCallingIdentity();
2215 try {
Amith Yamasani12747872015-12-07 14:19:49 -08002216 final UserData userData;
Amith Yamasani1df14732014-08-29 21:37:27 -07002217 synchronized (mPackagesLock) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002218 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08002219 userData = mUsers.get(userHandle);
2220 if (userHandle == 0 || userData == null || mRemovingUserIds.get(userHandle)) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002221 return false;
2222 }
Amith Yamasani1df14732014-08-29 21:37:27 -07002223 }
Amith Yamasani12747872015-12-07 14:19:49 -08002224 if (!userData.info.isGuest()) {
Amith Yamasani1df14732014-08-29 21:37:27 -07002225 return false;
2226 }
Adam Lesinskieddeb492014-09-08 17:50:03 -07002227 // We set this to a guest user that is to be removed. This is a temporary state
2228 // where we are allowed to add new Guest users, even if this one is still not
2229 // removed. This user will still show up in getUserInfo() calls.
2230 // If we don't get around to removing this Guest user, it will be purged on next
2231 // startup.
Amith Yamasani12747872015-12-07 14:19:49 -08002232 userData.info.guestToRemove = true;
Amith Yamasani1df14732014-08-29 21:37:27 -07002233 // Mark it as disabled, so that it isn't returned any more when
2234 // profiles are queried.
Amith Yamasani12747872015-12-07 14:19:49 -08002235 userData.info.flags |= UserInfo.FLAG_DISABLED;
2236 writeUserLP(userData);
Amith Yamasani1df14732014-08-29 21:37:27 -07002237 }
2238 } finally {
2239 Binder.restoreCallingIdentity(ident);
2240 }
2241 return true;
2242 }
2243
2244 /**
Amith Yamasani0b285492011-04-14 17:35:23 -07002245 * Removes a user and all data directories created for that user. This method should be called
2246 * after the user's processes have been terminated.
Dianne Hackborn10ad9822014-03-17 11:28:36 -07002247 * @param userHandle the user's id
Amith Yamasani0b285492011-04-14 17:35:23 -07002248 */
Amith Yamasani12747872015-12-07 14:19:49 -08002249 @Override
Amith Yamasani258848d2012-08-10 17:06:33 -07002250 public boolean removeUser(int userHandle) {
Amith Yamasani2a003292012-08-14 18:25:45 -07002251 checkManageUsersPermission("Only the system can remove users");
Julia Reynolds4ac5f852014-06-23 17:38:51 -04002252 if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(
2253 UserManager.DISALLOW_REMOVE_USER, false)) {
2254 Log.w(LOG_TAG, "Cannot remove user. DISALLOW_REMOVE_USER is enabled.");
2255 return false;
2256 }
2257
Kenny Guyee58b4f2014-05-23 15:19:53 +01002258 long ident = Binder.clearCallingIdentity();
2259 try {
Amith Yamasani12747872015-12-07 14:19:49 -08002260 final UserData userData;
Fyodor Kupolov0df68cd2015-10-01 13:54:22 -07002261 int currentUser = ActivityManager.getCurrentUser();
2262 if (currentUser == userHandle) {
2263 Log.w(LOG_TAG, "Current user cannot be removed");
2264 return false;
2265 }
Kenny Guyee58b4f2014-05-23 15:19:53 +01002266 synchronized (mPackagesLock) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002267 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08002268 userData = mUsers.get(userHandle);
2269 if (userHandle == 0 || userData == null || mRemovingUserIds.get(userHandle)) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002270 return false;
2271 }
Jeff Sharkey6eb09392014-11-14 15:57:59 -08002272
Fyodor Kupolov82402752015-10-28 14:54:51 -07002273 // We remember deleted user IDs to prevent them from being
2274 // reused during the current boot; they can still be reused
2275 // after a reboot.
2276 mRemovingUserIds.put(userHandle, true);
2277 }
Jeff Sharkey6eb09392014-11-14 15:57:59 -08002278
Kenny Guyee58b4f2014-05-23 15:19:53 +01002279 try {
2280 mAppOpsService.removeUser(userHandle);
2281 } catch (RemoteException e) {
2282 Log.w(LOG_TAG, "Unable to notify AppOpsService of removing user", e);
2283 }
2284 // Set this to a partially created user, so that the user will be purged
2285 // on next startup, in case the runtime stops now before stopping and
2286 // removing the user completely.
Amith Yamasani12747872015-12-07 14:19:49 -08002287 userData.info.partial = true;
Kenny Guyee58b4f2014-05-23 15:19:53 +01002288 // Mark it as disabled, so that it isn't returned any more when
2289 // profiles are queried.
Amith Yamasani12747872015-12-07 14:19:49 -08002290 userData.info.flags |= UserInfo.FLAG_DISABLED;
2291 writeUserLP(userData);
Kenny Guyee58b4f2014-05-23 15:19:53 +01002292 }
2293
Amith Yamasani12747872015-12-07 14:19:49 -08002294 if (userData.info.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
2295 && userData.info.isManagedProfile()) {
Kenny Guyee58b4f2014-05-23 15:19:53 +01002296 // Send broadcast to notify system that the user removed was a
2297 // managed user.
Amith Yamasani12747872015-12-07 14:19:49 -08002298 sendProfileRemovedBroadcast(userData.info.profileGroupId, userData.info.id);
Kenny Guyee58b4f2014-05-23 15:19:53 +01002299 }
2300
2301 if (DBG) Slog.i(LOG_TAG, "Stopping user " + userHandle);
2302 int res;
2303 try {
Fyodor Kupolov9cbfc9e2015-10-07 15:52:33 -07002304 res = ActivityManagerNative.getDefault().stopUser(userHandle, /* force= */ true,
2305 new IStopUserCallback.Stub() {
Kenny Guyee58b4f2014-05-23 15:19:53 +01002306 @Override
2307 public void userStopped(int userId) {
2308 finishRemoveUser(userId);
2309 }
2310 @Override
2311 public void userStopAborted(int userId) {
2312 }
2313 });
2314 } catch (RemoteException e) {
Dianne Hackborn80a4af22012-08-27 19:18:31 -07002315 return false;
2316 }
Kenny Guyee58b4f2014-05-23 15:19:53 +01002317 return res == ActivityManager.USER_OP_SUCCESS;
2318 } finally {
2319 Binder.restoreCallingIdentity(ident);
Dianne Hackborn80a4af22012-08-27 19:18:31 -07002320 }
Dianne Hackborn80a4af22012-08-27 19:18:31 -07002321 }
2322
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07002323 void finishRemoveUser(final int userHandle) {
Amith Yamasani16389312012-10-17 21:20:14 -07002324 if (DBG) Slog.i(LOG_TAG, "finishRemoveUser " + userHandle);
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07002325 // Let other services shutdown any activity and clean up their state before completely
2326 // wiping the user's system directory and removing from the user list
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002327 long ident = Binder.clearCallingIdentity();
2328 try {
2329 Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
2330 addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle);
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07002331 mContext.sendOrderedBroadcastAsUser(addedIntent, UserHandle.ALL,
2332 android.Manifest.permission.MANAGE_USERS,
2333
2334 new BroadcastReceiver() {
2335 @Override
2336 public void onReceive(Context context, Intent intent) {
2337 if (DBG) {
2338 Slog.i(LOG_TAG,
2339 "USER_REMOVED broadcast sent, cleaning up user data "
2340 + userHandle);
2341 }
2342 new Thread() {
Amith Yamasani12747872015-12-07 14:19:49 -08002343 @Override
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07002344 public void run() {
Amith Yamasani515d4062015-09-28 11:30:06 -07002345 // Clean up any ActivityManager state
2346 LocalServices.getService(ActivityManagerInternal.class)
2347 .onUserRemoved(userHandle);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002348 removeUserState(userHandle);
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07002349 }
2350 }.start();
2351 }
2352 },
2353
2354 null, Activity.RESULT_OK, null, null);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002355 } finally {
2356 Binder.restoreCallingIdentity(ident);
2357 }
Amith Yamasani2a003292012-08-14 18:25:45 -07002358 }
2359
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002360 private void removeUserState(final int userHandle) {
Paul Crowley91293792016-03-25 15:23:07 -07002361 try {
2362 mContext.getSystemService(StorageManager.class).destroyUserKey(userHandle);
2363 } catch (IllegalStateException e) {
2364 // This may be simply because the user was partially created.
2365 Slog.i(LOG_TAG,
2366 "Destroying key for user " + userHandle + " failed, continuing anyway", e);
2367 }
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002368
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07002369 // Cleanup package manager settings
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002370 mPm.cleanUpUser(this, userHandle);
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07002371 // Remove this user from the list
Fyodor Kupolov82402752015-10-28 14:54:51 -07002372 synchronized (mUsersLock) {
2373 mUsers.remove(userHandle);
Makoto Onukie7927da2015-11-25 10:05:17 -08002374 mIsUserManaged.delete(userHandle);
2375 }
2376 synchronized (mRestrictionsLock) {
2377 mBaseUserRestrictions.remove(userHandle);
2378 mAppliedUserRestrictions.remove(userHandle);
2379 mCachedEffectiveUserRestrictions.remove(userHandle);
2380 mDevicePolicyLocalUserRestrictions.remove(userHandle);
Fyodor Kupolov82402752015-10-28 14:54:51 -07002381 }
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07002382 // Update the user list
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002383 synchronized (mPackagesLock) {
2384 writeUserListLP();
2385 }
Jeff Sharkeycd575992016-03-29 14:12:49 -06002386 // Remove user file
2387 AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX));
2388 userFile.delete();
Fyodor Kupolov82402752015-10-28 14:54:51 -07002389 updateUserIds();
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07002390
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002391 // Now that we've purged all the metadata above, destroy the actual data
2392 // on disk; if we battery pull in here we'll finish cleaning up when
2393 // reconciling after reboot.
2394 mPm.destroyUserData(userHandle,
2395 StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
Amith Yamasani61f57372012-08-31 12:12:28 -07002396 }
2397
Kenny Guyf8d3a232014-05-15 16:09:52 +01002398 private void sendProfileRemovedBroadcast(int parentUserId, int removedUserId) {
Adam Connors7b66ed52014-04-14 11:58:10 +01002399 Intent managedProfileIntent = new Intent(Intent.ACTION_MANAGED_PROFILE_REMOVED);
Adam Connorsd4b584e2014-06-09 13:55:47 +01002400 managedProfileIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY |
2401 Intent.FLAG_RECEIVER_FOREGROUND);
Kenny Guyf8d3a232014-05-15 16:09:52 +01002402 managedProfileIntent.putExtra(Intent.EXTRA_USER, new UserHandle(removedUserId));
Jeff Sharkeyaf6ec292015-12-17 11:19:00 -07002403 managedProfileIntent.putExtra(Intent.EXTRA_USER_HANDLE, removedUserId);
Kenny Guyf8d3a232014-05-15 16:09:52 +01002404 mContext.sendBroadcastAsUser(managedProfileIntent, new UserHandle(parentUserId), null);
Adam Connors7b66ed52014-04-14 11:58:10 +01002405 }
2406
Amith Yamasani2a003292012-08-14 18:25:45 -07002407 @Override
Amith Yamasani7e99bc02013-04-16 18:24:51 -07002408 public Bundle getApplicationRestrictions(String packageName) {
2409 return getApplicationRestrictionsForUser(packageName, UserHandle.getCallingUserId());
2410 }
2411
2412 @Override
2413 public Bundle getApplicationRestrictionsForUser(String packageName, int userId) {
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002414 if (UserHandle.getCallingUserId() != userId
Amith Yamasani9429afb2013-04-10 18:40:51 -07002415 || !UserHandle.isSameApp(Binder.getCallingUid(), getUidForPackage(packageName))) {
Esteban Talavera5b9f1672015-12-11 15:22:34 +00002416 checkSystemOrRoot("get application restrictions for other users/apps");
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002417 }
2418 synchronized (mPackagesLock) {
2419 // Read the restrictions from XML
Fyodor Kupolov82402752015-10-28 14:54:51 -07002420 return readApplicationRestrictionsLP(packageName, userId);
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002421 }
2422 }
2423
2424 @Override
Amith Yamasani7e99bc02013-04-16 18:24:51 -07002425 public void setApplicationRestrictions(String packageName, Bundle restrictions,
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002426 int userId) {
Esteban Talavera5b9f1672015-12-11 15:22:34 +00002427 checkSystemOrRoot("set application restrictions");
Fyodor Kupolov0d88d542016-04-19 11:37:22 -07002428 if (restrictions != null) {
2429 restrictions.setDefusable(true);
2430 }
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002431 synchronized (mPackagesLock) {
Kenny Guyd21b2182014-07-17 16:38:55 +01002432 if (restrictions == null || restrictions.isEmpty()) {
2433 cleanAppRestrictionsForPackage(packageName, userId);
2434 } else {
2435 // Write the restrictions to XML
Fyodor Kupolov82402752015-10-28 14:54:51 -07002436 writeApplicationRestrictionsLP(packageName, restrictions, userId);
Kenny Guyd21b2182014-07-17 16:38:55 +01002437 }
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002438 }
Robin Lee66e5d962014-04-09 16:44:21 +01002439
Fyodor Kupolovd2846122016-02-11 18:06:34 -08002440 // Notify package of changes via an intent - only sent to explicitly registered receivers.
2441 Intent changeIntent = new Intent(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED);
2442 changeIntent.setPackage(packageName);
2443 changeIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
2444 mContext.sendBroadcastAsUser(changeIntent, UserHandle.of(userId));
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002445 }
2446
2447 private int getUidForPackage(String packageName) {
Amith Yamasani9429afb2013-04-10 18:40:51 -07002448 long ident = Binder.clearCallingIdentity();
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002449 try {
2450 return mContext.getPackageManager().getApplicationInfo(packageName,
Fyodor Kupolovd2846122016-02-11 18:06:34 -08002451 PackageManager.MATCH_UNINSTALLED_PACKAGES).uid;
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002452 } catch (NameNotFoundException nnfe) {
2453 return -1;
Amith Yamasani9429afb2013-04-10 18:40:51 -07002454 } finally {
2455 Binder.restoreCallingIdentity(ident);
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002456 }
2457 }
2458
Fyodor Kupolov82402752015-10-28 14:54:51 -07002459 private Bundle readApplicationRestrictionsLP(String packageName, int userId) {
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002460 AtomicFile restrictionsFile =
2461 new AtomicFile(new File(Environment.getUserSystemDirectory(userId),
2462 packageToRestrictionsFileName(packageName)));
Fyodor Kupolov82402752015-10-28 14:54:51 -07002463 return readApplicationRestrictionsLP(restrictionsFile);
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002464 }
2465
2466 @VisibleForTesting
Fyodor Kupolov82402752015-10-28 14:54:51 -07002467 static Bundle readApplicationRestrictionsLP(AtomicFile restrictionsFile) {
Amith Yamasani7e99bc02013-04-16 18:24:51 -07002468 final Bundle restrictions = new Bundle();
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002469 final ArrayList<String> values = new ArrayList<>();
Fyodor Kupolov6f34d362015-04-02 12:42:13 -07002470 if (!restrictionsFile.getBaseFile().exists()) {
Fyodor Kupolovf6ee2242015-04-06 10:15:07 -07002471 return restrictions;
Fyodor Kupolov6f34d362015-04-02 12:42:13 -07002472 }
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002473
2474 FileInputStream fis = null;
2475 try {
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002476 fis = restrictionsFile.openRead();
2477 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01002478 parser.setInput(fis, StandardCharsets.UTF_8.name());
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002479 XmlUtils.nextElement(parser);
2480 if (parser.getEventType() != XmlPullParser.START_TAG) {
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002481 Slog.e(LOG_TAG, "Unable to read restrictions file "
2482 + restrictionsFile.getBaseFile());
Amith Yamasani7e99bc02013-04-16 18:24:51 -07002483 return restrictions;
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002484 }
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002485 while (parser.next() != XmlPullParser.END_DOCUMENT) {
2486 readEntry(restrictions, values, parser);
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002487 }
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002488 } catch (IOException|XmlPullParserException e) {
2489 Log.w(LOG_TAG, "Error parsing " + restrictionsFile.getBaseFile(), e);
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002490 } finally {
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002491 IoUtils.closeQuietly(fis);
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002492 }
Amith Yamasani7e99bc02013-04-16 18:24:51 -07002493 return restrictions;
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002494 }
2495
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002496 private static void readEntry(Bundle restrictions, ArrayList<String> values,
2497 XmlPullParser parser) throws XmlPullParserException, IOException {
2498 int type = parser.getEventType();
2499 if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_ENTRY)) {
2500 String key = parser.getAttributeValue(null, ATTR_KEY);
2501 String valType = parser.getAttributeValue(null, ATTR_VALUE_TYPE);
2502 String multiple = parser.getAttributeValue(null, ATTR_MULTIPLE);
2503 if (multiple != null) {
2504 values.clear();
2505 int count = Integer.parseInt(multiple);
2506 while (count > 0 && (type = parser.next()) != XmlPullParser.END_DOCUMENT) {
2507 if (type == XmlPullParser.START_TAG
2508 && parser.getName().equals(TAG_VALUE)) {
2509 values.add(parser.nextText().trim());
2510 count--;
2511 }
2512 }
2513 String [] valueStrings = new String[values.size()];
2514 values.toArray(valueStrings);
2515 restrictions.putStringArray(key, valueStrings);
2516 } else if (ATTR_TYPE_BUNDLE.equals(valType)) {
2517 restrictions.putBundle(key, readBundleEntry(parser, values));
2518 } else if (ATTR_TYPE_BUNDLE_ARRAY.equals(valType)) {
2519 final int outerDepth = parser.getDepth();
2520 ArrayList<Bundle> bundleList = new ArrayList<>();
2521 while (XmlUtils.nextElementWithin(parser, outerDepth)) {
2522 Bundle childBundle = readBundleEntry(parser, values);
2523 bundleList.add(childBundle);
2524 }
2525 restrictions.putParcelableArray(key,
2526 bundleList.toArray(new Bundle[bundleList.size()]));
2527 } else {
2528 String value = parser.nextText().trim();
2529 if (ATTR_TYPE_BOOLEAN.equals(valType)) {
2530 restrictions.putBoolean(key, Boolean.parseBoolean(value));
2531 } else if (ATTR_TYPE_INTEGER.equals(valType)) {
2532 restrictions.putInt(key, Integer.parseInt(value));
2533 } else {
2534 restrictions.putString(key, value);
2535 }
2536 }
2537 }
2538 }
2539
2540 private static Bundle readBundleEntry(XmlPullParser parser, ArrayList<String> values)
2541 throws IOException, XmlPullParserException {
2542 Bundle childBundle = new Bundle();
2543 final int outerDepth = parser.getDepth();
2544 while (XmlUtils.nextElementWithin(parser, outerDepth)) {
2545 readEntry(childBundle, values, parser);
2546 }
2547 return childBundle;
2548 }
2549
Fyodor Kupolov82402752015-10-28 14:54:51 -07002550 private void writeApplicationRestrictionsLP(String packageName,
Amith Yamasani7e99bc02013-04-16 18:24:51 -07002551 Bundle restrictions, int userId) {
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002552 AtomicFile restrictionsFile = new AtomicFile(
2553 new File(Environment.getUserSystemDirectory(userId),
Amith Yamasanifc95e702013-09-26 13:20:17 -07002554 packageToRestrictionsFileName(packageName)));
Fyodor Kupolov82402752015-10-28 14:54:51 -07002555 writeApplicationRestrictionsLP(restrictions, restrictionsFile);
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002556 }
2557
2558 @VisibleForTesting
Fyodor Kupolov82402752015-10-28 14:54:51 -07002559 static void writeApplicationRestrictionsLP(Bundle restrictions, AtomicFile restrictionsFile) {
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002560 FileOutputStream fos = null;
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002561 try {
2562 fos = restrictionsFile.startWrite();
2563 final BufferedOutputStream bos = new BufferedOutputStream(fos);
2564
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002565 final XmlSerializer serializer = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01002566 serializer.setOutput(bos, StandardCharsets.UTF_8.name());
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002567 serializer.startDocument(null, true);
2568 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
2569
2570 serializer.startTag(null, TAG_RESTRICTIONS);
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002571 writeBundle(restrictions, serializer);
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002572 serializer.endTag(null, TAG_RESTRICTIONS);
2573
2574 serializer.endDocument();
2575 restrictionsFile.finishWrite(fos);
2576 } catch (Exception e) {
2577 restrictionsFile.failWrite(fos);
Fyodor Kupolov262f9952015-03-23 18:55:11 -07002578 Slog.e(LOG_TAG, "Error writing application restrictions list", e);
2579 }
2580 }
2581
2582 private static void writeBundle(Bundle restrictions, XmlSerializer serializer)
2583 throws IOException {
2584 for (String key : restrictions.keySet()) {
2585 Object value = restrictions.get(key);
2586 serializer.startTag(null, TAG_ENTRY);
2587 serializer.attribute(null, ATTR_KEY, key);
2588
2589 if (value instanceof Boolean) {
2590 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BOOLEAN);
2591 serializer.text(value.toString());
2592 } else if (value instanceof Integer) {
2593 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_INTEGER);
2594 serializer.text(value.toString());
2595 } else if (value == null || value instanceof String) {
2596 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_STRING);
2597 serializer.text(value != null ? (String) value : "");
2598 } else if (value instanceof Bundle) {
2599 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BUNDLE);
2600 writeBundle((Bundle) value, serializer);
2601 } else if (value instanceof Parcelable[]) {
2602 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BUNDLE_ARRAY);
2603 Parcelable[] array = (Parcelable[]) value;
2604 for (Parcelable parcelable : array) {
2605 if (!(parcelable instanceof Bundle)) {
2606 throw new IllegalArgumentException("bundle-array can only hold Bundles");
2607 }
2608 serializer.startTag(null, TAG_ENTRY);
2609 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BUNDLE);
2610 writeBundle((Bundle) parcelable, serializer);
2611 serializer.endTag(null, TAG_ENTRY);
2612 }
2613 } else {
2614 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_STRING_ARRAY);
2615 String[] values = (String[]) value;
2616 serializer.attribute(null, ATTR_MULTIPLE, Integer.toString(values.length));
2617 for (String choice : values) {
2618 serializer.startTag(null, TAG_VALUE);
2619 serializer.text(choice != null ? choice : "");
2620 serializer.endTag(null, TAG_VALUE);
2621 }
2622 }
2623 serializer.endTag(null, TAG_ENTRY);
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08002624 }
2625 }
2626
2627 @Override
Amith Yamasani2a003292012-08-14 18:25:45 -07002628 public int getUserSerialNumber(int userHandle) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002629 synchronized (mUsersLock) {
Amith Yamasani2a003292012-08-14 18:25:45 -07002630 if (!exists(userHandle)) return -1;
Fyodor Kupolov82402752015-10-28 14:54:51 -07002631 return getUserInfoLU(userHandle).serialNumber;
Amith Yamasani2a003292012-08-14 18:25:45 -07002632 }
2633 }
2634
2635 @Override
2636 public int getUserHandle(int userSerialNumber) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002637 synchronized (mUsersLock) {
Amith Yamasani2a003292012-08-14 18:25:45 -07002638 for (int userId : mUserIds) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002639 UserInfo info = getUserInfoLU(userId);
Kenny Guy945f8832015-02-10 15:17:26 +00002640 if (info != null && info.serialNumber == userSerialNumber) return userId;
Amith Yamasani2a003292012-08-14 18:25:45 -07002641 }
2642 // Not found
2643 return -1;
Amith Yamasani13593602012-03-22 16:16:17 -07002644 }
2645 }
2646
Fyodor Kupolovff7233e2015-04-08 11:28:52 -07002647 @Override
2648 public long getUserCreationTime(int userHandle) {
2649 int callingUserId = UserHandle.getCallingUserId();
2650 UserInfo userInfo = null;
Fyodor Kupolov82402752015-10-28 14:54:51 -07002651 synchronized (mUsersLock) {
Fyodor Kupolovff7233e2015-04-08 11:28:52 -07002652 if (callingUserId == userHandle) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002653 userInfo = getUserInfoLU(userHandle);
Fyodor Kupolovff7233e2015-04-08 11:28:52 -07002654 } else {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002655 UserInfo parent = getProfileParentLU(userHandle);
Fyodor Kupolovff7233e2015-04-08 11:28:52 -07002656 if (parent != null && parent.id == callingUserId) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002657 userInfo = getUserInfoLU(userHandle);
Fyodor Kupolovff7233e2015-04-08 11:28:52 -07002658 }
2659 }
2660 }
2661 if (userInfo == null) {
2662 throw new SecurityException("userHandle can only be the calling user or a managed "
2663 + "profile associated with this user");
2664 }
2665 return userInfo.creationTime;
2666 }
2667
Amith Yamasani0b285492011-04-14 17:35:23 -07002668 /**
2669 * Caches the list of user ids in an array, adjusting the array size when necessary.
2670 */
Fyodor Kupolov82402752015-10-28 14:54:51 -07002671 private void updateUserIds() {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07002672 int num = 0;
Fyodor Kupolov82402752015-10-28 14:54:51 -07002673 synchronized (mUsersLock) {
2674 final int userSize = mUsers.size();
2675 for (int i = 0; i < userSize; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -08002676 if (!mUsers.valueAt(i).info.partial) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002677 num++;
2678 }
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07002679 }
Fyodor Kupolov82402752015-10-28 14:54:51 -07002680 final int[] newUsers = new int[num];
2681 int n = 0;
2682 for (int i = 0; i < userSize; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -08002683 if (!mUsers.valueAt(i).info.partial) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002684 newUsers[n++] = mUsers.keyAt(i);
2685 }
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07002686 }
Fyodor Kupolov82402752015-10-28 14:54:51 -07002687 mUserIds = newUsers;
Amith Yamasani0b285492011-04-14 17:35:23 -07002688 }
2689 }
2690
2691 /**
Jeff Sharkey0e62384c2016-01-13 18:52:55 -07002692 * Called right before a user is started. This gives us a chance to prepare
2693 * app storage and apply any user restrictions.
Makoto Onuki1a2cd742015-11-16 13:51:27 -08002694 */
2695 public void onBeforeStartUser(int userId) {
Jeff Sharkey47f71082016-02-01 17:03:54 -07002696 final int userSerial = getUserSerialNumber(userId);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002697 mPm.prepareUserData(userId, userSerial, StorageManager.FLAG_STORAGE_DE);
Jeff Sharkey47f71082016-02-01 17:03:54 -07002698 mPm.reconcileAppsData(userId, StorageManager.FLAG_STORAGE_DE);
Jeff Sharkey0e62384c2016-01-13 18:52:55 -07002699
2700 if (userId != UserHandle.USER_SYSTEM) {
2701 synchronized (mRestrictionsLock) {
2702 applyUserRestrictionsLR(userId);
2703 }
Makoto Onuki1a2cd742015-11-16 13:51:27 -08002704 }
2705 }
2706
2707 /**
Jeff Sharkey0e62384c2016-01-13 18:52:55 -07002708 * Called right before a user is unlocked. This gives us a chance to prepare
2709 * app storage.
2710 */
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06002711 public void onBeforeUnlockUser(@UserIdInt int userId) {
Jeff Sharkey47f71082016-02-01 17:03:54 -07002712 final int userSerial = getUserSerialNumber(userId);
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06002713 mPm.prepareUserData(userId, userSerial, StorageManager.FLAG_STORAGE_CE);
Jeff Sharkey47f71082016-02-01 17:03:54 -07002714 mPm.reconcileAppsData(userId, StorageManager.FLAG_STORAGE_CE);
Jeff Sharkey0e62384c2016-01-13 18:52:55 -07002715 }
2716
2717 /**
Amith Yamasani1a7472e2013-07-02 11:17:30 -07002718 * Make a note of the last started time of a user and do some cleanup.
Amith Yamasani920ace02012-09-20 22:15:37 -07002719 * @param userId the user that was just foregrounded
2720 */
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06002721 public void onUserLoggedIn(@UserIdInt int userId) {
Amith Yamasani12747872015-12-07 14:19:49 -08002722 UserData userData = getUserDataNoChecks(userId);
2723 if (userData == null || userData.info.partial) {
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002724 Slog.w(LOG_TAG, "userForeground: unknown user #" + userId);
2725 return;
2726 }
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06002727
2728 final long now = System.currentTimeMillis();
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002729 if (now > EPOCH_PLUS_30_YEARS) {
Amith Yamasani12747872015-12-07 14:19:49 -08002730 userData.info.lastLoggedInTime = now;
Amith Yamasani920ace02012-09-20 22:15:37 -07002731 }
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06002732 userData.info.lastLoggedInFingerprint = Build.FINGERPRINT;
2733 scheduleWriteUser(userData);
Amith Yamasani920ace02012-09-20 22:15:37 -07002734 }
2735
2736 /**
Amith Yamasani0b285492011-04-14 17:35:23 -07002737 * Returns the next available user id, filling in any holes in the ids.
Amith Yamasani742a6712011-05-04 14:49:28 -07002738 * TODO: May not be a good idea to recycle ids, in case it results in confusion
2739 * for data and battery stats collection, or unexpected cross-talk.
Amith Yamasani0b285492011-04-14 17:35:23 -07002740 */
Fyodor Kupolov82402752015-10-28 14:54:51 -07002741 private int getNextAvailableId() {
2742 synchronized (mUsersLock) {
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -08002743 int i = MIN_USER_ID;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07002744 while (i < MAX_USER_ID) {
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -08002745 if (mUsers.indexOfKey(i) < 0 && !mRemovingUserIds.get(i)) {
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07002746 return i;
Amith Yamasani195263742012-08-21 15:40:12 -07002747 }
2748 i++;
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002749 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002750 }
Xiaohui Chen621b3fc2015-10-02 14:41:42 -07002751 throw new IllegalStateException("No user id available!");
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002752 }
Amith Yamasani920ace02012-09-20 22:15:37 -07002753
Amith Yamasanifc95e702013-09-26 13:20:17 -07002754 private String packageToRestrictionsFileName(String packageName) {
2755 return RESTRICTIONS_FILE_PREFIX + packageName + XML_SUFFIX;
2756 }
2757
Jeff Sharkey6dce4962015-07-03 18:08:41 -07002758 /**
Jeff Sharkey6dce4962015-07-03 18:08:41 -07002759 * Enforce that serial number stored in user directory inode matches the
2760 * given expected value. Gracefully sets the serial number if currently
2761 * undefined.
2762 *
2763 * @throws IOException when problem extracting serial number, or serial
2764 * number is mismatched.
2765 */
2766 public static void enforceSerialNumber(File file, int serialNumber) throws IOException {
2767 final int foundSerial = getSerialNumber(file);
2768 Slog.v(LOG_TAG, "Found " + file + " with serial number " + foundSerial);
2769
2770 if (foundSerial == -1) {
2771 Slog.d(LOG_TAG, "Serial number missing on " + file + "; assuming current is valid");
2772 try {
2773 setSerialNumber(file, serialNumber);
2774 } catch (IOException e) {
2775 Slog.w(LOG_TAG, "Failed to set serial number on " + file, e);
2776 }
2777
2778 } else if (foundSerial != serialNumber) {
2779 throw new IOException("Found serial number " + foundSerial
2780 + " doesn't match expected " + serialNumber);
2781 }
2782 }
2783
2784 /**
2785 * Set serial number stored in user directory inode.
2786 *
2787 * @throws IOException if serial number was already set
2788 */
2789 private static void setSerialNumber(File file, int serialNumber)
2790 throws IOException {
2791 try {
2792 final byte[] buf = Integer.toString(serialNumber).getBytes(StandardCharsets.UTF_8);
2793 Os.setxattr(file.getAbsolutePath(), XATTR_SERIAL, buf, OsConstants.XATTR_CREATE);
2794 } catch (ErrnoException e) {
2795 throw e.rethrowAsIOException();
2796 }
2797 }
2798
2799 /**
2800 * Return serial number stored in user directory inode.
2801 *
2802 * @return parsed serial number, or -1 if not set
2803 */
2804 private static int getSerialNumber(File file) throws IOException {
2805 try {
2806 final byte[] buf = new byte[256];
2807 final int len = Os.getxattr(file.getAbsolutePath(), XATTR_SERIAL, buf);
2808 final String serial = new String(buf, 0, len);
2809 try {
2810 return Integer.parseInt(serial);
2811 } catch (NumberFormatException e) {
2812 throw new IOException("Bad serial number: " + serial);
2813 }
2814 } catch (ErrnoException e) {
2815 if (e.errno == OsConstants.ENODATA) {
2816 return -1;
2817 } else {
2818 throw e.rethrowAsIOException();
2819 }
2820 }
2821 }
2822
Amith Yamasani920ace02012-09-20 22:15:37 -07002823 @Override
Amith Yamasani12747872015-12-07 14:19:49 -08002824 public void setSeedAccountData(int userId, String accountName, String accountType,
2825 PersistableBundle accountOptions, boolean persist) {
2826 checkManageUsersPermission("Require MANAGE_USERS permission to set user seed data");
2827 synchronized (mPackagesLock) {
2828 final UserData userData;
2829 synchronized (mUsersLock) {
2830 userData = getUserDataLU(userId);
2831 if (userData == null) {
2832 Slog.e(LOG_TAG, "No such user for settings seed data u=" + userId);
2833 return;
2834 }
2835 userData.seedAccountName = accountName;
2836 userData.seedAccountType = accountType;
2837 userData.seedAccountOptions = accountOptions;
2838 userData.persistSeedData = persist;
2839 }
2840 if (persist) {
2841 writeUserLP(userData);
2842 }
2843 }
2844 }
2845
2846 @Override
2847 public String getSeedAccountName() throws RemoteException {
2848 checkManageUsersPermission("Cannot get seed account information");
2849 synchronized (mUsersLock) {
2850 UserData userData = getUserDataLU(UserHandle.getCallingUserId());
2851 return userData.seedAccountName;
2852 }
2853 }
2854
2855 @Override
2856 public String getSeedAccountType() throws RemoteException {
2857 checkManageUsersPermission("Cannot get seed account information");
2858 synchronized (mUsersLock) {
2859 UserData userData = getUserDataLU(UserHandle.getCallingUserId());
2860 return userData.seedAccountType;
2861 }
2862 }
2863
2864 @Override
2865 public PersistableBundle getSeedAccountOptions() throws RemoteException {
2866 checkManageUsersPermission("Cannot get seed account information");
2867 synchronized (mUsersLock) {
2868 UserData userData = getUserDataLU(UserHandle.getCallingUserId());
2869 return userData.seedAccountOptions;
2870 }
2871 }
2872
2873 @Override
2874 public void clearSeedAccountData() throws RemoteException {
2875 checkManageUsersPermission("Cannot clear seed account information");
2876 synchronized (mPackagesLock) {
2877 UserData userData;
2878 synchronized (mUsersLock) {
2879 userData = getUserDataLU(UserHandle.getCallingUserId());
2880 if (userData == null) return;
2881 userData.clearSeedAccountData();
2882 }
2883 writeUserLP(userData);
2884 }
2885 }
2886
2887 @Override
2888 public boolean someUserHasSeedAccount(String accountName, String accountType)
2889 throws RemoteException {
2890 checkManageUsersPermission("Cannot check seed account information");
2891 synchronized (mUsersLock) {
2892 final int userSize = mUsers.size();
2893 for (int i = 0; i < userSize; i++) {
2894 final UserData data = mUsers.valueAt(i);
2895 if (data.info.isInitialized()) continue;
2896 if (data.seedAccountName == null || !data.seedAccountName.equals(accountName)) {
2897 continue;
2898 }
2899 if (data.seedAccountType == null || !data.seedAccountType.equals(accountType)) {
2900 continue;
2901 }
2902 return true;
2903 }
2904 }
2905 return false;
2906 }
2907
2908 @Override
Todd Kennedy60459ab2015-10-30 11:32:16 -07002909 public void onShellCommand(FileDescriptor in, FileDescriptor out,
2910 FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
2911 (new Shell()).exec(this, in, out, err, args, resultReceiver);
2912 }
2913
2914 int onShellCommand(Shell shell, String cmd) {
2915 if (cmd == null) {
2916 return shell.handleDefaultCommands(cmd);
2917 }
2918
2919 final PrintWriter pw = shell.getOutPrintWriter();
2920 try {
2921 switch(cmd) {
2922 case "list":
2923 return runList(pw);
2924 }
2925 } catch (RemoteException e) {
2926 pw.println("Remote exception: " + e);
2927 }
2928 return -1;
2929 }
2930
2931 private int runList(PrintWriter pw) throws RemoteException {
2932 final IActivityManager am = ActivityManagerNative.getDefault();
2933 final List<UserInfo> users = getUsers(false);
2934 if (users == null) {
2935 pw.println("Error: couldn't get users");
2936 return 1;
2937 } else {
2938 pw.println("Users:");
2939 for (int i = 0; i < users.size(); i++) {
Jeff Sharkeye17ac152015-11-06 22:40:29 -08002940 String running = am.isUserRunning(users.get(i).id, 0) ? " running" : "";
Todd Kennedy60459ab2015-10-30 11:32:16 -07002941 pw.println("\t" + users.get(i).toString() + running);
2942 }
2943 return 0;
2944 }
2945 }
2946
2947 @Override
Amith Yamasani920ace02012-09-20 22:15:37 -07002948 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2949 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
2950 != PackageManager.PERMISSION_GRANTED) {
2951 pw.println("Permission Denial: can't dump UserManager from from pid="
2952 + Binder.getCallingPid()
2953 + ", uid=" + Binder.getCallingUid()
2954 + " without permission "
2955 + android.Manifest.permission.DUMP);
2956 return;
2957 }
2958
2959 long now = System.currentTimeMillis();
2960 StringBuilder sb = new StringBuilder();
2961 synchronized (mPackagesLock) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002962 synchronized (mUsersLock) {
2963 pw.println("Users:");
2964 for (int i = 0; i < mUsers.size(); i++) {
Amith Yamasani12747872015-12-07 14:19:49 -08002965 UserData userData = mUsers.valueAt(i);
2966 if (userData == null) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002967 continue;
2968 }
Amith Yamasani12747872015-12-07 14:19:49 -08002969 UserInfo userInfo = userData.info;
2970 final int userId = userInfo.id;
2971 pw.print(" "); pw.print(userInfo);
2972 pw.print(" serialNo="); pw.print(userInfo.serialNumber);
Makoto Onukie7927da2015-11-25 10:05:17 -08002973 if (mRemovingUserIds.get(userId)) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002974 pw.print(" <removing> ");
2975 }
Amith Yamasani12747872015-12-07 14:19:49 -08002976 if (userInfo.partial) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002977 pw.print(" <partial>");
2978 }
2979 pw.println();
2980 pw.print(" Created: ");
Amith Yamasani12747872015-12-07 14:19:49 -08002981 if (userInfo.creationTime == 0) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002982 pw.println("<unknown>");
2983 } else {
2984 sb.setLength(0);
Amith Yamasani12747872015-12-07 14:19:49 -08002985 TimeUtils.formatDuration(now - userInfo.creationTime, sb);
Fyodor Kupolov82402752015-10-28 14:54:51 -07002986 sb.append(" ago");
2987 pw.println(sb);
2988 }
2989 pw.print(" Last logged in: ");
Amith Yamasani12747872015-12-07 14:19:49 -08002990 if (userInfo.lastLoggedInTime == 0) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002991 pw.println("<unknown>");
2992 } else {
2993 sb.setLength(0);
Amith Yamasani12747872015-12-07 14:19:49 -08002994 TimeUtils.formatDuration(now - userInfo.lastLoggedInTime, sb);
Fyodor Kupolov82402752015-10-28 14:54:51 -07002995 sb.append(" ago");
2996 pw.println(sb);
2997 }
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06002998 pw.print(" Last logged in fingerprint: ");
2999 pw.println(userInfo.lastLoggedInFingerprint);
Makoto Onukie7927da2015-11-25 10:05:17 -08003000 pw.print(" Has profile owner: ");
3001 pw.println(mIsUserManaged.get(userId));
Fyodor Kupolov82402752015-10-28 14:54:51 -07003002 pw.println(" Restrictions:");
3003 synchronized (mRestrictionsLock) {
3004 UserRestrictionsUtils.dumpRestrictions(
Amith Yamasani12747872015-12-07 14:19:49 -08003005 pw, " ", mBaseUserRestrictions.get(userInfo.id));
Makoto Onuki1a2cd742015-11-16 13:51:27 -08003006 pw.println(" Device policy local restrictions:");
3007 UserRestrictionsUtils.dumpRestrictions(
Amith Yamasani12747872015-12-07 14:19:49 -08003008 pw, " ", mDevicePolicyLocalUserRestrictions.get(userInfo.id));
Fyodor Kupolov82402752015-10-28 14:54:51 -07003009 pw.println(" Effective restrictions:");
3010 UserRestrictionsUtils.dumpRestrictions(
Amith Yamasani12747872015-12-07 14:19:49 -08003011 pw, " ", mCachedEffectiveUserRestrictions.get(userInfo.id));
Fyodor Kupolov82402752015-10-28 14:54:51 -07003012 }
Amith Yamasani12747872015-12-07 14:19:49 -08003013
3014 if (userData.account != null) {
3015 pw.print(" Account name: " + userData.account);
Xiaohui Chenb3b92582015-12-07 11:22:13 -08003016 pw.println();
3017 }
Amith Yamasani12747872015-12-07 14:19:49 -08003018
3019 if (userData.seedAccountName != null) {
3020 pw.print(" Seed account name: " + userData.seedAccountName);
3021 pw.println();
3022 if (userData.seedAccountType != null) {
3023 pw.print(" account type: " + userData.seedAccountType);
3024 pw.println();
3025 }
3026 if (userData.seedAccountOptions != null) {
3027 pw.print(" account options exist");
3028 pw.println();
3029 }
3030 }
Amith Yamasani920ace02012-09-20 22:15:37 -07003031 }
Amith Yamasani920ace02012-09-20 22:15:37 -07003032 }
Amith Yamasani12747872015-12-07 14:19:49 -08003033 pw.println();
Makoto Onuki1a2cd742015-11-16 13:51:27 -08003034 pw.println(" Device policy global restrictions:");
3035 synchronized (mRestrictionsLock) {
3036 UserRestrictionsUtils
3037 .dumpRestrictions(pw, " ", mDevicePolicyGlobalUserRestrictions);
3038 }
Makoto Onukia4f11972015-10-01 13:19:58 -07003039 pw.println();
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +01003040 pw.println(" Global restrictions owner id:" + mGlobalRestrictionOwnerUserId);
3041 pw.println();
Makoto Onuki1a2cd742015-11-16 13:51:27 -08003042 pw.println(" Guest restrictions:");
Fyodor Kupolove80085d2015-11-06 18:21:39 -08003043 synchronized (mGuestRestrictions) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08003044 UserRestrictionsUtils.dumpRestrictions(pw, " ", mGuestRestrictions);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08003045 }
Makoto Onukie7927da2015-11-25 10:05:17 -08003046 synchronized (mUsersLock) {
3047 pw.println();
3048 pw.println(" Device managed: " + mIsDeviceManaged);
3049 }
Amith Yamasani12747872015-12-07 14:19:49 -08003050 // Dump some capabilities
3051 pw.println();
3052 pw.println(" Max users: " + UserManager.getMaxSupportedUsers());
3053 pw.println(" Supports switchable users: " + UserManager.supportsMultipleUsers());
Lenka Trochtova02fee152015-12-22 14:26:18 +01003054 pw.println(" All guests ephemeral: " + Resources.getSystem().getBoolean(
3055 com.android.internal.R.bool.config_guestUserEphemeral));
Amith Yamasani920ace02012-09-20 22:15:37 -07003056 }
3057 }
Fyodor Kupolov75d0ea82014-12-15 16:21:07 -08003058
3059 final class MainHandler extends Handler {
3060
3061 @Override
3062 public void handleMessage(Message msg) {
3063 switch (msg.what) {
3064 case WRITE_USER_MSG:
3065 removeMessages(WRITE_USER_MSG, msg.obj);
3066 synchronized (mPackagesLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08003067 int userId = ((UserData) msg.obj).info.id;
3068 UserData userData = getUserDataNoChecks(userId);
3069 if (userData != null) {
3070 writeUserLP(userData);
Fyodor Kupolov75d0ea82014-12-15 16:21:07 -08003071 }
3072 }
3073 }
3074 }
3075 }
Amith Yamasanibb054c92015-07-09 14:16:27 -07003076
3077 /**
3078 * @param userId
3079 * @return whether the user has been initialized yet
3080 */
3081 boolean isInitialized(int userId) {
3082 return (getUserInfo(userId).flags & UserInfo.FLAG_INITIALIZED) != 0;
3083 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07003084
3085 private class LocalService extends UserManagerInternal {
Makoto Onuki068c54a2015-10-13 14:34:03 -07003086 @Override
Makoto Onuki1a2cd742015-11-16 13:51:27 -08003087 public void setDevicePolicyUserRestrictions(int userId, @NonNull Bundle localRestrictions,
3088 @Nullable Bundle globalRestrictions) {
Makoto Onuki2a3c3da2016-02-18 14:25:30 -08003089 UserManagerService.this.setDevicePolicyUserRestrictionsInner(userId, localRestrictions,
Makoto Onuki1a2cd742015-11-16 13:51:27 -08003090 globalRestrictions);
Makoto Onuki068c54a2015-10-13 14:34:03 -07003091 }
3092
3093 @Override
3094 public Bundle getBaseUserRestrictions(int userId) {
3095 synchronized (mRestrictionsLock) {
3096 return mBaseUserRestrictions.get(userId);
3097 }
3098 }
3099
3100 @Override
3101 public void setBaseUserRestrictionsByDpmsForMigration(
3102 int userId, Bundle baseRestrictions) {
3103 synchronized (mRestrictionsLock) {
3104 mBaseUserRestrictions.put(userId, new Bundle(baseRestrictions));
Fyodor Kupolov82402752015-10-28 14:54:51 -07003105 invalidateEffectiveUserRestrictionsLR(userId);
Makoto Onuki068c54a2015-10-13 14:34:03 -07003106 }
3107
Amith Yamasani12747872015-12-07 14:19:49 -08003108 final UserData userData = getUserDataNoChecks(userId);
Makoto Onuki068c54a2015-10-13 14:34:03 -07003109 synchronized (mPackagesLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08003110 if (userData != null) {
3111 writeUserLP(userData);
Makoto Onuki068c54a2015-10-13 14:34:03 -07003112 } else {
3113 Slog.w(LOG_TAG, "UserInfo not found for " + userId);
3114 }
3115 }
3116 }
Makoto Onukid45a4a22015-11-02 17:17:38 -08003117
3118 @Override
3119 public boolean getUserRestriction(int userId, String key) {
3120 return getUserRestrictions(userId).getBoolean(key);
3121 }
3122
3123 @Override
3124 public void addUserRestrictionsListener(UserRestrictionsListener listener) {
3125 synchronized (mUserRestrictionsListeners) {
3126 mUserRestrictionsListeners.add(listener);
3127 }
3128 }
3129
3130 @Override
3131 public void removeUserRestrictionsListener(UserRestrictionsListener listener) {
3132 synchronized (mUserRestrictionsListeners) {
3133 mUserRestrictionsListeners.remove(listener);
3134 }
3135 }
Makoto Onukie7927da2015-11-25 10:05:17 -08003136
3137 @Override
3138 public void setDeviceManaged(boolean isManaged) {
3139 synchronized (mUsersLock) {
3140 mIsDeviceManaged = isManaged;
3141 }
3142 }
3143
3144 @Override
3145 public void setUserManaged(int userId, boolean isManaged) {
3146 synchronized (mUsersLock) {
3147 mIsUserManaged.put(userId, isManaged);
3148 }
3149 }
Oleksandr Peletskyi7f1f1df2016-01-18 15:40:21 +01003150
3151 @Override
3152 public void setUserIcon(int userId, Bitmap bitmap) {
3153 long ident = Binder.clearCallingIdentity();
3154 try {
3155 synchronized (mPackagesLock) {
3156 UserData userData = getUserDataNoChecks(userId);
3157 if (userData == null || userData.info.partial) {
3158 Slog.w(LOG_TAG, "setUserIcon: unknown user #" + userId);
3159 return;
3160 }
3161 writeBitmapLP(userData.info, bitmap);
3162 writeUserLP(userData);
3163 }
3164 sendUserInfoChangedBroadcast(userId);
3165 } finally {
3166 Binder.restoreCallingIdentity(ident);
3167 }
3168 }
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +01003169
3170 @Override
3171 public void setForceEphemeralUsers(boolean forceEphemeralUsers) {
3172 synchronized (mUsersLock) {
3173 mForceEphemeralUsers = forceEphemeralUsers;
3174 }
3175 }
3176
3177 @Override
3178 public void removeAllUsers() {
3179 if (UserHandle.USER_SYSTEM == ActivityManager.getCurrentUser()) {
3180 // Remove the non-system users straight away.
3181 removeNonSystemUsers();
3182 } else {
3183 // Switch to the system user first and then remove the other users.
3184 BroadcastReceiver userSwitchedReceiver = new BroadcastReceiver() {
3185 @Override
3186 public void onReceive(Context context, Intent intent) {
3187 int userId =
3188 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
3189 if (userId != UserHandle.USER_SYSTEM) {
3190 return;
3191 }
3192 mContext.unregisterReceiver(this);
3193 removeNonSystemUsers();
3194 }
3195 };
3196 IntentFilter userSwitchedFilter = new IntentFilter();
3197 userSwitchedFilter.addAction(Intent.ACTION_USER_SWITCHED);
3198 mContext.registerReceiver(
3199 userSwitchedReceiver, userSwitchedFilter, null, mHandler);
3200
3201 // Switch to the system user.
3202 ActivityManager am =
3203 (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
3204 am.switchUser(UserHandle.USER_SYSTEM);
3205 }
3206 }
phweisse9c44062016-02-10 12:57:38 +01003207
3208 @Override
Lenka Trochtova1ddda472016-02-12 10:42:12 +01003209 public void onEphemeralUserStop(int userId) {
3210 synchronized (mUsersLock) {
3211 UserInfo userInfo = getUserInfoLU(userId);
3212 if (userInfo != null && userInfo.isEphemeral()) {
3213 // Do not allow switching back to the ephemeral user again as the user is going
3214 // to be deleted.
3215 userInfo.flags |= UserInfo.FLAG_DISABLED;
3216 if (userInfo.isGuest()) {
3217 // Indicate that the guest will be deleted after it stops.
3218 userInfo.guestToRemove = true;
3219 }
3220 }
3221 }
3222 }
3223
3224 @Override
phweisse9c44062016-02-10 12:57:38 +01003225 public UserInfo createUserEvenWhenDisallowed(String name, int flags) {
3226 UserInfo user = createUserInternalUnchecked(name, flags, UserHandle.USER_NULL);
3227 // Keep this in sync with UserManager.createUser
3228 if (user != null && !user.isAdmin()) {
3229 setUserRestriction(UserManager.DISALLOW_SMS, true, user.id);
3230 setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, true, user.id);
3231 }
3232 return user;
3233 }
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +01003234 }
3235
3236 /* Remove all the users except of the system one. */
3237 private void removeNonSystemUsers() {
3238 ArrayList<UserInfo> usersToRemove = new ArrayList<>();
3239 synchronized (mUsersLock) {
3240 final int userSize = mUsers.size();
3241 for (int i = 0; i < userSize; i++) {
3242 UserInfo ui = mUsers.valueAt(i).info;
3243 if (ui.id != UserHandle.USER_SYSTEM) {
3244 usersToRemove.add(ui);
3245 }
3246 }
3247 }
3248 for (UserInfo ui: usersToRemove) {
3249 removeUser(ui.id);
3250 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07003251 }
Todd Kennedy60459ab2015-10-30 11:32:16 -07003252
3253 private class Shell extends ShellCommand {
3254 @Override
3255 public int onCommand(String cmd) {
3256 return onShellCommand(this, cmd);
3257 }
3258
3259 @Override
3260 public void onHelp() {
3261 final PrintWriter pw = getOutPrintWriter();
3262 pw.println("User manager (user) commands:");
3263 pw.println(" help");
3264 pw.println(" Print this help text.");
3265 pw.println("");
3266 pw.println(" list");
3267 pw.println(" Prints all users on the system.");
3268 }
3269 }
Makoto Onuki1a2cd742015-11-16 13:51:27 -08003270
3271 private static void debug(String message) {
3272 Log.d(LOG_TAG, message +
3273 (DBG_WITH_STACKTRACE ? " called at\n" + Debug.getCallers(10, " ") : ""));
3274 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07003275}