blob: ca273babcefb28a400984be22a568be2f1c0484a [file] [log] [blame]
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.pm;
18
Benjamin Franzf02420c2016-04-04 18:52:21 +010019import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
20import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
21
Xiaohui Chenb3b92582015-12-07 11:22:13 -080022import android.Manifest;
Xiaohui Chen594f2082015-08-18 11:04:20 -070023import android.annotation.NonNull;
Makoto Onuki068c54a2015-10-13 14:34:03 -070024import android.annotation.Nullable;
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -060025import android.annotation.UserIdInt;
Amith Yamasanidb6a14c2012-10-17 21:16:52 -070026import android.app.Activity;
Amith Yamasani2a003292012-08-14 18:25:45 -070027import android.app.ActivityManager;
Amith Yamasani515d4062015-09-28 11:30:06 -070028import android.app.ActivityManagerInternal;
Andrew Scull85a63bc2016-10-24 13:47:47 +010029import android.app.ActivityManagerNative;
Todd Kennedy60459ab2015-10-30 11:32:16 -070030import android.app.IActivityManager;
Dianne Hackborn80a4af22012-08-27 19:18:31 -070031import android.app.IStopUserCallback;
Benjamin Franzf02420c2016-04-04 18:52:21 +010032import android.app.KeyguardManager;
Ricky Waib1dd80b2016-06-07 18:00:55 +010033import android.app.PendingIntent;
arangelov9b632d72018-12-07 23:21:22 +000034import android.app.admin.DevicePolicyEventLogger;
Amith Yamasanidb6a14c2012-10-17 21:16:52 -070035import android.content.BroadcastReceiver;
Amith Yamasani258848d2012-08-10 17:06:33 -070036import android.content.Context;
37import android.content.Intent;
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +010038import android.content.IntentFilter;
Benjamin Franzf02420c2016-04-04 18:52:21 +010039import android.content.IntentSender;
Amith Yamasani0b285492011-04-14 17:35:23 -070040import android.content.pm.PackageManager;
Amith Yamasanidf2e92a2013-03-01 17:04:38 -080041import android.content.pm.PackageManager.NameNotFoundException;
Tony Make3d1f652017-12-12 11:00:37 +000042import android.content.pm.ShortcutServiceInternal;
Amith Yamasani4b2e9342011-03-31 12:38:53 -070043import android.content.pm.UserInfo;
Felipe Lemec1ca4412019-09-11 09:23:26 -070044import android.content.pm.UserInfo.UserInfoFlag;
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;
Tony Mak64fd8c02017-12-01 19:11:59 +000055import android.os.IProgressListener;
Amith Yamasani258848d2012-08-10 17:06:33 -070056import android.os.IUserManager;
Fyodor Kupolov75d0ea82014-12-15 16:21:07 -080057import android.os.Message;
Adrian Roos1bdff912015-02-17 15:51:35 +010058import android.os.ParcelFileDescriptor;
Fyodor Kupolov262f9952015-03-23 18:55:11 -070059import android.os.Parcelable;
Amith Yamasani12747872015-12-07 14:19:49 -080060import android.os.PersistableBundle;
Amith Yamasani258848d2012-08-10 17:06:33 -070061import android.os.Process;
Dianne Hackborn80a4af22012-08-27 19:18:31 -070062import android.os.RemoteException;
Todd Kennedy60459ab2015-10-30 11:32:16 -070063import android.os.ResultReceiver;
Oleksandr Peletskyicd6fa302016-02-25 16:28:39 +010064import android.os.SELinux;
Jason Monk62062992014-05-06 09:55:28 -040065import android.os.ServiceManager;
Dianne Hackborn354736e2016-08-22 17:00:05 -070066import android.os.ShellCallback;
Todd Kennedy60459ab2015-10-30 11:32:16 -070067import android.os.ShellCommand;
Makoto Onuki73dded22017-12-20 13:14:48 +090068import android.os.SystemClock;
Kenny Guy02c89902016-11-15 19:36:38 +000069import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070070import android.os.UserHandle;
Jeff Sharkey27bd34d2012-09-16 12:49:00 -070071import android.os.UserManager;
Pavel Grafov6a40f092016-10-25 15:46:51 +010072import android.os.UserManager.EnforcingUser;
Makoto Onuki068c54a2015-10-13 14:34:03 -070073import android.os.UserManagerInternal;
Makoto Onukid45a4a22015-11-02 17:17:38 -080074import android.os.UserManagerInternal.UserRestrictionsListener;
Paul Crowley85e4e812015-05-19 12:42:00 +010075import android.os.storage.StorageManager;
Amith Yamasanid04aaa32016-06-13 12:09:36 -070076import android.security.GateKeeper;
77import android.service.gatekeeper.IGateKeeperService;
arangelov9b632d72018-12-07 23:21:22 +000078import android.stats.devicepolicy.DevicePolicyEnums;
Bookatz75f0a072019-08-05 14:12:16 -070079import android.util.ArraySet;
Amith Yamasani2a003292012-08-14 18:25:45 -070080import android.util.AtomicFile;
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -070081import android.util.IntArray;
Amith Yamasani655d0e22013-06-12 14:19:10 -070082import android.util.Log;
Amith Yamasani4b2e9342011-03-31 12:38:53 -070083import android.util.Slog;
84import android.util.SparseArray;
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -080085import android.util.SparseBooleanArray;
Amith Yamasaniea1b9d72016-05-27 15:57:38 +000086import android.util.SparseIntArray;
Amith Yamasani920ace02012-09-20 22:15:37 -070087import android.util.TimeUtils;
Amith Yamasani4b2e9342011-03-31 12:38:53 -070088import android.util.Xml;
89
Makoto Onuki068c54a2015-10-13 14:34:03 -070090import com.android.internal.annotations.GuardedBy;
Fyodor Kupolov262f9952015-03-23 18:55:11 -070091import com.android.internal.annotations.VisibleForTesting;
Jason Monk62062992014-05-06 09:55:28 -040092import com.android.internal.app.IAppOpsService;
Fyodor Kupolov8385e4b2015-12-29 18:15:32 -080093import com.android.internal.logging.MetricsLogger;
Fyodor Kupolova68a2862018-01-30 18:22:00 -080094import com.android.internal.os.BackgroundThread;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060095import com.android.internal.util.DumpUtils;
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -080096import com.android.internal.util.FastXmlSerializer;
Makoto Onuki068c54a2015-10-13 14:34:03 -070097import com.android.internal.util.Preconditions;
Fyodor Kupolov262f9952015-03-23 18:55:11 -070098import com.android.internal.util.XmlUtils;
Clara Bayarri10ad84a2015-12-01 17:38:05 +000099import com.android.internal.widget.LockPatternUtils;
Amith Yamasani515d4062015-09-28 11:30:06 -0700100import com.android.server.LocalServices;
Jeff Sharkey5f3e9342017-03-13 14:53:11 -0600101import com.android.server.LockGuard;
Amith Yamasanid04aaa32016-06-13 12:09:36 -0700102import com.android.server.SystemService;
Amith Yamasaniea1b9d72016-05-27 15:57:38 +0000103import com.android.server.am.UserState;
Suprabh Shuklac5e057c2016-08-08 16:22:44 -0700104import com.android.server.storage.DeviceStorageMonitorInternal;
Felipe Leme3aad1be2019-05-31 11:43:12 -0700105import com.android.server.utils.TimingsTraceAndSlog;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -0700106import com.android.server.wm.ActivityTaskManagerInternal;
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -0800107
arangelov9b632d72018-12-07 23:21:22 +0000108import libcore.io.IoUtils;
109
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -0800110import org.xmlpull.v1.XmlPullParser;
111import org.xmlpull.v1.XmlPullParserException;
112import org.xmlpull.v1.XmlSerializer;
113
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700114import java.io.BufferedOutputStream;
115import java.io.File;
Amith Yamasani920ace02012-09-20 22:15:37 -0700116import java.io.FileDescriptor;
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700117import java.io.FileInputStream;
Amith Yamasanib8151ec2012-04-18 18:02:48 -0700118import java.io.FileNotFoundException;
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700119import java.io.FileOutputStream;
Tony Mak64fd8c02017-12-01 19:11:59 +0000120import java.io.IOException;
Kenny Guy02c89902016-11-15 19:36:38 +0000121import java.io.InputStream;
122import java.io.OutputStream;
Amith Yamasani920ace02012-09-20 22:15:37 -0700123import java.io.PrintWriter;
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +0100124import java.nio.charset.StandardCharsets;
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700125import java.util.ArrayList;
Pavel Grafov6a40f092016-10-25 15:46:51 +0100126import java.util.Collections;
Fyodor Kupolov0f4533d2016-05-18 18:43:12 -0700127import java.util.LinkedList;
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700128import java.util.List;
Narayan Kamath607223f2018-02-19 14:09:02 +0000129import java.util.Objects;
Bookatz75f0a072019-08-05 14:12:16 -0700130import java.util.Set;
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700131
Makoto Onuki068c54a2015-10-13 14:34:03 -0700132/**
133 * Service for {@link UserManager}.
134 *
135 * Method naming convention:
Fyodor Kupolov82402752015-10-28 14:54:51 -0700136 * <ul>
Fyodor Kupolovd31cee92017-09-05 16:31:08 -0700137 * <li> Methods suffixed with "LAr" should be called within the {@link #mAppRestrictionsLock} lock.
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800138 * <li> Methods suffixed with "LP" should be called within the {@link #mPackagesLock} lock.
Fyodor Kupolov82402752015-10-28 14:54:51 -0700139 * <li> Methods suffixed with "LR" should be called within the {@link #mRestrictionsLock} lock.
140 * <li> Methods suffixed with "LU" should be called within the {@link #mUsersLock} lock.
141 * </ul>
Makoto Onuki068c54a2015-10-13 14:34:03 -0700142 */
Amith Yamasani258848d2012-08-10 17:06:33 -0700143public class UserManagerService extends IUserManager.Stub {
Amith Yamasanid04aaa32016-06-13 12:09:36 -0700144
Amith Yamasani2a003292012-08-14 18:25:45 -0700145 private static final String LOG_TAG = "UserManagerService";
Makoto Onuki81c61ea2016-01-22 11:22:26 -0800146 static final boolean DBG = false; // DO NOT SUBMIT WITH TRUE
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800147 private static final boolean DBG_WITH_STACKTRACE = false; // DO NOT SUBMIT WITH TRUE
Fyodor Kupolov0f4533d2016-05-18 18:43:12 -0700148 // Can be used for manual testing of id recycling
149 private static final boolean RELEASE_DELETED_USER_ID = false; // DO NOT SUBMIT WITH TRUE
Amith Yamasani16389312012-10-17 21:20:14 -0700150
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700151 private static final String TAG_NAME = "name";
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800152 private static final String TAG_ACCOUNT = "account";
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700153 private static final String ATTR_FLAGS = "flags";
Amith Yamasanib8151ec2012-04-18 18:02:48 -0700154 private static final String ATTR_ICON_PATH = "icon";
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700155 private static final String ATTR_ID = "id";
Amith Yamasani920ace02012-09-20 22:15:37 -0700156 private static final String ATTR_CREATION_TIME = "created";
157 private static final String ATTR_LAST_LOGGED_IN_TIME = "lastLoggedIn";
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -0600158 private static final String ATTR_LAST_LOGGED_IN_FINGERPRINT = "lastLoggedInFingerprint";
Amith Yamasani2a003292012-08-14 18:25:45 -0700159 private static final String ATTR_SERIAL_NO = "serialNumber";
160 private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber";
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700161 private static final String ATTR_PARTIAL = "partial";
Felipe Lemec1ca4412019-09-11 09:23:26 -0700162 private static final String ATTR_PRE_CREATED = "preCreated";
Adam Lesinskieddeb492014-09-08 17:50:03 -0700163 private static final String ATTR_GUEST_TO_REMOVE = "guestToRemove";
Amith Yamasani6f34b412012-10-22 18:19:27 -0700164 private static final String ATTR_USER_VERSION = "version";
Kenny Guy2a764942014-04-02 13:29:20 +0100165 private static final String ATTR_PROFILE_GROUP_ID = "profileGroupId";
Kenny Guy02c89902016-11-15 19:36:38 +0000166 private static final String ATTR_PROFILE_BADGE = "profileBadge";
Fyodor Kupolov06a484a2015-08-21 16:33:20 -0700167 private static final String ATTR_RESTRICTED_PROFILE_PARENT_ID = "restrictedProfileParentId";
Amith Yamasani12747872015-12-07 14:19:49 -0800168 private static final String ATTR_SEED_ACCOUNT_NAME = "seedAccountName";
169 private static final String ATTR_SEED_ACCOUNT_TYPE = "seedAccountType";
Amith Yamasanie4afaa32014-06-30 14:55:07 +0530170 private static final String TAG_GUEST_RESTRICTIONS = "guestRestrictions";
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700171 private static final String TAG_USERS = "users";
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700172 private static final String TAG_USER = "user";
Amith Yamasanie4cf7342012-12-17 11:12:09 -0800173 private static final String TAG_RESTRICTIONS = "restrictions";
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800174 private static final String TAG_DEVICE_POLICY_RESTRICTIONS = "device_policy_restrictions";
Pavel Grafov6a40f092016-10-25 15:46:51 +0100175 private static final String TAG_DEVICE_POLICY_GLOBAL_RESTRICTIONS =
176 "device_policy_global_restrictions";
177 /** Legacy name for device owner id tag. */
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +0100178 private static final String TAG_GLOBAL_RESTRICTION_OWNER_ID = "globalRestrictionOwnerUserId";
Pavel Grafov6a40f092016-10-25 15:46:51 +0100179 private static final String TAG_DEVICE_OWNER_USER_ID = "deviceOwnerUserId";
Amith Yamasanidf2e92a2013-03-01 17:04:38 -0800180 private static final String TAG_ENTRY = "entry";
181 private static final String TAG_VALUE = "value";
Amith Yamasani12747872015-12-07 14:19:49 -0800182 private static final String TAG_SEED_ACCOUNT_OPTIONS = "seedAccountOptions";
arangelov9b632d72018-12-07 23:21:22 +0000183 private static final String TAG_LAST_REQUEST_QUIET_MODE_ENABLED_CALL =
184 "lastRequestQuietModeEnabledCall";
Amith Yamasanidf2e92a2013-03-01 17:04:38 -0800185 private static final String ATTR_KEY = "key";
Amith Yamasani7e99bc02013-04-16 18:24:51 -0700186 private static final String ATTR_VALUE_TYPE = "type";
Amith Yamasanidf2e92a2013-03-01 17:04:38 -0800187 private static final String ATTR_MULTIPLE = "m";
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700188
Amith Yamasani7e99bc02013-04-16 18:24:51 -0700189 private static final String ATTR_TYPE_STRING_ARRAY = "sa";
190 private static final String ATTR_TYPE_STRING = "s";
191 private static final String ATTR_TYPE_BOOLEAN = "b";
Amith Yamasani5b5aa402014-06-01 20:10:14 -0700192 private static final String ATTR_TYPE_INTEGER = "i";
Fyodor Kupolov262f9952015-03-23 18:55:11 -0700193 private static final String ATTR_TYPE_BUNDLE = "B";
194 private static final String ATTR_TYPE_BUNDLE_ARRAY = "BA";
Amith Yamasani7e99bc02013-04-16 18:24:51 -0700195
Amith Yamasani0b285492011-04-14 17:35:23 -0700196 private static final String USER_INFO_DIR = "system" + File.separator + "users";
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700197 private static final String USER_LIST_FILENAME = "userlist.xml";
Amith Yamasanib8151ec2012-04-18 18:02:48 -0700198 private static final String USER_PHOTO_FILENAME = "photo.png";
Adrian Roos1bdff912015-02-17 15:51:35 +0100199 private static final String USER_PHOTO_FILENAME_TMP = USER_PHOTO_FILENAME + ".tmp";
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700200
Amith Yamasanidf2e92a2013-03-01 17:04:38 -0800201 private static final String RESTRICTIONS_FILE_PREFIX = "res_";
Amith Yamasanifc95e702013-09-26 13:20:17 -0700202 private static final String XML_SUFFIX = ".xml";
Amith Yamasanidf2e92a2013-03-01 17:04:38 -0800203
Sudheer Shankaf5cea032016-06-08 17:13:24 -0700204 private static final int ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION =
205 UserInfo.FLAG_MANAGED_PROFILE
206 | UserInfo.FLAG_EPHEMERAL
207 | UserInfo.FLAG_RESTRICTED
Sudheer Shanka234d1af2016-08-26 15:42:53 -0700208 | UserInfo.FLAG_GUEST
209 | UserInfo.FLAG_DEMO;
Sudheer Shankaf5cea032016-06-08 17:13:24 -0700210
Fyodor Kupolov0f4533d2016-05-18 18:43:12 -0700211 @VisibleForTesting
212 static final int MIN_USER_ID = 10;
Xiaohui Chen621b3fc2015-10-02 14:41:42 -0700213 // We need to keep process uid within Integer.MAX_VALUE.
Fyodor Kupolov0f4533d2016-05-18 18:43:12 -0700214 @VisibleForTesting
215 static final int MAX_USER_ID = Integer.MAX_VALUE / UserHandle.PER_USER_RANGE;
216
217 // Max size of the queue of recently removed users
218 @VisibleForTesting
219 static final int MAX_RECENTLY_REMOVED_IDS_SIZE = 100;
Amith Yamasani634cf312012-10-04 17:34:21 -0700220
Bookatz75f0a072019-08-05 14:12:16 -0700221 private static final int USER_VERSION = 8;
Amith Yamasani6f34b412012-10-22 18:19:27 -0700222
Amith Yamasani920ace02012-09-20 22:15:37 -0700223 private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // ms
224
Nicolas Prevotb8186812015-08-06 15:00:03 +0100225 // Maximum number of managed profiles permitted per user is 1. This cannot be increased
Amith Yamasani95ab7842014-08-11 17:09:26 -0700226 // without first making sure that the rest of the framework is prepared for it.
Kenny Guy02c89902016-11-15 19:36:38 +0000227 @VisibleForTesting
228 static final int MAX_MANAGED_PROFILES = 1;
Amith Yamasani95ab7842014-08-11 17:09:26 -0700229
Fyodor Kupolov75d0ea82014-12-15 16:21:07 -0800230 static final int WRITE_USER_MSG = 1;
231 static final int WRITE_USER_DELAY = 2*1000; // 2 seconds
Amith Yamasanie4afaa32014-06-30 14:55:07 +0530232
Fyodor Kupolov8385e4b2015-12-29 18:15:32 -0800233 // Tron counters
234 private static final String TRON_GUEST_CREATED = "users_guest_created";
235 private static final String TRON_USER_CREATED = "users_user_created";
Christine Franks88220562017-05-24 11:11:21 -0700236 private static final String TRON_DEMO_CREATED = "users_demo_created";
Fyodor Kupolov8385e4b2015-12-29 18:15:32 -0800237
Dianne Hackborn4428e172012-08-24 17:43:05 -0700238 private final Context mContext;
239 private final PackageManagerService mPm;
Dianne Hackborn4428e172012-08-24 17:43:05 -0700240 private final Object mPackagesLock;
Fyodor Kupolov5c0ecfd2017-01-27 11:11:57 -0800241 private final UserDataPreparer mUserDataPreparer;
Fyodor Kupolov82402752015-10-28 14:54:51 -0700242 // Short-term lock for internal state, when interaction/sync with PM is not required
Jeff Sharkey5f3e9342017-03-13 14:53:11 -0600243 private final Object mUsersLock = LockGuard.installNewLock(LockGuard.INDEX_USER);
Fyodor Kupolov82402752015-10-28 14:54:51 -0700244 private final Object mRestrictionsLock = new Object();
Fyodor Kupolovd31cee92017-09-05 16:31:08 -0700245 // Used for serializing access to app restriction files
246 private final Object mAppRestrictionsLock = new Object();
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700247
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -0800248 private final Handler mHandler;
249
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700250 private final File mUsersDir;
251 private final File mUserListFile;
Dianne Hackborn4428e172012-08-24 17:43:05 -0700252
Svet Ganov9cea80cd2016-02-16 11:47:00 -0800253 private static final IBinder mUserRestriconToken = new Binder();
254
Bookatz04d7ae52019-08-05 14:07:12 -0700255 /** Installs system packages based on user-type. */
256 private final UserSystemPackageInstaller mSystemPackageInstaller;
257
Makoto Onuki068c54a2015-10-13 14:34:03 -0700258 /**
Makoto Onuki73dded22017-12-20 13:14:48 +0900259 * Internal non-parcelable wrapper for UserInfo that is not exposed to other system apps.
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800260 */
Kenny Guy02c89902016-11-15 19:36:38 +0000261 @VisibleForTesting
262 static class UserData {
Amith Yamasani12747872015-12-07 14:19:49 -0800263 // Basic user information and properties
264 UserInfo info;
265 // Account name used when there is a strong association between a user and an account
266 String account;
267 // Account information for seeding into a newly created user. This could also be
268 // used for login validation for an existing user, for updating their credentials.
269 // In the latter case, data may not need to be persisted as it is only valid for the
270 // current login session.
271 String seedAccountName;
272 String seedAccountType;
273 PersistableBundle seedAccountOptions;
274 // Whether to perist the seed account information to be available after a boot
275 boolean persistSeedData;
276
Makoto Onuki73dded22017-12-20 13:14:48 +0900277 /** Elapsed realtime since boot when the user started. */
278 long startRealtime;
279
280 /** Elapsed realtime since boot when the user was unlocked. */
281 long unlockRealtime;
282
arangelov9b632d72018-12-07 23:21:22 +0000283 private long mLastRequestQuietModeEnabledMillis;
284
285 void setLastRequestQuietModeEnabledMillis(long millis) {
286 mLastRequestQuietModeEnabledMillis = millis;
287 }
288
289 long getLastRequestQuietModeEnabledMillis() {
290 return mLastRequestQuietModeEnabledMillis;
291 }
292
Amith Yamasani12747872015-12-07 14:19:49 -0800293 void clearSeedAccountData() {
294 seedAccountName = null;
295 seedAccountType = null;
296 seedAccountOptions = null;
297 persistSeedData = false;
298 }
299 }
300
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800301 @GuardedBy("mUsersLock")
Amith Yamasani12747872015-12-07 14:19:49 -0800302 private final SparseArray<UserData> mUsers = new SparseArray<>();
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800303
304 /**
Makoto Onuki068c54a2015-10-13 14:34:03 -0700305 * User restrictions set via UserManager. This doesn't include restrictions set by
Pavel Grafov6a40f092016-10-25 15:46:51 +0100306 * device owner / profile owners. Only non-empty restriction bundles are stored.
Makoto Onuki068c54a2015-10-13 14:34:03 -0700307 *
308 * DO NOT Change existing {@link Bundle} in it. When changing a restriction for a user,
309 * a new {@link Bundle} should always be created and set. This is because a {@link Bundle}
310 * maybe shared between {@link #mBaseUserRestrictions} and
311 * {@link #mCachedEffectiveUserRestrictions}, but they should always updated separately.
312 * (Otherwise we won't be able to detect what restrictions have changed in
Fyodor Kupolov82402752015-10-28 14:54:51 -0700313 * {@link #updateUserRestrictionsInternalLR}.
Makoto Onuki068c54a2015-10-13 14:34:03 -0700314 */
315 @GuardedBy("mRestrictionsLock")
316 private final SparseArray<Bundle> mBaseUserRestrictions = new SparseArray<>();
317
318 /**
319 * Cached user restrictions that are in effect -- i.e. {@link #mBaseUserRestrictions} combined
320 * with device / profile owner restrictions. We'll initialize it lazily; use
321 * {@link #getEffectiveUserRestrictions} to access it.
322 *
323 * DO NOT Change existing {@link Bundle} in it. When changing a restriction for a user,
324 * a new {@link Bundle} should always be created and set. This is because a {@link Bundle}
325 * maybe shared between {@link #mBaseUserRestrictions} and
326 * {@link #mCachedEffectiveUserRestrictions}, but they should always updated separately.
327 * (Otherwise we won't be able to detect what restrictions have changed in
Fyodor Kupolov82402752015-10-28 14:54:51 -0700328 * {@link #updateUserRestrictionsInternalLR}.
Makoto Onuki068c54a2015-10-13 14:34:03 -0700329 */
330 @GuardedBy("mRestrictionsLock")
331 private final SparseArray<Bundle> mCachedEffectiveUserRestrictions = new SparseArray<>();
332
Makoto Onuki4f160732015-10-27 17:15:38 -0700333 /**
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800334 * User restrictions that have already been applied in
335 * {@link #updateUserRestrictionsInternalLR(Bundle, int)}. We use it to detect restrictions
336 * that have changed since the last
337 * {@link #updateUserRestrictionsInternalLR(Bundle, int)} call.
Makoto Onuki4f160732015-10-27 17:15:38 -0700338 */
339 @GuardedBy("mRestrictionsLock")
340 private final SparseArray<Bundle> mAppliedUserRestrictions = new SparseArray<>();
341
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800342 /**
Makoto Onukie7927da2015-11-25 10:05:17 -0800343 * User restrictions set by {@link com.android.server.devicepolicy.DevicePolicyManagerService}
Pavel Grafov6a40f092016-10-25 15:46:51 +0100344 * that should be applied to all users, including guests. Only non-empty restriction bundles are
345 * stored.
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800346 */
347 @GuardedBy("mRestrictionsLock")
Pavel Grafov6a40f092016-10-25 15:46:51 +0100348 private final SparseArray<Bundle> mDevicePolicyGlobalUserRestrictions = new SparseArray<>();
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800349
350 /**
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +0100351 * Id of the user that set global restrictions.
352 */
353 @GuardedBy("mRestrictionsLock")
Pavel Grafov6a40f092016-10-25 15:46:51 +0100354 private int mDeviceOwnerUserId = UserHandle.USER_NULL;
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +0100355
356 /**
Makoto Onukie7927da2015-11-25 10:05:17 -0800357 * User restrictions set by {@link com.android.server.devicepolicy.DevicePolicyManagerService}
Pavel Grafov6a40f092016-10-25 15:46:51 +0100358 * for each user. Only non-empty restriction bundles are stored.
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800359 */
360 @GuardedBy("mRestrictionsLock")
361 private final SparseArray<Bundle> mDevicePolicyLocalUserRestrictions = new SparseArray<>();
362
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800363 @GuardedBy("mGuestRestrictions")
Amith Yamasanie4afaa32014-06-30 14:55:07 +0530364 private final Bundle mGuestRestrictions = new Bundle();
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -0800365
366 /**
367 * Set of user IDs being actively removed. Removed IDs linger in this set
368 * for several seconds to work around a VFS caching issue.
Fyodor Kupolov0f4533d2016-05-18 18:43:12 -0700369 * Use {@link #addRemovingUserIdLocked(int)} to add elements to this array
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -0800370 */
Fyodor Kupolov82402752015-10-28 14:54:51 -0700371 @GuardedBy("mUsersLock")
Jeff Sharkeyffe0cb42012-11-05 17:24:43 -0800372 private final SparseBooleanArray mRemovingUserIds = new SparseBooleanArray();
Dianne Hackborn4428e172012-08-24 17:43:05 -0700373
Fyodor Kupolov0f4533d2016-05-18 18:43:12 -0700374 /**
375 * Queue of recently removed userIds. Used for recycling of userIds
376 */
377 @GuardedBy("mUsersLock")
378 private final LinkedList<Integer> mRecentlyRemovedIds = new LinkedList<>();
379
Fyodor Kupolov82402752015-10-28 14:54:51 -0700380 @GuardedBy("mUsersLock")
Amith Yamasani0b285492011-04-14 17:35:23 -0700381 private int[] mUserIds;
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800382 @GuardedBy("mPackagesLock")
Amith Yamasani2a003292012-08-14 18:25:45 -0700383 private int mNextSerialNumber;
Amith Yamasani6f34b412012-10-22 18:19:27 -0700384 private int mUserVersion = 0;
Amith Yamasani0b285492011-04-14 17:35:23 -0700385
Jason Monk62062992014-05-06 09:55:28 -0400386 private IAppOpsService mAppOpsService;
387
Makoto Onuki068c54a2015-10-13 14:34:03 -0700388 private final LocalService mLocalService;
389
Makoto Onukie7927da2015-11-25 10:05:17 -0800390 @GuardedBy("mUsersLock")
391 private boolean mIsDeviceManaged;
392
393 @GuardedBy("mUsersLock")
394 private final SparseBooleanArray mIsUserManaged = new SparseBooleanArray();
395
Makoto Onukid45a4a22015-11-02 17:17:38 -0800396 @GuardedBy("mUserRestrictionsListeners")
397 private final ArrayList<UserRestrictionsListener> mUserRestrictionsListeners =
398 new ArrayList<>();
399
Clara Bayarria1771112015-12-18 16:29:18 +0000400 private final LockPatternUtils mLockPatternUtils;
401
Ricky Waib1dd80b2016-06-07 18:00:55 +0100402 private final String ACTION_DISABLE_QUIET_MODE_AFTER_UNLOCK =
403 "com.android.server.pm.DISABLE_QUIET_MODE_AFTER_UNLOCK";
404
405 private final BroadcastReceiver mDisableQuietModeCallback = new BroadcastReceiver() {
406 @Override
407 public void onReceive(Context context, Intent intent) {
Tony Mak64fd8c02017-12-01 19:11:59 +0000408 if (!ACTION_DISABLE_QUIET_MODE_AFTER_UNLOCK.equals(intent.getAction())) {
409 return;
Ricky Waib1dd80b2016-06-07 18:00:55 +0100410 }
Tony Mak64fd8c02017-12-01 19:11:59 +0000411 final IntentSender target = intent.getParcelableExtra(Intent.EXTRA_INTENT);
Bookatzf56f2582019-09-04 16:06:41 -0700412 final int userId = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.USER_NULL);
Fyodor Kupolova68a2862018-01-30 18:22:00 -0800413 // Call setQuietModeEnabled on bg thread to avoid ANR
arangelov9b632d72018-12-07 23:21:22 +0000414 BackgroundThread.getHandler().post(() ->
Bookatzf56f2582019-09-04 16:06:41 -0700415 setQuietModeEnabled(userId, false, target, /* callingPackage */ null));
Ricky Waib1dd80b2016-06-07 18:00:55 +0100416 }
417 };
418
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +0100419 /**
Tony Mak64fd8c02017-12-01 19:11:59 +0000420 * Start an {@link IntentSender} when user is unlocked after disabling quiet mode.
421 *
Tony Makbece85d2018-01-12 12:10:17 +0000422 * @see {@link #requestQuietModeEnabled(String, boolean, int, IntentSender)}
Tony Mak64fd8c02017-12-01 19:11:59 +0000423 */
424 private class DisableQuietModeUserUnlockedCallback extends IProgressListener.Stub {
425 private final IntentSender mTarget;
426
427 public DisableQuietModeUserUnlockedCallback(IntentSender target) {
428 Preconditions.checkNotNull(target);
429 mTarget = target;
430 }
431
432 @Override
433 public void onStarted(int id, Bundle extras) {}
434
435 @Override
436 public void onProgress(int id, int progress, Bundle extras) {}
437
438 @Override
439 public void onFinished(int id, Bundle extras) {
440 try {
441 mContext.startIntentSender(mTarget, null, 0, 0, 0);
442 } catch (IntentSender.SendIntentException e) {
443 Slog.e(LOG_TAG, "Failed to start the target in the callback", e);
444 }
445 }
446 }
447
448 /**
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +0100449 * Whether all users should be created ephemeral.
450 */
451 @GuardedBy("mUsersLock")
452 private boolean mForceEphemeralUsers;
453
Amith Yamasaniea1b9d72016-05-27 15:57:38 +0000454 @GuardedBy("mUserStates")
455 private final SparseIntArray mUserStates = new SparseIntArray();
Fyodor Kupolov6c915ea2016-05-09 19:10:53 -0700456
Amith Yamasani258848d2012-08-10 17:06:33 -0700457 private static UserManagerService sInstance;
Amith Yamasani258848d2012-08-10 17:06:33 -0700458
Dianne Hackborn4428e172012-08-24 17:43:05 -0700459 public static UserManagerService getInstance() {
460 synchronized (UserManagerService.class) {
461 return sInstance;
Amith Yamasani258848d2012-08-10 17:06:33 -0700462 }
Amith Yamasani258848d2012-08-10 17:06:33 -0700463 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700464
Amith Yamasanid04aaa32016-06-13 12:09:36 -0700465 public static class LifeCycle extends SystemService {
466
467 private UserManagerService mUms;
468
469 /**
470 * @param context
471 */
472 public LifeCycle(Context context) {
473 super(context);
474 }
475
476 @Override
477 public void onStart() {
478 mUms = UserManagerService.getInstance();
479 publishBinderService(Context.USER_SERVICE, mUms);
480 }
481
482 @Override
483 public void onBootPhase(int phase) {
484 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
485 mUms.cleanupPartialUsers();
486 }
487 }
Makoto Onuki73dded22017-12-20 13:14:48 +0900488
489 @Override
Bookatzf56f2582019-09-04 16:06:41 -0700490 public void onStartUser(@UserIdInt int userId) {
Makoto Onuki73dded22017-12-20 13:14:48 +0900491 synchronized (mUms.mUsersLock) {
Bookatzf56f2582019-09-04 16:06:41 -0700492 final UserData user = mUms.getUserDataLU(userId);
Makoto Onuki73dded22017-12-20 13:14:48 +0900493 if (user != null) {
494 user.startRealtime = SystemClock.elapsedRealtime();
495 }
496 }
497 }
498
499 @Override
Bookatzf56f2582019-09-04 16:06:41 -0700500 public void onUnlockUser(@UserIdInt int userId) {
Makoto Onuki73dded22017-12-20 13:14:48 +0900501 synchronized (mUms.mUsersLock) {
Bookatzf56f2582019-09-04 16:06:41 -0700502 final UserData user = mUms.getUserDataLU(userId);
Makoto Onuki73dded22017-12-20 13:14:48 +0900503 if (user != null) {
504 user.unlockRealtime = SystemClock.elapsedRealtime();
505 }
506 }
507 }
508
509 @Override
Bookatzf56f2582019-09-04 16:06:41 -0700510 public void onStopUser(@UserIdInt int userId) {
Makoto Onuki73dded22017-12-20 13:14:48 +0900511 synchronized (mUms.mUsersLock) {
Bookatzf56f2582019-09-04 16:06:41 -0700512 final UserData user = mUms.getUserDataLU(userId);
Makoto Onuki73dded22017-12-20 13:14:48 +0900513 if (user != null) {
514 user.startRealtime = 0;
515 user.unlockRealtime = 0;
516 }
517 }
518 }
Amith Yamasanid04aaa32016-06-13 12:09:36 -0700519 }
520
Fyodor Kupolov0f4533d2016-05-18 18:43:12 -0700521 // TODO b/28848102 Add support for test dependencies injection
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800522 @VisibleForTesting
Fyodor Kupolov0f4533d2016-05-18 18:43:12 -0700523 UserManagerService(Context context) {
Fyodor Kupolov5c0ecfd2017-01-27 11:11:57 -0800524 this(context, null, null, new Object(), context.getCacheDir());
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700525 }
526
Dianne Hackborn4428e172012-08-24 17:43:05 -0700527 /**
528 * Called by package manager to create the service. This is closely
529 * associated with the package manager, and the given lock is the
530 * package manager's own lock.
531 */
Fyodor Kupolov5c0ecfd2017-01-27 11:11:57 -0800532 UserManagerService(Context context, PackageManagerService pm, UserDataPreparer userDataPreparer,
533 Object packagesLock) {
534 this(context, pm, userDataPreparer, packagesLock, Environment.getDataDirectory());
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700535 }
536
Dianne Hackborn4428e172012-08-24 17:43:05 -0700537 private UserManagerService(Context context, PackageManagerService pm,
Fyodor Kupolov5c0ecfd2017-01-27 11:11:57 -0800538 UserDataPreparer userDataPreparer, Object packagesLock, File dataDir) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700539 mContext = context;
540 mPm = pm;
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700541 mPackagesLock = packagesLock;
Fyodor Kupolov75d0ea82014-12-15 16:21:07 -0800542 mHandler = new MainHandler();
Fyodor Kupolov5c0ecfd2017-01-27 11:11:57 -0800543 mUserDataPreparer = userDataPreparer;
Fyodor Kupolove80085d2015-11-06 18:21:39 -0800544 synchronized (mPackagesLock) {
545 mUsersDir = new File(dataDir, USER_INFO_DIR);
546 mUsersDir.mkdirs();
547 // Make zeroth user directory, for services to migrate their files to that location
548 File userZeroDir = new File(mUsersDir, String.valueOf(UserHandle.USER_SYSTEM));
549 userZeroDir.mkdirs();
550 FileUtils.setPermissions(mUsersDir.toString(),
551 FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IROTH | FileUtils.S_IXOTH,
552 -1, -1);
553 mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
554 initDefaultGuestRestrictions();
555 readUserListLP();
556 sInstance = this;
Xiaohui Chen4be96e42015-05-06 09:55:43 -0700557 }
Bookatz04d7ae52019-08-05 14:07:12 -0700558 mSystemPackageInstaller = new UserSystemPackageInstaller(this);
Makoto Onuki068c54a2015-10-13 14:34:03 -0700559 mLocalService = new LocalService();
560 LocalServices.addService(UserManagerInternal.class, mLocalService);
Clara Bayarria1771112015-12-18 16:29:18 +0000561 mLockPatternUtils = new LockPatternUtils(mContext);
Amith Yamasaniea1b9d72016-05-27 15:57:38 +0000562 mUserStates.put(UserHandle.USER_SYSTEM, UserState.STATE_BOOTING);
Xiaohui Chen4be96e42015-05-06 09:55:43 -0700563 }
564
565 void systemReady() {
Jason Monk62062992014-05-06 09:55:28 -0400566 mAppOpsService = IAppOpsService.Stub.asInterface(
567 ServiceManager.getService(Context.APP_OPS_SERVICE));
Makoto Onuki1a2cd742015-11-16 13:51:27 -0800568
569 synchronized (mRestrictionsLock) {
570 applyUserRestrictionsLR(UserHandle.USER_SYSTEM);
Jason Monk62062992014-05-06 09:55:28 -0400571 }
Samuel Tand9453b82016-03-14 15:57:02 -0700572
573 UserInfo currentGuestUser = findCurrentGuestUser();
574 if (currentGuestUser != null && !hasUserRestriction(
575 UserManager.DISALLOW_CONFIG_WIFI, currentGuestUser.id)) {
576 // If a guest user currently exists, apply the DISALLOW_CONFIG_WIFI option
577 // to it, in case this guest was created in a previous version where this
578 // user restriction was not a default guest restriction.
579 setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true, currentGuestUser.id);
580 }
Amith Yamasanieb437d42016-04-29 09:31:25 -0700581
Ricky Waib1dd80b2016-06-07 18:00:55 +0100582 mContext.registerReceiver(mDisableQuietModeCallback,
583 new IntentFilter(ACTION_DISABLE_QUIET_MODE_AFTER_UNLOCK),
584 null, mHandler);
Amith Yamasani258848d2012-08-10 17:06:33 -0700585 }
586
Patrick Baumann6ae7afc2019-07-30 13:11:28 -0700587 /**
588 * This method retrieves the {@link UserManagerInternal} only for the purpose of
589 * PackageManagerService construction.
590 */
591 UserManagerInternal getInternalForInjectorOnly() {
592 return mLocalService;
593 }
594
Amith Yamasanid04aaa32016-06-13 12:09:36 -0700595 void cleanupPartialUsers() {
596 // Prune out any partially created, partially removed and ephemeral users.
597 ArrayList<UserInfo> partials = new ArrayList<>();
598 synchronized (mUsersLock) {
599 final int userSize = mUsers.size();
600 for (int i = 0; i < userSize; i++) {
601 UserInfo ui = mUsers.valueAt(i).info;
Felipe Lemec1ca4412019-09-11 09:23:26 -0700602 if ((ui.partial || ui.guestToRemove || (ui.isEphemeral() && !ui.preCreated))
603 && i != 0) {
Amith Yamasanid04aaa32016-06-13 12:09:36 -0700604 partials.add(ui);
Fyodor Kupolov0f4533d2016-05-18 18:43:12 -0700605 addRemovingUserIdLocked(ui.id);
Amith Yamasaniae261892016-06-27 10:40:09 -0700606 ui.partial = true;
Amith Yamasanid04aaa32016-06-13 12:09:36 -0700607 }
608 }
609 }
610 final int partialsSize = partials.size();
611 for (int i = 0; i < partialsSize; i++) {
612 UserInfo ui = partials.get(i);
613 Slog.w(LOG_TAG, "Removing partially created user " + ui.id
614 + " (name=" + ui.name + ")");
615 removeUserState(ui.id);
616 }
617 }
618
Amith Yamasani258848d2012-08-10 17:06:33 -0700619 @Override
Bookatzf56f2582019-09-04 16:06:41 -0700620 public String getUserAccount(@UserIdInt int userId) {
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800621 checkManageUserAndAcrossUsersFullPermission("get user account");
622 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -0800623 return mUsers.get(userId).account;
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800624 }
625 }
626
627 @Override
Bookatzf56f2582019-09-04 16:06:41 -0700628 public void setUserAccount(@UserIdInt int userId, String accountName) {
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800629 checkManageUserAndAcrossUsersFullPermission("set user account");
Amith Yamasani12747872015-12-07 14:19:49 -0800630 UserData userToUpdate = null;
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800631 synchronized (mPackagesLock) {
632 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -0800633 final UserData userData = mUsers.get(userId);
634 if (userData == null) {
635 Slog.e(LOG_TAG, "User not found for setting user account: u" + userId);
636 return;
637 }
638 String currentAccount = userData.account;
Narayan Kamath607223f2018-02-19 14:09:02 +0000639 if (!Objects.equals(currentAccount, accountName)) {
Amith Yamasani12747872015-12-07 14:19:49 -0800640 userData.account = accountName;
641 userToUpdate = userData;
Xiaohui Chenb3b92582015-12-07 11:22:13 -0800642 }
643 }
644
645 if (userToUpdate != null) {
646 writeUserLP(userToUpdate);
647 }
648 }
649 }
650
651 @Override
Xiaohui Chen70f6c382015-04-28 14:21:43 -0700652 public UserInfo getPrimaryUser() {
653 checkManageUsersPermission("query users");
Fyodor Kupolov82402752015-10-28 14:54:51 -0700654 synchronized (mUsersLock) {
Amith Yamasani515d4062015-09-28 11:30:06 -0700655 final int userSize = mUsers.size();
656 for (int i = 0; i < userSize; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -0800657 UserInfo ui = mUsers.valueAt(i).info;
Xiaohui Chend3e9e182015-11-18 13:37:32 -0800658 if (ui.isPrimary() && !mRemovingUserIds.get(ui.id)) {
Xiaohui Chen70f6c382015-04-28 14:21:43 -0700659 return ui;
660 }
661 }
662 }
663 return null;
664 }
665
666 @Override
Xiaohui Chen594f2082015-08-18 11:04:20 -0700667 public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
Felipe Lemec1ca4412019-09-11 09:23:26 -0700668 return getUsers(/*excludePartial= */ true, excludeDying, /* excludePreCreated= */ true);
669 }
670
671 private @NonNull List<UserInfo> getUsers(boolean excludePartial, boolean excludeDying,
672 boolean excludePreCreated) {
Sudheer Shankaf5cea032016-06-08 17:13:24 -0700673 checkManageOrCreateUsersPermission("query users");
Fyodor Kupolov82402752015-10-28 14:54:51 -0700674 synchronized (mUsersLock) {
Amith Yamasani13593602012-03-22 16:16:17 -0700675 ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
Amith Yamasani515d4062015-09-28 11:30:06 -0700676 final int userSize = mUsers.size();
677 for (int i = 0; i < userSize; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -0800678 UserInfo ui = mUsers.valueAt(i).info;
Felipe Lemec1ca4412019-09-11 09:23:26 -0700679 if ((excludePartial && ui.partial)
680 || (excludeDying && mRemovingUserIds.get(ui.id))
681 || (excludePreCreated && ui.preCreated)) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700682 continue;
683 }
Felipe Lemec1ca4412019-09-11 09:23:26 -0700684 users.add(userWithName(ui));
Amith Yamasani13593602012-03-22 16:16:17 -0700685 }
686 return users;
Amith Yamasani4b2e9342011-03-31 12:38:53 -0700687 }
Amith Yamasani13593602012-03-22 16:16:17 -0700688 }
689
Amith Yamasani258848d2012-08-10 17:06:33 -0700690 @Override
Bookatzf56f2582019-09-04 16:06:41 -0700691 public List<UserInfo> getProfiles(@UserIdInt int userId, boolean enabledOnly) {
Fyodor Kupolovc533b562016-04-01 14:37:07 -0700692 boolean returnFullInfo = true;
Amith Yamasani4f582632014-02-19 14:31:52 -0800693 if (userId != UserHandle.getCallingUserId()) {
Sudheer Shanka74680912016-07-29 11:03:37 -0700694 checkManageOrCreateUsersPermission("getting profiles related to user " + userId);
Fyodor Kupolovc533b562016-04-01 14:37:07 -0700695 } else {
696 returnFullInfo = hasManageUsersPermission();
Amith Yamasani4f582632014-02-19 14:31:52 -0800697 }
Amith Yamasanibe465322014-04-24 13:45:17 -0700698 final long ident = Binder.clearCallingIdentity();
699 try {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700700 synchronized (mUsersLock) {
Fyodor Kupolovc533b562016-04-01 14:37:07 -0700701 return getProfilesLU(userId, enabledOnly, returnFullInfo);
Alexandra Gherghina385124d2014-04-03 13:37:39 +0100702 }
Amith Yamasanibe465322014-04-24 13:45:17 -0700703 } finally {
704 Binder.restoreCallingIdentity(ident);
Kenny Guya52dc3e2014-02-11 15:33:14 +0000705 }
706 }
707
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700708 @Override
Bookatzf56f2582019-09-04 16:06:41 -0700709 public int[] getProfileIds(@UserIdInt int userId, boolean enabledOnly) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700710 if (userId != UserHandle.getCallingUserId()) {
bohu12d23a12016-09-26 16:20:07 -0700711 checkManageOrCreateUsersPermission("getting profiles related to user " + userId);
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700712 }
713 final long ident = Binder.clearCallingIdentity();
714 try {
715 synchronized (mUsersLock) {
716 return getProfileIdsLU(userId, enabledOnly).toArray();
717 }
718 } finally {
719 Binder.restoreCallingIdentity(ident);
720 }
721 }
722
Amith Yamasanibe465322014-04-24 13:45:17 -0700723 /** Assume permissions already checked and caller's identity cleared */
Andreas Gampe2e8c7672018-07-20 13:01:08 -0700724 @GuardedBy("mUsersLock")
Bookatzf56f2582019-09-04 16:06:41 -0700725 private List<UserInfo> getProfilesLU(@UserIdInt int userId, boolean enabledOnly,
726 boolean fullInfo) {
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700727 IntArray profileIds = getProfileIdsLU(userId, enabledOnly);
728 ArrayList<UserInfo> users = new ArrayList<>(profileIds.size());
729 for (int i = 0; i < profileIds.size(); i++) {
730 int profileId = profileIds.get(i);
731 UserInfo userInfo = mUsers.get(profileId).info;
732 // If full info is not required - clear PII data to prevent 3P apps from reading it
733 if (!fullInfo) {
734 userInfo = new UserInfo(userInfo);
735 userInfo.name = null;
736 userInfo.iconPath = null;
737 } else {
738 userInfo = userWithName(userInfo);
739 }
740 users.add(userInfo);
741 }
742 return users;
743 }
744
745 /**
746 * Assume permissions already checked and caller's identity cleared
747 */
Andreas Gampe2e8c7672018-07-20 13:01:08 -0700748 @GuardedBy("mUsersLock")
Bookatzf56f2582019-09-04 16:06:41 -0700749 private IntArray getProfileIdsLU(@UserIdInt int userId, boolean enabledOnly) {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700750 UserInfo user = getUserInfoLU(userId);
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700751 IntArray result = new IntArray(mUsers.size());
Amith Yamasanidda003f2014-08-28 18:06:51 -0700752 if (user == null) {
753 // Probably a dying user
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700754 return result;
Amith Yamasanidda003f2014-08-28 18:06:51 -0700755 }
Amith Yamasani515d4062015-09-28 11:30:06 -0700756 final int userSize = mUsers.size();
757 for (int i = 0; i < userSize; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -0800758 UserInfo profile = mUsers.valueAt(i).info;
Amith Yamasanibe465322014-04-24 13:45:17 -0700759 if (!isProfileOf(user, profile)) {
760 continue;
761 }
Alexandra Gherghinadf35d572014-04-09 13:54:39 +0100762 if (enabledOnly && !profile.isEnabled()) {
763 continue;
Amith Yamasanibe465322014-04-24 13:45:17 -0700764 }
Amith Yamasani70fcf0c2014-07-11 08:40:19 -0700765 if (mRemovingUserIds.get(profile.id)) {
766 continue;
767 }
Tony Mak80189cd2016-04-05 17:21:42 +0100768 if (profile.partial) {
769 continue;
770 }
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700771 result.add(profile.id);
Amith Yamasanibe465322014-04-24 13:45:17 -0700772 }
Fyodor Kupolov7f98aa42016-04-07 14:56:25 -0700773 return result;
Amith Yamasanibe465322014-04-24 13:45:17 -0700774 }
775
Jessica Hummelbe81c802014-04-22 15:49:22 +0100776 @Override
Bookatzf56f2582019-09-04 16:06:41 -0700777 public int getCredentialOwnerProfile(@UserIdInt int userId) {
Andres Moralesc5548c02015-08-05 10:23:12 -0700778 checkManageUsersPermission("get the credential owner");
Bookatzf56f2582019-09-04 16:06:41 -0700779 if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700780 synchronized (mUsersLock) {
Bookatzf56f2582019-09-04 16:06:41 -0700781 UserInfo profileParent = getProfileParentLU(userId);
Andres Moralesc5548c02015-08-05 10:23:12 -0700782 if (profileParent != null) {
783 return profileParent.id;
784 }
785 }
786 }
787
Bookatzf56f2582019-09-04 16:06:41 -0700788 return userId;
Andres Moralesc5548c02015-08-05 10:23:12 -0700789 }
790
791 @Override
Bookatzf56f2582019-09-04 16:06:41 -0700792 public boolean isSameProfileGroup(@UserIdInt int userId, int otherUserId) {
Xiaohui Chenfd5b7742015-10-14 15:47:04 -0700793 if (userId == otherUserId) return true;
794 checkManageUsersPermission("check if in the same profile group");
Fyodor Kupolov0fb772e2016-10-13 16:27:34 -0700795 return isSameProfileGroupNoChecks(userId, otherUserId);
796 }
797
Bookatzf56f2582019-09-04 16:06:41 -0700798 private boolean isSameProfileGroupNoChecks(@UserIdInt int userId, int otherUserId) {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700799 synchronized (mUsersLock) {
800 UserInfo userInfo = getUserInfoLU(userId);
801 if (userInfo == null || userInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
802 return false;
803 }
804 UserInfo otherUserInfo = getUserInfoLU(otherUserId);
805 if (otherUserInfo == null
806 || otherUserInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
807 return false;
808 }
809 return userInfo.profileGroupId == otherUserInfo.profileGroupId;
Xiaohui Chenfd5b7742015-10-14 15:47:04 -0700810 }
Xiaohui Chenfd5b7742015-10-14 15:47:04 -0700811 }
812
813 @Override
Bookatzf56f2582019-09-04 16:06:41 -0700814 public UserInfo getProfileParent(@UserIdInt int userId) {
Jessica Hummelbe81c802014-04-22 15:49:22 +0100815 checkManageUsersPermission("get the profile parent");
Fyodor Kupolov82402752015-10-28 14:54:51 -0700816 synchronized (mUsersLock) {
Bookatzf56f2582019-09-04 16:06:41 -0700817 return getProfileParentLU(userId);
Fyodor Kupolovff7233e2015-04-08 11:28:52 -0700818 }
819 }
820
Jakub Pawlowski0f1f5b72017-11-15 14:50:43 -0800821 @Override
Bookatzf56f2582019-09-04 16:06:41 -0700822 public int getProfileParentId(@UserIdInt int userId) {
Jakub Pawlowski0f1f5b72017-11-15 14:50:43 -0800823 checkManageUsersPermission("get the profile parent");
Bookatzf56f2582019-09-04 16:06:41 -0700824 return mLocalService.getProfileParentId(userId);
Jakub Pawlowski0f1f5b72017-11-15 14:50:43 -0800825 }
826
Andreas Gampe2e8c7672018-07-20 13:01:08 -0700827 @GuardedBy("mUsersLock")
Bookatzf56f2582019-09-04 16:06:41 -0700828 private UserInfo getProfileParentLU(@UserIdInt int userId) {
829 UserInfo profile = getUserInfoLU(userId);
Fyodor Kupolovff7233e2015-04-08 11:28:52 -0700830 if (profile == null) {
831 return null;
832 }
833 int parentUserId = profile.profileGroupId;
Bookatzf56f2582019-09-04 16:06:41 -0700834 if (parentUserId == userId || parentUserId == UserInfo.NO_PROFILE_GROUP_ID) {
Fyodor Kupolovff7233e2015-04-08 11:28:52 -0700835 return null;
836 } else {
Fyodor Kupolov82402752015-10-28 14:54:51 -0700837 return getUserInfoLU(parentUserId);
Jessica Hummelbe81c802014-04-22 15:49:22 +0100838 }
839 }
840
Fyodor Kupolov82402752015-10-28 14:54:51 -0700841 private static boolean isProfileOf(UserInfo user, UserInfo profile) {
Kenny Guy2a764942014-04-02 13:29:20 +0100842 return user.id == profile.id ||
843 (user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
844 && user.profileGroupId == profile.profileGroupId);
Kenny Guya52dc3e2014-02-11 15:33:14 +0000845 }
846
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000847 private void broadcastProfileAvailabilityChanges(UserHandle profileHandle,
Rubin Xuf13c9802016-01-21 18:06:00 +0000848 UserHandle parentHandle, boolean inQuietMode) {
Rubin Xue95057a2016-04-01 16:49:25 +0100849 Intent intent = new Intent();
850 if (inQuietMode) {
851 intent.setAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
852 } else {
853 intent.setAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
854 }
Rubin Xuf13c9802016-01-21 18:06:00 +0000855 intent.putExtra(Intent.EXTRA_QUIET_MODE, inQuietMode);
856 intent.putExtra(Intent.EXTRA_USER, profileHandle);
857 intent.putExtra(Intent.EXTRA_USER_HANDLE, profileHandle.getIdentifier());
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000858 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Rubin Xuf13c9802016-01-21 18:06:00 +0000859 mContext.sendBroadcastAsUser(intent, parentHandle);
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000860 }
861
862 @Override
Tony Makbece85d2018-01-12 12:10:17 +0000863 public boolean requestQuietModeEnabled(@NonNull String callingPackage, boolean enableQuietMode,
Bookatzf56f2582019-09-04 16:06:41 -0700864 @UserIdInt int userId, @Nullable IntentSender target) {
Tony Make3d1f652017-12-12 11:00:37 +0000865 Preconditions.checkNotNull(callingPackage);
866
Tony Makb7e6fd42017-12-05 19:40:28 +0000867 if (enableQuietMode && target != null) {
868 throw new IllegalArgumentException(
869 "target should only be specified when we are disabling quiet mode.");
870 }
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000871
Tony Makd390ae92017-12-28 13:23:10 +0000872 ensureCanModifyQuietMode(callingPackage, Binder.getCallingUid(), target != null);
Tony Makb7e6fd42017-12-05 19:40:28 +0000873 final long identity = Binder.clearCallingIdentity();
874 try {
arangelov9b632d72018-12-07 23:21:22 +0000875 boolean result = false;
Tony Makb7e6fd42017-12-05 19:40:28 +0000876 if (enableQuietMode) {
arangelov9b632d72018-12-07 23:21:22 +0000877 setQuietModeEnabled(
Bookatzf56f2582019-09-04 16:06:41 -0700878 userId, true /* enableQuietMode */, target, callingPackage);
arangelov9b632d72018-12-07 23:21:22 +0000879 result = true;
Tony Makb7e6fd42017-12-05 19:40:28 +0000880 } else {
881 boolean needToShowConfirmCredential =
Bookatzf56f2582019-09-04 16:06:41 -0700882 mLockPatternUtils.isSecure(userId)
883 && !StorageManager.isUserKeyUnlocked(userId);
Tony Makb7e6fd42017-12-05 19:40:28 +0000884 if (needToShowConfirmCredential) {
Bookatzf56f2582019-09-04 16:06:41 -0700885 showConfirmCredentialToDisableQuietMode(userId, target);
Tony Makb7e6fd42017-12-05 19:40:28 +0000886 } else {
arangelov9b632d72018-12-07 23:21:22 +0000887 setQuietModeEnabled(
Bookatzf56f2582019-09-04 16:06:41 -0700888 userId, false /* enableQuietMode */, target, callingPackage);
arangelov9b632d72018-12-07 23:21:22 +0000889 result = true;
Tony Makb7e6fd42017-12-05 19:40:28 +0000890 }
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000891 }
arangelov9b632d72018-12-07 23:21:22 +0000892 return result;
Tony Makb7e6fd42017-12-05 19:40:28 +0000893 } finally {
894 Binder.restoreCallingIdentity(identity);
895 }
896 }
897
Tony Make3d1f652017-12-12 11:00:37 +0000898 /**
Tony Makd390ae92017-12-28 13:23:10 +0000899 * The caller can modify quiet mode if it meets one of these conditions:
Tony Make3d1f652017-12-12 11:00:37 +0000900 * <ul>
901 * <li>Has system UID or root UID</li>
902 * <li>Has {@link Manifest.permission#MODIFY_QUIET_MODE}</li>
903 * <li>Has {@link Manifest.permission#MANAGE_USERS}</li>
904 * </ul>
Tony Makd390ae92017-12-28 13:23:10 +0000905 * <p>
906 * If caller wants to start an intent after disabling the quiet mode, it must has
907 * {@link Manifest.permission#MANAGE_USERS}.
Tony Make3d1f652017-12-12 11:00:37 +0000908 */
Tony Makd390ae92017-12-28 13:23:10 +0000909 private void ensureCanModifyQuietMode(String callingPackage, int callingUid,
910 boolean startIntent) {
Tony Make3d1f652017-12-12 11:00:37 +0000911 if (hasManageUsersPermission()) {
Tony Makd390ae92017-12-28 13:23:10 +0000912 return;
Tony Make3d1f652017-12-12 11:00:37 +0000913 }
Tony Makd390ae92017-12-28 13:23:10 +0000914 if (startIntent) {
915 throw new SecurityException("MANAGE_USERS permission is required to start intent "
916 + "after disabling quiet mode.");
917 }
jovanakf24ad492018-05-18 12:15:59 -0700918 final boolean hasModifyQuietModePermission = hasPermissionGranted(
919 Manifest.permission.MODIFY_QUIET_MODE, callingUid);
Tony Make3d1f652017-12-12 11:00:37 +0000920 if (hasModifyQuietModePermission) {
Tony Makd390ae92017-12-28 13:23:10 +0000921 return;
Tony Make3d1f652017-12-12 11:00:37 +0000922 }
923
Tony Makd390ae92017-12-28 13:23:10 +0000924 verifyCallingPackage(callingPackage, callingUid);
Tony Make3d1f652017-12-12 11:00:37 +0000925 final ShortcutServiceInternal shortcutInternal =
926 LocalServices.getService(ShortcutServiceInternal.class);
927 if (shortcutInternal != null) {
928 boolean isForegroundLauncher =
929 shortcutInternal.isForegroundDefaultLauncher(callingPackage, callingUid);
930 if (isForegroundLauncher) {
Tony Makd390ae92017-12-28 13:23:10 +0000931 return;
Tony Make3d1f652017-12-12 11:00:37 +0000932 }
933 }
Tony Makd390ae92017-12-28 13:23:10 +0000934 throw new SecurityException("Can't modify quiet mode, caller is neither foreground "
935 + "default launcher nor has MANAGE_USERS/MODIFY_QUIET_MODE permission");
Tony Make3d1f652017-12-12 11:00:37 +0000936 }
937
Bookatzf56f2582019-09-04 16:06:41 -0700938 private void setQuietModeEnabled(@UserIdInt int userId, boolean enableQuietMode,
arangelov9b632d72018-12-07 23:21:22 +0000939 IntentSender target, @Nullable String callingPackage) {
Tony Makb7e6fd42017-12-05 19:40:28 +0000940 final UserInfo profile, parent;
941 final UserData profileUserData;
942 synchronized (mUsersLock) {
Bookatzf56f2582019-09-04 16:06:41 -0700943 profile = getUserInfoLU(userId);
944 parent = getProfileParentLU(userId);
Tony Makb7e6fd42017-12-05 19:40:28 +0000945
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000946 if (profile == null || !profile.isManagedProfile()) {
Bookatzf56f2582019-09-04 16:06:41 -0700947 throw new IllegalArgumentException("User " + userId + " is not a profile");
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000948 }
Tony Makb7e6fd42017-12-05 19:40:28 +0000949 if (profile.isQuietModeEnabled() == enableQuietMode) {
950 Slog.i(LOG_TAG, "Quiet mode is already " + enableQuietMode);
951 return;
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000952 }
Tony Makb7e6fd42017-12-05 19:40:28 +0000953 profile.flags ^= UserInfo.FLAG_QUIET_MODE;
954 profileUserData = getUserDataLU(profile.id);
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000955 }
Tony Makb7e6fd42017-12-05 19:40:28 +0000956 synchronized (mPackagesLock) {
957 writeUserLP(profileUserData);
958 }
959 try {
960 if (enableQuietMode) {
Bookatzf56f2582019-09-04 16:06:41 -0700961 ActivityManager.getService().stopUser(userId, /* force */true, null);
Tony Makb7e6fd42017-12-05 19:40:28 +0000962 LocalServices.getService(ActivityManagerInternal.class)
Bookatzf56f2582019-09-04 16:06:41 -0700963 .killForegroundAppsForUser(userId);
Tony Makb7e6fd42017-12-05 19:40:28 +0000964 } else {
965 IProgressListener callback = target != null
966 ? new DisableQuietModeUserUnlockedCallback(target)
967 : null;
968 ActivityManager.getService().startUserInBackgroundWithListener(
Bookatzf56f2582019-09-04 16:06:41 -0700969 userId, callback);
Rubin Xuf13c9802016-01-21 18:06:00 +0000970 }
Bookatzf56f2582019-09-04 16:06:41 -0700971 logQuietModeEnabled(userId, enableQuietMode, callingPackage);
Tony Makb7e6fd42017-12-05 19:40:28 +0000972 } catch (RemoteException e) {
973 // Should not happen, same process.
974 e.rethrowAsRuntimeException();
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000975 }
Tony Makb7e6fd42017-12-05 19:40:28 +0000976 broadcastProfileAvailabilityChanges(profile.getUserHandle(), parent.getUserHandle(),
977 enableQuietMode);
Rubin Xu0a29ecd2015-11-04 15:11:48 +0000978 }
979
Bookatzf56f2582019-09-04 16:06:41 -0700980 private void logQuietModeEnabled(@UserIdInt int userId, boolean enableQuietMode,
arangelov9b632d72018-12-07 23:21:22 +0000981 @Nullable String callingPackage) {
982 UserData userData;
983 synchronized (mUsersLock) {
Bookatzf56f2582019-09-04 16:06:41 -0700984 userData = getUserDataLU(userId);
arangelov9b632d72018-12-07 23:21:22 +0000985 }
986 if (userData == null) {
987 return;
988 }
989 final long now = System.currentTimeMillis();
990 final long period = (userData.getLastRequestQuietModeEnabledMillis() != 0L
991 ? now - userData.getLastRequestQuietModeEnabledMillis()
992 : now - userData.info.creationTime);
993 DevicePolicyEventLogger
994 .createEvent(DevicePolicyEnums.REQUEST_QUIET_MODE_ENABLED)
995 .setStrings(callingPackage)
996 .setBoolean(enableQuietMode)
997 .setTimePeriod(period)
998 .write();
999 userData.setLastRequestQuietModeEnabledMillis(now);
1000 }
1001
Rubin Xu0a29ecd2015-11-04 15:11:48 +00001002 @Override
Bookatzf56f2582019-09-04 16:06:41 -07001003 public boolean isQuietModeEnabled(@UserIdInt int userId) {
Rubin Xu0a29ecd2015-11-04 15:11:48 +00001004 synchronized (mPackagesLock) {
1005 UserInfo info;
1006 synchronized (mUsersLock) {
Bookatzf56f2582019-09-04 16:06:41 -07001007 info = getUserInfoLU(userId);
Rubin Xu0a29ecd2015-11-04 15:11:48 +00001008 }
1009 if (info == null || !info.isManagedProfile()) {
Rubin Xuf13c9802016-01-21 18:06:00 +00001010 return false;
Rubin Xu0a29ecd2015-11-04 15:11:48 +00001011 }
1012 return info.isQuietModeEnabled();
1013 }
1014 }
1015
Tony Makb7e6fd42017-12-05 19:40:28 +00001016 /**
1017 * Show confirm credential screen to unlock user in order to turn off quiet mode.
1018 */
1019 private void showConfirmCredentialToDisableQuietMode(
Bookatzf56f2582019-09-04 16:06:41 -07001020 @UserIdInt int userId, @Nullable IntentSender target) {
Tony Makb7e6fd42017-12-05 19:40:28 +00001021 // otherwise, we show a profile challenge to trigger decryption of the user
1022 final KeyguardManager km = (KeyguardManager) mContext.getSystemService(
1023 Context.KEYGUARD_SERVICE);
Bookatzf56f2582019-09-04 16:06:41 -07001024 // We should use userId not credentialOwnerUserId here, as even if it is unified
Tony Makb7e6fd42017-12-05 19:40:28 +00001025 // lock, confirm screenlock page will know and show personal challenge, and unlock
1026 // work profile when personal challenge is correct
Bookatzf56f2582019-09-04 16:06:41 -07001027 final Intent unlockIntent = km.createConfirmDeviceCredentialIntent(null, null, userId);
Tony Makb7e6fd42017-12-05 19:40:28 +00001028 if (unlockIntent == null) {
1029 return;
Benjamin Franzf02420c2016-04-04 18:52:21 +01001030 }
Tony Makb7e6fd42017-12-05 19:40:28 +00001031 final Intent callBackIntent = new Intent(
1032 ACTION_DISABLE_QUIET_MODE_AFTER_UNLOCK);
1033 if (target != null) {
1034 callBackIntent.putExtra(Intent.EXTRA_INTENT, target);
Benjamin Franzf02420c2016-04-04 18:52:21 +01001035 }
Bookatzf56f2582019-09-04 16:06:41 -07001036 callBackIntent.putExtra(Intent.EXTRA_USER_ID, userId);
Tony Makb7e6fd42017-12-05 19:40:28 +00001037 callBackIntent.setPackage(mContext.getPackageName());
1038 callBackIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
1039 final PendingIntent pendingIntent = PendingIntent.getBroadcast(
1040 mContext,
1041 0,
1042 callBackIntent,
1043 PendingIntent.FLAG_CANCEL_CURRENT |
1044 PendingIntent.FLAG_ONE_SHOT |
1045 PendingIntent.FLAG_IMMUTABLE);
1046 // After unlocking the challenge, it will disable quiet mode and run the original
1047 // intentSender
1048 unlockIntent.putExtra(Intent.EXTRA_INTENT, pendingIntent.getIntentSender());
1049 unlockIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
1050 mContext.startActivity(unlockIntent);
Benjamin Franzf02420c2016-04-04 18:52:21 +01001051 }
1052
1053 @Override
Bookatzf56f2582019-09-04 16:06:41 -07001054 public void setUserEnabled(@UserIdInt int userId) {
Alexandra Gherghinadf35d572014-04-09 13:54:39 +01001055 checkManageUsersPermission("enable user");
1056 synchronized (mPackagesLock) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07001057 UserInfo info;
1058 synchronized (mUsersLock) {
1059 info = getUserInfoLU(userId);
1060 }
Alexandra Gherghinadf35d572014-04-09 13:54:39 +01001061 if (info != null && !info.isEnabled()) {
1062 info.flags ^= UserInfo.FLAG_DISABLED;
Amith Yamasani12747872015-12-07 14:19:49 -08001063 writeUserLP(getUserDataLU(info.id));
Alexandra Gherghinadf35d572014-04-09 13:54:39 +01001064 }
1065 }
1066 }
1067
jovanakf24ad492018-05-18 12:15:59 -07001068 @Override
Bookatzf56f2582019-09-04 16:06:41 -07001069 public void setUserAdmin(@UserIdInt int userId) {
jovanakf24ad492018-05-18 12:15:59 -07001070 checkManageUserAndAcrossUsersFullPermission("set user admin");
1071
1072 synchronized (mPackagesLock) {
1073 UserInfo info;
1074 synchronized (mUsersLock) {
1075 info = getUserInfoLU(userId);
1076 }
1077 if (info == null || info.isAdmin()) {
1078 // Exit if no user found with that id, or the user is already an Admin.
1079 return;
1080 }
1081
1082 info.flags ^= UserInfo.FLAG_ADMIN;
1083 writeUserLP(getUserDataLU(info.id));
1084 }
1085
1086 // Remove non-admin restrictions.
1087 // Keep synchronized with createUserEvenWhenDisallowed.
1088 setUserRestriction(UserManager.DISALLOW_SMS, false, userId);
1089 setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, false, userId);
1090 }
1091
Andrew Scull85a63bc2016-10-24 13:47:47 +01001092 /**
1093 * Evicts a user's CE key by stopping and restarting the user.
1094 *
1095 * The key is evicted automatically by the user controller when the user has stopped.
1096 */
1097 @Override
1098 public void evictCredentialEncryptionKey(@UserIdInt int userId) {
1099 checkManageUsersPermission("evict CE key");
1100 final IActivityManager am = ActivityManagerNative.getDefault();
1101 final long identity = Binder.clearCallingIdentity();
1102 try {
1103 am.restartUserInBackground(userId);
1104 } catch (RemoteException re) {
1105 throw re.rethrowAsRuntimeException();
1106 } finally {
1107 Binder.restoreCallingIdentity(identity);
1108 }
1109 }
1110
Alexandra Gherghinadf35d572014-04-09 13:54:39 +01001111 @Override
Bookatzf56f2582019-09-04 16:06:41 -07001112 public UserInfo getUserInfo(@UserIdInt int userId) {
Sudheer Shankaaccaa082016-06-14 16:22:57 -07001113 checkManageOrCreateUsersPermission("query user");
Tony Mak8673b282016-03-21 21:10:59 +00001114 synchronized (mUsersLock) {
Amith Yamasani6f48d6e2016-03-23 14:28:25 -07001115 return userWithName(getUserInfoLU(userId));
1116 }
1117 }
1118
1119 /**
1120 * Returns a UserInfo object with the name filled in, for Owner, or the original
1121 * if the name is already set.
1122 */
1123 private UserInfo userWithName(UserInfo orig) {
1124 if (orig != null && orig.name == null && orig.id == UserHandle.USER_SYSTEM) {
1125 UserInfo withName = new UserInfo(orig);
1126 withName.name = getOwnerName();
1127 return withName;
1128 } else {
1129 return orig;
Tony Mak8673b282016-03-21 21:10:59 +00001130 }
1131 }
1132
1133 @Override
Kenny Guy02c89902016-11-15 19:36:38 +00001134 public int getManagedProfileBadge(@UserIdInt int userId) {
Jon Miranda2b340a22019-01-25 14:03:49 -08001135 checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "getManagedProfileBadge");
Kenny Guy02c89902016-11-15 19:36:38 +00001136 synchronized (mUsersLock) {
1137 UserInfo userInfo = getUserInfoLU(userId);
1138 return userInfo != null ? userInfo.profileBadge : 0;
1139 }
1140 }
1141
1142 @Override
Bookatzf56f2582019-09-04 16:06:41 -07001143 public boolean isManagedProfile(@UserIdInt int userId) {
Jon Miranda2b340a22019-01-25 14:03:49 -08001144 checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "isManagedProfile");
Fyodor Kupolov82402752015-10-28 14:54:51 -07001145 synchronized (mUsersLock) {
Amith Yamasani1c41dc82016-06-28 16:13:15 -07001146 UserInfo userInfo = getUserInfoLU(userId);
Tony Mak8673b282016-03-21 21:10:59 +00001147 return userInfo != null && userInfo.isManagedProfile();
Amith Yamasani13593602012-03-22 16:16:17 -07001148 }
1149 }
1150
Amith Yamasani71e6c692013-03-24 17:39:28 -07001151 @Override
Bookatzf56f2582019-09-04 16:06:41 -07001152 public boolean isUserUnlockingOrUnlocked(@UserIdInt int userId) {
Fyodor Kupolov2e7e0962016-12-01 18:09:17 -08001153 checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "isUserUnlockingOrUnlocked");
Fyodor Kupolovc413f702016-10-06 17:11:14 -07001154 return mLocalService.isUserUnlockingOrUnlocked(userId);
1155 }
1156
1157 @Override
Bookatzf56f2582019-09-04 16:06:41 -07001158 public boolean isUserUnlocked(@UserIdInt int userId) {
Fyodor Kupolov2e7e0962016-12-01 18:09:17 -08001159 checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "isUserUnlocked");
Fyodor Kupolov0468ee92017-05-25 17:06:17 -07001160 return mLocalService.isUserUnlocked(userId);
Fyodor Kupolov2e7e0962016-12-01 18:09:17 -08001161 }
1162
1163 @Override
Bookatzf56f2582019-09-04 16:06:41 -07001164 public boolean isUserRunning(@UserIdInt int userId) {
Fyodor Kupolov2e7e0962016-12-01 18:09:17 -08001165 checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "isUserRunning");
1166 return mLocalService.isUserRunning(userId);
1167 }
1168
Makoto Onuki73dded22017-12-20 13:14:48 +09001169 @Override
Bookatzcde3d922019-03-08 14:30:00 -08001170 public String getUserName() {
1171 if (!hasManageUsersOrPermission(android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED)) {
1172 throw new SecurityException("You need MANAGE_USERS or GET_ACCOUNTS_PRIVILEGED "
1173 + "permissions to: get user name");
1174 }
1175 final int userId = UserHandle.getUserId(Binder.getCallingUid());
1176 synchronized (mUsersLock) {
1177 UserInfo userInfo = userWithName(getUserInfoLU(userId));
1178 return userInfo == null ? "" : userInfo.name;
1179 }
1180 }
1181
1182 @Override
Makoto Onuki73dded22017-12-20 13:14:48 +09001183 public long getUserStartRealtime() {
1184 final int userId = UserHandle.getUserId(Binder.getCallingUid());
1185 synchronized (mUsersLock) {
1186 final UserData user = getUserDataLU(userId);
1187 if (user != null) {
1188 return user.startRealtime;
1189 }
1190 return 0;
1191 }
1192 }
1193
1194 @Override
1195 public long getUserUnlockRealtime() {
1196 synchronized (mUsersLock) {
1197 final UserData user = getUserDataLU(UserHandle.getUserId(Binder.getCallingUid()));
1198 if (user != null) {
1199 return user.unlockRealtime;
1200 }
1201 return 0;
1202 }
1203 }
1204
Bookatzf56f2582019-09-04 16:06:41 -07001205 private void checkManageOrInteractPermIfCallerInOtherProfileGroup(@UserIdInt int userId,
1206 String name) {
Felipe Lemec1ca4412019-09-11 09:23:26 -07001207 final int callingUserId = UserHandle.getCallingUserId();
Fyodor Kupolov2e7e0962016-12-01 18:09:17 -08001208 if (callingUserId == userId || isSameProfileGroupNoChecks(callingUserId, userId) ||
1209 hasManageUsersPermission()) {
1210 return;
1211 }
jovanakf24ad492018-05-18 12:15:59 -07001212 if (!hasPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS,
1213 Binder.getCallingUid())) {
Fyodor Kupolov2e7e0962016-12-01 18:09:17 -08001214 throw new SecurityException("You need INTERACT_ACROSS_USERS or MANAGE_USERS permission "
1215 + "to: check " + name);
1216 }
1217 }
1218
1219 @Override
Bookatzf56f2582019-09-04 16:06:41 -07001220 public boolean isDemoUser(@UserIdInt int userId) {
Felipe Lemec1ca4412019-09-11 09:23:26 -07001221 final int callingUserId = UserHandle.getCallingUserId();
Amith Yamasani1c41dc82016-06-28 16:13:15 -07001222 if (callingUserId != userId && !hasManageUsersPermission()) {
1223 throw new SecurityException("You need MANAGE_USERS permission to query if u=" + userId
1224 + " is a demo user");
1225 }
1226 synchronized (mUsersLock) {
1227 UserInfo userInfo = getUserInfoLU(userId);
1228 return userInfo != null && userInfo.isDemo();
1229 }
1230 }
1231
1232 @Override
Felipe Lemec1ca4412019-09-11 09:23:26 -07001233 public boolean isPreCreated(@UserIdInt int userId) {
1234 final int callingUserId = UserHandle.getCallingUserId();
1235 if (callingUserId != userId && !hasManageUsersPermission()) {
1236 throw new SecurityException("You need MANAGE_USERS permission to query if u=" + userId
1237 + " is pre-created");
1238 }
1239 synchronized (mUsersLock) {
1240 UserInfo userInfo = getUserInfoLU(userId);
1241 return userInfo != null && userInfo.preCreated;
1242 }
1243 }
1244
1245 @Override
Amith Yamasani71e6c692013-03-24 17:39:28 -07001246 public boolean isRestricted() {
Fyodor Kupolov82402752015-10-28 14:54:51 -07001247 synchronized (mUsersLock) {
1248 return getUserInfoLU(UserHandle.getCallingUserId()).isRestricted();
Amith Yamasani71e6c692013-03-24 17:39:28 -07001249 }
1250 }
1251
Fyodor Kupolov1c363152015-09-02 13:27:21 -07001252 @Override
Bookatzf56f2582019-09-04 16:06:41 -07001253 public boolean canHaveRestrictedProfile(@UserIdInt int userId) {
Fyodor Kupolov1c363152015-09-02 13:27:21 -07001254 checkManageUsersPermission("canHaveRestrictedProfile");
Fyodor Kupolov82402752015-10-28 14:54:51 -07001255 synchronized (mUsersLock) {
1256 final UserInfo userInfo = getUserInfoLU(userId);
Fyodor Kupolov1c363152015-09-02 13:27:21 -07001257 if (userInfo == null || !userInfo.canHaveProfile()) {
1258 return false;
1259 }
1260 if (!userInfo.isAdmin()) {
1261 return false;
1262 }
Makoto Onukie7927da2015-11-25 10:05:17 -08001263 // restricted profile can be created if there is no DO set and the admin user has no PO;
1264 return !mIsDeviceManaged && !mIsUserManaged.get(userId);
Fyodor Kupolov1c363152015-09-02 13:27:21 -07001265 }
Fyodor Kupolov1c363152015-09-02 13:27:21 -07001266 }
1267
Fyodor Kupolovca177562017-11-09 17:43:01 -08001268 @Override
1269 public boolean hasRestrictedProfiles() {
1270 checkManageUsersPermission("hasRestrictedProfiles");
1271 final int callingUserId = UserHandle.getCallingUserId();
1272 synchronized (mUsersLock) {
1273 final int userSize = mUsers.size();
1274 for (int i = 0; i < userSize; i++) {
1275 UserInfo profile = mUsers.valueAt(i).info;
1276 if (callingUserId != profile.id
1277 && profile.restrictedProfileParentId == callingUserId) {
1278 return true;
1279 }
1280 }
1281 return false;
1282 }
1283 }
1284
Amith Yamasani195263742012-08-21 15:40:12 -07001285 /*
1286 * Should be locked on mUsers before calling this.
1287 */
Andreas Gampe2e8c7672018-07-20 13:01:08 -07001288 @GuardedBy("mUsersLock")
Bookatzf56f2582019-09-04 16:06:41 -07001289 private UserInfo getUserInfoLU(@UserIdInt int userId) {
Amith Yamasani12747872015-12-07 14:19:49 -08001290 final UserData userData = mUsers.get(userId);
Amith Yamasani16389312012-10-17 21:20:14 -07001291 // If it is partial and not in the process of being removed, return as unknown user.
Amith Yamasani12747872015-12-07 14:19:49 -08001292 if (userData != null && userData.info.partial && !mRemovingUserIds.get(userId)) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07001293 Slog.w(LOG_TAG, "getUserInfo: unknown user #" + userId);
1294 return null;
1295 }
Amith Yamasani12747872015-12-07 14:19:49 -08001296 return userData != null ? userData.info : null;
1297 }
1298
Andreas Gampe2e8c7672018-07-20 13:01:08 -07001299 @GuardedBy("mUsersLock")
Bookatzf56f2582019-09-04 16:06:41 -07001300 private UserData getUserDataLU(@UserIdInt int userId) {
Amith Yamasani12747872015-12-07 14:19:49 -08001301 final UserData userData = mUsers.get(userId);
1302 // If it is partial and not in the process of being removed, return as unknown user.
1303 if (userData != null && userData.info.partial && !mRemovingUserIds.get(userId)) {
1304 return null;
1305 }
1306 return userData;
Amith Yamasani195263742012-08-21 15:40:12 -07001307 }
1308
Fyodor Kupolov82402752015-10-28 14:54:51 -07001309 /**
1310 * Obtains {@link #mUsersLock} and return UserInfo from mUsers.
1311 * <p>No permissions checking or any addition checks are made</p>
1312 */
Bookatzf56f2582019-09-04 16:06:41 -07001313 private UserInfo getUserInfoNoChecks(@UserIdInt int userId) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07001314 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08001315 final UserData userData = mUsers.get(userId);
1316 return userData != null ? userData.info : null;
1317 }
1318 }
1319
1320 /**
1321 * Obtains {@link #mUsersLock} and return UserData from mUsers.
1322 * <p>No permissions checking or any addition checks are made</p>
1323 */
Bookatzf56f2582019-09-04 16:06:41 -07001324 private UserData getUserDataNoChecks(@UserIdInt int userId) {
Amith Yamasani12747872015-12-07 14:19:49 -08001325 synchronized (mUsersLock) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07001326 return mUsers.get(userId);
1327 }
1328 }
1329
Amith Yamasani236b2b52015-08-18 14:32:14 -07001330 /** Called by PackageManagerService */
Bookatzf56f2582019-09-04 16:06:41 -07001331 public boolean exists(@UserIdInt int userId) {
Todd Kennedy0eb97382017-10-03 16:57:22 -07001332 return mLocalService.exists(userId);
Amith Yamasani13593602012-03-22 16:16:17 -07001333 }
1334
Amith Yamasani258848d2012-08-10 17:06:33 -07001335 @Override
Bookatzf56f2582019-09-04 16:06:41 -07001336 public void setUserName(@UserIdInt int userId, String name) {
Amith Yamasani2a003292012-08-14 18:25:45 -07001337 checkManageUsersPermission("rename users");
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07001338 boolean changed = false;
Dianne Hackborn4428e172012-08-24 17:43:05 -07001339 synchronized (mPackagesLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08001340 UserData userData = getUserDataNoChecks(userId);
1341 if (userData == null || userData.info.partial) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07001342 Slog.w(LOG_TAG, "setUserName: unknown user #" + userId);
1343 return;
1344 }
Amith Yamasani12747872015-12-07 14:19:49 -08001345 if (name != null && !name.equals(userData.info.name)) {
1346 userData.info.name = name;
1347 writeUserLP(userData);
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07001348 changed = true;
Amith Yamasani13593602012-03-22 16:16:17 -07001349 }
1350 }
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07001351 if (changed) {
Bookatzf9368552019-03-14 11:57:09 -07001352 long ident = Binder.clearCallingIdentity();
1353 try {
1354 sendUserInfoChangedBroadcast(userId);
1355 } finally {
1356 Binder.restoreCallingIdentity(ident);
1357 }
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07001358 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07001359 }
1360
Amith Yamasani258848d2012-08-10 17:06:33 -07001361 @Override
Bookatzf56f2582019-09-04 16:06:41 -07001362 public void setUserIcon(@UserIdInt int userId, Bitmap bitmap) {
Amith Yamasani2a003292012-08-14 18:25:45 -07001363 checkManageUsersPermission("update users");
Oleksandr Peletskyi7f1f1df2016-01-18 15:40:21 +01001364 if (hasUserRestriction(UserManager.DISALLOW_SET_USER_ICON, userId)) {
1365 Log.w(LOG_TAG, "Cannot set user icon. DISALLOW_SET_USER_ICON is enabled.");
1366 return;
Amith Yamasanib8151ec2012-04-18 18:02:48 -07001367 }
Oleksandr Peletskyi7f1f1df2016-01-18 15:40:21 +01001368 mLocalService.setUserIcon(userId, bitmap);
Amith Yamasanie928d7d2012-09-17 21:46:51 -07001369 }
1370
Oleksandr Peletskyi7f1f1df2016-01-18 15:40:21 +01001371
1372
Bookatzf56f2582019-09-04 16:06:41 -07001373 private void sendUserInfoChangedBroadcast(@UserIdInt int userId) {
Amith Yamasanie928d7d2012-09-17 21:46:51 -07001374 Intent changedIntent = new Intent(Intent.ACTION_USER_INFO_CHANGED);
1375 changedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
1376 changedIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -07001377 mContext.sendBroadcastAsUser(changedIntent, UserHandle.ALL);
Amith Yamasanib8151ec2012-04-18 18:02:48 -07001378 }
1379
Amith Yamasani258848d2012-08-10 17:06:33 -07001380 @Override
Oleksandr Peletskyicd6fa302016-02-25 16:28:39 +01001381 public ParcelFileDescriptor getUserIcon(int targetUserId) {
Bookatzcde3d922019-03-08 14:30:00 -08001382 if (!hasManageUsersOrPermission(android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED)) {
1383 throw new SecurityException("You need MANAGE_USERS or GET_ACCOUNTS_PRIVILEGED "
1384 + "permissions to: get user icon");
1385 }
Adrian Roos1bdff912015-02-17 15:51:35 +01001386 String iconPath;
Amith Yamasani3b49f072012-09-17 10:21:43 -07001387 synchronized (mPackagesLock) {
Oleksandr Peletskyicd6fa302016-02-25 16:28:39 +01001388 UserInfo targetUserInfo = getUserInfoNoChecks(targetUserId);
1389 if (targetUserInfo == null || targetUserInfo.partial) {
1390 Slog.w(LOG_TAG, "getUserIcon: unknown user #" + targetUserId);
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07001391 return null;
1392 }
Oleksandr Peletskyicd6fa302016-02-25 16:28:39 +01001393
1394 final int callingUserId = UserHandle.getCallingUserId();
1395 final int callingGroupId = getUserInfoNoChecks(callingUserId).profileGroupId;
1396 final int targetGroupId = targetUserInfo.profileGroupId;
1397 final boolean sameGroup = (callingGroupId != UserInfo.NO_PROFILE_GROUP_ID
1398 && callingGroupId == targetGroupId);
1399 if ((callingUserId != targetUserId) && !sameGroup) {
Nicolas Prevot88cc3462014-05-14 14:51:48 +01001400 checkManageUsersPermission("get the icon of a user who is not related");
1401 }
Oleksandr Peletskyicd6fa302016-02-25 16:28:39 +01001402
1403 if (targetUserInfo.iconPath == null) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07001404 return null;
1405 }
Oleksandr Peletskyicd6fa302016-02-25 16:28:39 +01001406 iconPath = targetUserInfo.iconPath;
Amith Yamasani3b49f072012-09-17 10:21:43 -07001407 }
Adrian Roos1bdff912015-02-17 15:51:35 +01001408
1409 try {
1410 return ParcelFileDescriptor.open(
1411 new File(iconPath), ParcelFileDescriptor.MODE_READ_ONLY);
1412 } catch (FileNotFoundException e) {
1413 Log.e(LOG_TAG, "Couldn't find icon file", e);
1414 }
1415 return null;
Amith Yamasani3b49f072012-09-17 10:21:43 -07001416 }
1417
Bookatzf56f2582019-09-04 16:06:41 -07001418 public void makeInitialized(@UserIdInt int userId) {
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001419 checkManageUsersPermission("makeInitialized");
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001420 boolean scheduleWriteUser = false;
Amith Yamasani12747872015-12-07 14:19:49 -08001421 UserData userData;
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001422 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08001423 userData = mUsers.get(userId);
1424 if (userData == null || userData.info.partial) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07001425 Slog.w(LOG_TAG, "makeInitialized: unknown user #" + userId);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001426 return;
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07001427 }
Amith Yamasani12747872015-12-07 14:19:49 -08001428 if ((userData.info.flags & UserInfo.FLAG_INITIALIZED) == 0) {
1429 userData.info.flags |= UserInfo.FLAG_INITIALIZED;
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001430 scheduleWriteUser = true;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001431 }
1432 }
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001433 if (scheduleWriteUser) {
Amith Yamasani12747872015-12-07 14:19:49 -08001434 scheduleWriteUser(userData);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001435 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07001436 }
1437
Amith Yamasaniaa6634e2014-10-06 14:20:28 -07001438 /**
1439 * If default guest restrictions haven't been initialized yet, add the basic
1440 * restrictions.
1441 */
1442 private void initDefaultGuestRestrictions() {
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001443 synchronized (mGuestRestrictions) {
1444 if (mGuestRestrictions.isEmpty()) {
Samuel Tand9453b82016-03-14 15:57:02 -07001445 mGuestRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_WIFI, true);
Fyodor Kupolove04462c2015-11-30 15:02:53 -08001446 mGuestRestrictions.putBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001447 mGuestRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, true);
1448 mGuestRestrictions.putBoolean(UserManager.DISALLOW_SMS, true);
1449 }
Amith Yamasaniaa6634e2014-10-06 14:20:28 -07001450 }
1451 }
1452
Amith Yamasanie4cf7342012-12-17 11:12:09 -08001453 @Override
Amith Yamasanie4afaa32014-06-30 14:55:07 +05301454 public Bundle getDefaultGuestRestrictions() {
1455 checkManageUsersPermission("getDefaultGuestRestrictions");
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001456 synchronized (mGuestRestrictions) {
Amith Yamasanie4afaa32014-06-30 14:55:07 +05301457 return new Bundle(mGuestRestrictions);
1458 }
1459 }
1460
1461 @Override
1462 public void setDefaultGuestRestrictions(Bundle restrictions) {
1463 checkManageUsersPermission("setDefaultGuestRestrictions");
Fyodor Kupolove80085d2015-11-06 18:21:39 -08001464 synchronized (mGuestRestrictions) {
1465 mGuestRestrictions.clear();
1466 mGuestRestrictions.putAll(restrictions);
1467 }
1468 synchronized (mPackagesLock) {
1469 writeUserListLP();
Amith Yamasanie4afaa32014-06-30 14:55:07 +05301470 }
1471 }
1472
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001473 /**
Pavel Grafov6a40f092016-10-25 15:46:51 +01001474 * See {@link UserManagerInternal#setDevicePolicyUserRestrictions}
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001475 */
Bookatzf56f2582019-09-04 16:06:41 -07001476 private void setDevicePolicyUserRestrictionsInner(@UserIdInt int userId,
1477 @Nullable Bundle restrictions, boolean isDeviceOwner, int cameraRestrictionScope) {
Pavel Grafov6a40f092016-10-25 15:46:51 +01001478 final Bundle global = new Bundle();
1479 final Bundle local = new Bundle();
1480
1481 // Sort restrictions into local and global ensuring they don't overlap.
1482 UserRestrictionsUtils.sortToGlobalAndLocal(restrictions, isDeviceOwner,
1483 cameraRestrictionScope, global, local);
1484
1485 boolean globalChanged, localChanged;
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001486 synchronized (mRestrictionsLock) {
Pavel Grafov6a40f092016-10-25 15:46:51 +01001487 // Update global and local restrictions if they were changed.
1488 globalChanged = updateRestrictionsIfNeededLR(
1489 userId, global, mDevicePolicyGlobalUserRestrictions);
1490 localChanged = updateRestrictionsIfNeededLR(
1491 userId, local, mDevicePolicyLocalUserRestrictions);
1492
1493 if (isDeviceOwner) {
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +01001494 // Remember the global restriction owner userId to be able to make a distinction
1495 // in getUserRestrictionSource on who set local policies.
Pavel Grafov6a40f092016-10-25 15:46:51 +01001496 mDeviceOwnerUserId = userId;
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +01001497 } else {
Pavel Grafov6a40f092016-10-25 15:46:51 +01001498 if (mDeviceOwnerUserId == userId) {
Zoltan Szatmary-Ban8a5536d2016-05-27 17:56:44 +01001499 // When profile owner sets restrictions it passes null global bundle and we
1500 // reset global restriction owner userId.
1501 // This means this user used to have DO, but now the DO is gone and the user
1502 // instead has PO.
Pavel Grafov6a40f092016-10-25 15:46:51 +01001503 mDeviceOwnerUserId = UserHandle.USER_NULL;
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001504 }
1505 }
1506 }
1507 if (DBG) {
1508 Log.d(LOG_TAG, "setDevicePolicyUserRestrictions: userId=" + userId
1509 + " global=" + global + (globalChanged ? " (changed)" : "")
1510 + " local=" + local + (localChanged ? " (changed)" : "")
1511 );
1512 }
1513 // Don't call them within the mRestrictionsLock.
1514 synchronized (mPackagesLock) {
Pavel Grafov6a40f092016-10-25 15:46:51 +01001515 if (localChanged || globalChanged) {
Amith Yamasani12747872015-12-07 14:19:49 -08001516 writeUserLP(getUserDataNoChecks(userId));
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001517 }
1518 }
1519
1520 synchronized (mRestrictionsLock) {
1521 if (globalChanged) {
1522 applyUserRestrictionsForAllUsersLR();
1523 } else if (localChanged) {
1524 applyUserRestrictionsLR(userId);
1525 }
1526 }
1527 }
1528
Pavel Grafov6a40f092016-10-25 15:46:51 +01001529 /**
1530 * Updates restriction bundle for a given user in a given restriction array. If new bundle is
1531 * empty, record is removed from the array.
1532 * @return whether restrictions bundle is different from the old one.
1533 */
Bookatzf56f2582019-09-04 16:06:41 -07001534 private boolean updateRestrictionsIfNeededLR(@UserIdInt int userId,
1535 @Nullable Bundle restrictions, SparseArray<Bundle> restrictionsArray) {
Pavel Grafov6a40f092016-10-25 15:46:51 +01001536 final boolean changed =
1537 !UserRestrictionsUtils.areEqual(restrictionsArray.get(userId), restrictions);
1538 if (changed) {
1539 if (!UserRestrictionsUtils.isEmpty(restrictions)) {
1540 restrictionsArray.put(userId, restrictions);
1541 } else {
1542 restrictionsArray.delete(userId);
1543 }
1544 }
1545 return changed;
1546 }
1547
Makoto Onuki068c54a2015-10-13 14:34:03 -07001548 @GuardedBy("mRestrictionsLock")
Bookatzf56f2582019-09-04 16:06:41 -07001549 private Bundle computeEffectiveUserRestrictionsLR(@UserIdInt int userId) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001550 final Bundle baseRestrictions =
1551 UserRestrictionsUtils.nonNull(mBaseUserRestrictions.get(userId));
Pavel Grafov6a40f092016-10-25 15:46:51 +01001552 final Bundle global = UserRestrictionsUtils.mergeAll(mDevicePolicyGlobalUserRestrictions);
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001553 final Bundle local = mDevicePolicyLocalUserRestrictions.get(userId);
Makoto Onuki068c54a2015-10-13 14:34:03 -07001554
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001555 if (UserRestrictionsUtils.isEmpty(global) && UserRestrictionsUtils.isEmpty(local)) {
1556 // Common case first.
1557 return baseRestrictions;
Makoto Onuki068c54a2015-10-13 14:34:03 -07001558 }
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001559 final Bundle effective = UserRestrictionsUtils.clone(baseRestrictions);
1560 UserRestrictionsUtils.merge(effective, global);
1561 UserRestrictionsUtils.merge(effective, local);
1562
Makoto Onuki068c54a2015-10-13 14:34:03 -07001563 return effective;
1564 }
1565
1566 @GuardedBy("mRestrictionsLock")
Bookatzf56f2582019-09-04 16:06:41 -07001567 private void invalidateEffectiveUserRestrictionsLR(@UserIdInt int userId) {
Makoto Onuki068c54a2015-10-13 14:34:03 -07001568 if (DBG) {
1569 Log.d(LOG_TAG, "invalidateEffectiveUserRestrictions userId=" + userId);
1570 }
1571 mCachedEffectiveUserRestrictions.remove(userId);
1572 }
1573
Bookatzf56f2582019-09-04 16:06:41 -07001574 private Bundle getEffectiveUserRestrictions(@UserIdInt int userId) {
Makoto Onuki068c54a2015-10-13 14:34:03 -07001575 synchronized (mRestrictionsLock) {
1576 Bundle restrictions = mCachedEffectiveUserRestrictions.get(userId);
1577 if (restrictions == null) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07001578 restrictions = computeEffectiveUserRestrictionsLR(userId);
Makoto Onuki068c54a2015-10-13 14:34:03 -07001579 mCachedEffectiveUserRestrictions.put(userId, restrictions);
1580 }
1581 return restrictions;
Amith Yamasani8cd28b52014-06-08 17:54:27 -07001582 }
1583 }
1584
Makoto Onuki068c54a2015-10-13 14:34:03 -07001585 /** @return a specific user restriction that's in effect currently. */
1586 @Override
Bookatzf56f2582019-09-04 16:06:41 -07001587 public boolean hasUserRestriction(String restrictionKey, @UserIdInt int userId) {
Patrick Baumann2f2fd712019-07-31 15:18:53 -07001588 return mLocalService.hasUserRestriction(restrictionKey, userId);
Makoto Onuki068c54a2015-10-13 14:34:03 -07001589 }
1590
Makoto Onukiacc50462018-02-14 14:13:49 -08001591 /** @return if any user has the given restriction. */
1592 @Override
1593 public boolean hasUserRestrictionOnAnyUser(String restrictionKey) {
1594 if (!UserRestrictionsUtils.isValidRestriction(restrictionKey)) {
1595 return false;
1596 }
1597 final List<UserInfo> users = getUsers(/* excludeDying= */ true);
1598 for (int i = 0; i < users.size(); i++) {
1599 final int userId = users.get(i).id;
1600 Bundle restrictions = getEffectiveUserRestrictions(userId);
1601 if (restrictions != null && restrictions.getBoolean(restrictionKey)) {
1602 return true;
1603 }
1604 }
1605 return false;
1606 }
1607
Makoto Onuki068c54a2015-10-13 14:34:03 -07001608 /**
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +01001609 * @hide
1610 *
1611 * Returns who set a user restriction on a user.
1612 * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
1613 * @param restrictionKey the string key representing the restriction
1614 * @param userId the id of the user for whom to retrieve the restrictions.
1615 * @return The source of user restriction. Any combination of
1616 * {@link UserManager#RESTRICTION_NOT_SET},
1617 * {@link UserManager#RESTRICTION_SOURCE_SYSTEM},
1618 * {@link UserManager#RESTRICTION_SOURCE_DEVICE_OWNER}
1619 * and {@link UserManager#RESTRICTION_SOURCE_PROFILE_OWNER}
1620 */
1621 @Override
Bookatzf56f2582019-09-04 16:06:41 -07001622 public int getUserRestrictionSource(String restrictionKey, @UserIdInt int userId) {
Pavel Grafov6a40f092016-10-25 15:46:51 +01001623 List<EnforcingUser> enforcingUsers = getUserRestrictionSources(restrictionKey, userId);
1624 // Get "bitwise or" of restriction sources for all enforcing users.
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +01001625 int result = UserManager.RESTRICTION_NOT_SET;
Pavel Grafov6a40f092016-10-25 15:46:51 +01001626 for (int i = enforcingUsers.size() - 1; i >= 0; i--) {
1627 result |= enforcingUsers.get(i).getUserRestrictionSource();
1628 }
1629 return result;
1630 }
1631
1632 @Override
1633 public List<EnforcingUser> getUserRestrictionSources(
1634 String restrictionKey, @UserIdInt int userId) {
1635 checkManageUsersPermission("getUserRestrictionSource");
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +01001636
1637 // Shortcut for the most common case
1638 if (!hasUserRestriction(restrictionKey, userId)) {
Pavel Grafov6a40f092016-10-25 15:46:51 +01001639 return Collections.emptyList();
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +01001640 }
1641
Pavel Grafov6a40f092016-10-25 15:46:51 +01001642 final List<EnforcingUser> result = new ArrayList<>();
1643
1644 // Check if it is base restriction.
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +01001645 if (hasBaseUserRestriction(restrictionKey, userId)) {
Pavel Grafov6a40f092016-10-25 15:46:51 +01001646 result.add(new EnforcingUser(
1647 UserHandle.USER_NULL, UserManager.RESTRICTION_SOURCE_SYSTEM));
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +01001648 }
1649
Pavel Grafov6a40f092016-10-25 15:46:51 +01001650 synchronized (mRestrictionsLock) {
1651 // Check if it is set by profile owner.
1652 Bundle profileOwnerRestrictions = mDevicePolicyLocalUserRestrictions.get(userId);
1653 if (UserRestrictionsUtils.contains(profileOwnerRestrictions, restrictionKey)) {
1654 result.add(getEnforcingUserLocked(userId));
1655 }
1656
1657 // Iterate over all users who enforce global restrictions.
1658 for (int i = mDevicePolicyGlobalUserRestrictions.size() - 1; i >= 0; i--) {
1659 Bundle globalRestrictions = mDevicePolicyGlobalUserRestrictions.valueAt(i);
1660 int profileUserId = mDevicePolicyGlobalUserRestrictions.keyAt(i);
1661 if (UserRestrictionsUtils.contains(globalRestrictions, restrictionKey)) {
1662 result.add(getEnforcingUserLocked(profileUserId));
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +01001663 }
1664 }
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +01001665 }
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +01001666 return result;
1667 }
1668
Andreas Gampea36dc622018-02-05 17:19:22 -08001669 @GuardedBy("mRestrictionsLock")
Pavel Grafov6a40f092016-10-25 15:46:51 +01001670 private EnforcingUser getEnforcingUserLocked(@UserIdInt int userId) {
1671 int source = mDeviceOwnerUserId == userId ? UserManager.RESTRICTION_SOURCE_DEVICE_OWNER
1672 : UserManager.RESTRICTION_SOURCE_PROFILE_OWNER;
1673 return new EnforcingUser(userId, source);
1674 }
1675
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +01001676 /**
Makoto Onuki068c54a2015-10-13 14:34:03 -07001677 * @return UserRestrictions that are in effect currently. This always returns a new
1678 * {@link Bundle}.
1679 */
Amith Yamasani8cd28b52014-06-08 17:54:27 -07001680 @Override
Bookatzf56f2582019-09-04 16:06:41 -07001681 public Bundle getUserRestrictions(@UserIdInt int userId) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001682 return UserRestrictionsUtils.clone(getEffectiveUserRestrictions(userId));
Amith Yamasanie4cf7342012-12-17 11:12:09 -08001683 }
1684
1685 @Override
Bookatzf56f2582019-09-04 16:06:41 -07001686 public boolean hasBaseUserRestriction(String restrictionKey, @UserIdInt int userId) {
Zoltan Szatmary-Ban3bbcedd2015-11-26 13:45:51 +00001687 checkManageUsersPermission("hasBaseUserRestriction");
Makoto Onuki1f1ceef2016-01-28 11:32:32 -08001688 if (!UserRestrictionsUtils.isValidRestriction(restrictionKey)) {
1689 return false;
1690 }
Zoltan Szatmary-Ban3bbcedd2015-11-26 13:45:51 +00001691 synchronized (mRestrictionsLock) {
1692 Bundle bundle = mBaseUserRestrictions.get(userId);
1693 return (bundle != null && bundle.getBoolean(restrictionKey, false));
1694 }
1695 }
1696
1697 @Override
Bookatzf56f2582019-09-04 16:06:41 -07001698 public void setUserRestriction(String key, boolean value, @UserIdInt int userId) {
Fyodor Kupolovd4b26042015-07-27 14:30:59 -07001699 checkManageUsersPermission("setUserRestriction");
Makoto Onuki1f1ceef2016-01-28 11:32:32 -08001700 if (!UserRestrictionsUtils.isValidRestriction(key)) {
1701 return;
1702 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07001703 synchronized (mRestrictionsLock) {
1704 // Note we can't modify Bundles stored in mBaseUserRestrictions directly, so create
1705 // a copy.
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001706 final Bundle newRestrictions = UserRestrictionsUtils.clone(
1707 mBaseUserRestrictions.get(userId));
Makoto Onuki068c54a2015-10-13 14:34:03 -07001708 newRestrictions.putBoolean(key, value);
1709
Fyodor Kupolov82402752015-10-28 14:54:51 -07001710 updateUserRestrictionsInternalLR(newRestrictions, userId);
Fyodor Kupolovb5013302015-04-17 17:59:14 -07001711 }
1712 }
1713
Makoto Onuki068c54a2015-10-13 14:34:03 -07001714 /**
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001715 * Optionally updating user restrictions, calculate the effective user restrictions and also
1716 * propagate to other services and system settings.
Makoto Onuki068c54a2015-10-13 14:34:03 -07001717 *
Pavel Grafov6a40f092016-10-25 15:46:51 +01001718 * @param newBaseRestrictions User restrictions to set.
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001719 * If null, will not update user restrictions and only does the propagation.
Makoto Onuki068c54a2015-10-13 14:34:03 -07001720 * @param userId target user ID.
1721 */
1722 @GuardedBy("mRestrictionsLock")
Fyodor Kupolov82402752015-10-28 14:54:51 -07001723 private void updateUserRestrictionsInternalLR(
Bookatzf56f2582019-09-04 16:06:41 -07001724 @Nullable Bundle newBaseRestrictions, @UserIdInt int userId) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001725 final Bundle prevAppliedRestrictions = UserRestrictionsUtils.nonNull(
1726 mAppliedUserRestrictions.get(userId));
1727
1728 // Update base restrictions.
Pavel Grafov6a40f092016-10-25 15:46:51 +01001729 if (newBaseRestrictions != null) {
1730 // If newBaseRestrictions == the current one, it's probably a bug.
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001731 final Bundle prevBaseRestrictions = mBaseUserRestrictions.get(userId);
1732
Pavel Grafov6a40f092016-10-25 15:46:51 +01001733 Preconditions.checkState(prevBaseRestrictions != newBaseRestrictions);
Makoto Onuki068c54a2015-10-13 14:34:03 -07001734 Preconditions.checkState(mCachedEffectiveUserRestrictions.get(userId)
Pavel Grafov6a40f092016-10-25 15:46:51 +01001735 != newBaseRestrictions);
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001736
Pavel Grafov6a40f092016-10-25 15:46:51 +01001737 if (updateRestrictionsIfNeededLR(userId, newBaseRestrictions, mBaseUserRestrictions)) {
Amith Yamasani12747872015-12-07 14:19:49 -08001738 scheduleWriteUser(getUserDataNoChecks(userId));
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001739 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07001740 }
1741
Fyodor Kupolov82402752015-10-28 14:54:51 -07001742 final Bundle effective = computeEffectiveUserRestrictionsLR(userId);
Makoto Onuki068c54a2015-10-13 14:34:03 -07001743
Makoto Onuki759a7632015-10-28 16:43:10 -07001744 mCachedEffectiveUserRestrictions.put(userId, effective);
1745
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001746 // Apply the new restrictions.
Makoto Onuki4f160732015-10-27 17:15:38 -07001747 if (DBG) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001748 debug("Applying user restrictions: userId=" + userId
1749 + " new=" + effective + " prev=" + prevAppliedRestrictions);
Makoto Onuki4f160732015-10-27 17:15:38 -07001750 }
1751
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001752 if (mAppOpsService != null) { // We skip it until system-ready.
Fyodor Kupolovec30ca32016-06-16 15:09:29 -07001753 mHandler.post(new Runnable() {
1754 @Override
1755 public void run() {
1756 try {
1757 mAppOpsService.setUserRestrictions(effective, mUserRestriconToken, userId);
1758 } catch (RemoteException e) {
1759 Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
1760 }
1761 }
1762 });
Fyodor Kupolovb5013302015-04-17 17:59:14 -07001763 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07001764
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001765 propagateUserRestrictionsLR(userId, effective, prevAppliedRestrictions);
Makoto Onuki4f160732015-10-27 17:15:38 -07001766
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001767 mAppliedUserRestrictions.put(userId, new Bundle(effective));
Makoto Onuki068c54a2015-10-13 14:34:03 -07001768 }
1769
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001770 private void propagateUserRestrictionsLR(final int userId,
Makoto Onukid45a4a22015-11-02 17:17:38 -08001771 Bundle newRestrictions, Bundle prevRestrictions) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001772 // Note this method doesn't touch any state, meaning it doesn't require mRestrictionsLock
1773 // actually, but we still need some kind of synchronization otherwise we might end up
1774 // calling listeners out-of-order, thus "LR".
1775
1776 if (UserRestrictionsUtils.areEqual(newRestrictions, prevRestrictions)) {
1777 return;
1778 }
Makoto Onukid45a4a22015-11-02 17:17:38 -08001779
1780 final Bundle newRestrictionsFinal = new Bundle(newRestrictions);
1781 final Bundle prevRestrictionsFinal = new Bundle(prevRestrictions);
1782
1783 mHandler.post(new Runnable() {
1784 @Override
1785 public void run() {
Fyodor Kupolov9cbfc9e2015-10-07 15:52:33 -07001786 UserRestrictionsUtils.applyUserRestrictions(
1787 mContext, userId, newRestrictionsFinal, prevRestrictionsFinal);
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001788
Makoto Onukid45a4a22015-11-02 17:17:38 -08001789 final UserRestrictionsListener[] listeners;
1790 synchronized (mUserRestrictionsListeners) {
1791 listeners = new UserRestrictionsListener[mUserRestrictionsListeners.size()];
1792 mUserRestrictionsListeners.toArray(listeners);
1793 }
1794 for (int i = 0; i < listeners.length; i++) {
1795 listeners[i].onUserRestrictionsChanged(userId,
1796 newRestrictionsFinal, prevRestrictionsFinal);
1797 }
Makoto Onukie72f81b2017-03-16 14:08:19 -07001798
1799 final Intent broadcast = new Intent(UserManager.ACTION_USER_RESTRICTIONS_CHANGED)
1800 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1801 mContext.sendBroadcastAsUser(broadcast, UserHandle.of(userId));
Makoto Onukid45a4a22015-11-02 17:17:38 -08001802 }
1803 });
1804 }
1805
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001806 // Package private for the inner class.
Andreas Gampe2e8c7672018-07-20 13:01:08 -07001807 @GuardedBy("mRestrictionsLock")
Bookatzf56f2582019-09-04 16:06:41 -07001808 void applyUserRestrictionsLR(@UserIdInt int userId) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07001809 updateUserRestrictionsInternalLR(null, userId);
Makoto Onuki068c54a2015-10-13 14:34:03 -07001810 }
1811
1812 @GuardedBy("mRestrictionsLock")
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001813 // Package private for the inner class.
1814 void applyUserRestrictionsForAllUsersLR() {
1815 if (DBG) {
1816 debug("applyUserRestrictionsForAllUsersLR");
1817 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07001818 // First, invalidate all cached values.
Makoto Onuki4f160732015-10-27 17:15:38 -07001819 mCachedEffectiveUserRestrictions.clear();
1820
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001821 // We don't want to call into ActivityManagerService while taking a lock, so we'll call
Makoto Onuki068c54a2015-10-13 14:34:03 -07001822 // it on a handler.
1823 final Runnable r = new Runnable() {
1824 @Override
1825 public void run() {
1826 // Then get the list of running users.
1827 final int[] runningUsers;
1828 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001829 runningUsers = ActivityManager.getService().getRunningUserIds();
Makoto Onuki068c54a2015-10-13 14:34:03 -07001830 } catch (RemoteException e) {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001831 Log.w(LOG_TAG, "Unable to access ActivityManagerService");
Makoto Onuki068c54a2015-10-13 14:34:03 -07001832 return;
1833 }
1834 // Then re-calculate the effective restrictions and apply, only for running users.
1835 // It's okay if a new user has started after the getRunningUserIds() call,
1836 // because we'll do the same thing (re-calculate the restrictions and apply)
1837 // when we start a user.
Makoto Onuki068c54a2015-10-13 14:34:03 -07001838 synchronized (mRestrictionsLock) {
1839 for (int i = 0; i < runningUsers.length; i++) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08001840 applyUserRestrictionsLR(runningUsers[i]);
Makoto Onuki068c54a2015-10-13 14:34:03 -07001841 }
1842 }
1843 }
1844 };
1845 mHandler.post(r);
Fyodor Kupolovb5013302015-04-17 17:59:14 -07001846 }
1847
Amith Yamasani258848d2012-08-10 17:06:33 -07001848 /**
Amith Yamasanifaea76f2012-09-11 10:59:48 -07001849 * Check if we've hit the limit of how many users can be created.
1850 */
Fyodor Kupolov82402752015-10-28 14:54:51 -07001851 private boolean isUserLimitReached() {
1852 int count;
1853 synchronized (mUsersLock) {
1854 count = getAliveUsersExcludingGuestsCountLU();
1855 }
1856 return count >= UserManager.getMaxSupportedUsers();
Nicolas Prevot12678a92015-05-13 12:15:03 -07001857 }
1858
1859 @Override
Bookatzf56f2582019-09-04 16:06:41 -07001860 public boolean canAddMoreManagedProfiles(@UserIdInt int userId, boolean allowedToRemoveOne) {
Nicolas Prevot12678a92015-05-13 12:15:03 -07001861 checkManageUsersPermission("check if more managed profiles can be added.");
1862 if (ActivityManager.isLowRamDeviceStatic()) {
1863 return false;
1864 }
Fyodor Kupolovb6157992015-06-05 15:32:28 -07001865 if (!mContext.getPackageManager().hasSystemFeature(
1866 PackageManager.FEATURE_MANAGED_USERS)) {
1867 return false;
1868 }
Nicolas Prevotb8186812015-08-06 15:00:03 +01001869 // Limit number of managed profiles that can be created
Benjamin Franzc8776152017-01-06 14:16:41 +00001870 final int managedProfilesCount = getProfiles(userId, false).size() - 1;
Nicolas Prevot07387fe2015-10-30 17:53:30 +00001871 final int profilesRemovedCount = managedProfilesCount > 0 && allowedToRemoveOne ? 1 : 0;
Kenny Guy02c89902016-11-15 19:36:38 +00001872 if (managedProfilesCount - profilesRemovedCount >= getMaxManagedProfiles()) {
Nicolas Prevotb8186812015-08-06 15:00:03 +01001873 return false;
1874 }
Fyodor Kupolov82402752015-10-28 14:54:51 -07001875 synchronized(mUsersLock) {
1876 UserInfo userInfo = getUserInfoLU(userId);
yuanhao47f9f7c2017-01-18 09:54:45 +08001877 if (userInfo == null || !userInfo.canHaveProfile()) {
Nicolas Prevot12678a92015-05-13 12:15:03 -07001878 return false;
1879 }
Nicolas Prevot07387fe2015-10-30 17:53:30 +00001880 int usersCountAfterRemoving = getAliveUsersExcludingGuestsCountLU()
1881 - profilesRemovedCount;
Nicolas Prevot12678a92015-05-13 12:15:03 -07001882 // We allow creating a managed profile in the special case where there is only one user.
Nicolas Prevot07387fe2015-10-30 17:53:30 +00001883 return usersCountAfterRemoving == 1
1884 || usersCountAfterRemoving < UserManager.getMaxSupportedUsers();
Nicolas Prevot12678a92015-05-13 12:15:03 -07001885 }
1886 }
1887
Andreas Gampe2e8c7672018-07-20 13:01:08 -07001888 @GuardedBy("mUsersLock")
Fyodor Kupolov82402752015-10-28 14:54:51 -07001889 private int getAliveUsersExcludingGuestsCountLU() {
Amith Yamasanif584f012014-05-19 17:57:25 -07001890 int aliveUserCount = 0;
1891 final int totalUserCount = mUsers.size();
1892 // Skip over users being removed
1893 for (int i = 0; i < totalUserCount; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -08001894 UserInfo user = mUsers.valueAt(i).info;
Felipe Lemec1ca4412019-09-11 09:23:26 -07001895 if (!mRemovingUserIds.get(user.id) && !user.isGuest() && !user.preCreated) {
Amith Yamasanif584f012014-05-19 17:57:25 -07001896 aliveUserCount++;
1897 }
1898 }
Nicolas Prevot12678a92015-05-13 12:15:03 -07001899 return aliveUserCount;
Amith Yamasanifaea76f2012-09-11 10:59:48 -07001900 }
1901
1902 /**
Amith Yamasani195263742012-08-21 15:40:12 -07001903 * Enforces that only the system UID or root's UID or apps that have the
Xiaohui Chenb3b92582015-12-07 11:22:13 -08001904 * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} and
1905 * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL INTERACT_ACROSS_USERS_FULL}
1906 * permissions can make certain calls to the UserManager.
1907 *
1908 * @param message used as message if SecurityException is thrown
1909 * @throws SecurityException if the caller does not have enough privilege.
1910 */
1911 private static final void checkManageUserAndAcrossUsersFullPermission(String message) {
1912 final int uid = Binder.getCallingUid();
jovanakf24ad492018-05-18 12:15:59 -07001913
1914 if (uid == Process.SYSTEM_UID || uid == 0) {
1915 // System UID or root's UID are granted privilege.
1916 return;
Xiaohui Chenb3b92582015-12-07 11:22:13 -08001917 }
jovanakf24ad492018-05-18 12:15:59 -07001918
1919 if (hasPermissionGranted(Manifest.permission.MANAGE_USERS, uid)
1920 && hasPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS_FULL, uid)) {
1921 // Apps with both permissions are granted privilege.
1922 return;
1923 }
1924
1925 throw new SecurityException(
1926 "You need MANAGE_USERS and INTERACT_ACROSS_USERS_FULL permission to: " + message);
1927 }
1928
1929 private static boolean hasPermissionGranted(String permission, int uid) {
1930 return ActivityManager.checkComponentPermission(
1931 permission, uid, /* owningUid = */-1, /* exported = */ true) ==
1932 PackageManager.PERMISSION_GRANTED;
Xiaohui Chenb3b92582015-12-07 11:22:13 -08001933 }
1934
1935 /**
1936 * Enforces that only the system UID or root's UID or apps that have the
Dianne Hackborn10ad9822014-03-17 11:28:36 -07001937 * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS}
Amith Yamasani195263742012-08-21 15:40:12 -07001938 * permission can make certain calls to the UserManager.
Amith Yamasani258848d2012-08-10 17:06:33 -07001939 *
1940 * @param message used as message if SecurityException is thrown
1941 * @throws SecurityException if the caller is not system or root
Tony Mak4dc008c2016-03-16 10:46:49 +00001942 * @see #hasManageUsersPermission()
Amith Yamasani258848d2012-08-10 17:06:33 -07001943 */
Amith Yamasanibe465322014-04-24 13:45:17 -07001944 private static final void checkManageUsersPermission(String message) {
Tony Mak4dc008c2016-03-16 10:46:49 +00001945 if (!hasManageUsersPermission()) {
Amith Yamasanibe465322014-04-24 13:45:17 -07001946 throw new SecurityException("You need MANAGE_USERS permission to: " + message);
1947 }
Emily Bernier7a2b4d12014-04-23 12:51:35 -04001948 }
1949
Esteban Talavera5b9f1672015-12-11 15:22:34 +00001950 /**
Sudheer Shankaf5cea032016-06-08 17:13:24 -07001951 * Enforces that only the system UID or root's UID or apps that have the
1952 * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or
1953 * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS}
1954 * can make certain calls to the UserManager.
1955 *
1956 * @param message used as message if SecurityException is thrown
1957 * @throws SecurityException if the caller is not system or root
1958 * @see #hasManageOrCreateUsersPermission()
1959 */
1960 private static final void checkManageOrCreateUsersPermission(String message) {
1961 if (!hasManageOrCreateUsersPermission()) {
1962 throw new SecurityException(
1963 "You either need MANAGE_USERS or CREATE_USERS permission to: " + message);
1964 }
1965 }
1966
1967 /**
1968 * Similar to {@link #checkManageOrCreateUsersPermission(String)} but when the caller is tries
1969 * to create user/profiles other than what is allowed for
1970 * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS} permission, then it will only
1971 * allow callers with {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} permission.
1972 */
1973 private static final void checkManageOrCreateUsersPermission(int creationFlags) {
1974 if ((creationFlags & ~ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION) == 0) {
1975 if (!hasManageOrCreateUsersPermission()) {
1976 throw new SecurityException("You either need MANAGE_USERS or CREATE_USERS "
1977 + "permission to create an user with flags: " + creationFlags);
1978 }
1979 } else if (!hasManageUsersPermission()) {
1980 throw new SecurityException("You need MANAGE_USERS permission to create an user "
1981 + " with flags: " + creationFlags);
1982 }
1983 }
1984
1985 /**
Tony Mak4dc008c2016-03-16 10:46:49 +00001986 * @return whether the calling UID is system UID or root's UID or the calling app has the
1987 * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS}.
1988 */
1989 private static final boolean hasManageUsersPermission() {
1990 final int callingUid = Binder.getCallingUid();
1991 return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
1992 || callingUid == Process.ROOT_UID
jovanakf24ad492018-05-18 12:15:59 -07001993 || hasPermissionGranted(android.Manifest.permission.MANAGE_USERS, callingUid);
Tony Mak4dc008c2016-03-16 10:46:49 +00001994 }
1995
1996 /**
Sudheer Shankaf5cea032016-06-08 17:13:24 -07001997 * @return whether the calling UID is system UID or root's UID or the calling app has the
Bookatzcde3d922019-03-08 14:30:00 -08001998 * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or the provided permission.
Sudheer Shankaf5cea032016-06-08 17:13:24 -07001999 */
Bookatzcde3d922019-03-08 14:30:00 -08002000 private static final boolean hasManageUsersOrPermission(String alternativePermission) {
Sudheer Shankaf5cea032016-06-08 17:13:24 -07002001 final int callingUid = Binder.getCallingUid();
2002 return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
2003 || callingUid == Process.ROOT_UID
jovanakf24ad492018-05-18 12:15:59 -07002004 || hasPermissionGranted(android.Manifest.permission.MANAGE_USERS, callingUid)
Bookatzcde3d922019-03-08 14:30:00 -08002005 || hasPermissionGranted(alternativePermission, callingUid);
2006 }
2007
2008 /**
2009 * @return whether the calling UID is system UID or root's UID or the calling app has the
2010 * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or
2011 * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS}.
2012 */
2013 private static final boolean hasManageOrCreateUsersPermission() {
2014 return hasManageUsersOrPermission(android.Manifest.permission.CREATE_USERS);
Sudheer Shankaf5cea032016-06-08 17:13:24 -07002015 }
2016
2017 /**
Esteban Talavera5b9f1672015-12-11 15:22:34 +00002018 * Enforces that only the system UID or root's UID (on any user) can make certain calls to the
2019 * UserManager.
2020 *
2021 * @param message used as message if SecurityException is thrown
2022 * @throws SecurityException if the caller is not system or root
2023 */
2024 private static void checkSystemOrRoot(String message) {
2025 final int uid = Binder.getCallingUid();
2026 if (!UserHandle.isSameApp(uid, Process.SYSTEM_UID) && uid != Process.ROOT_UID) {
2027 throw new SecurityException("Only system may: " + message);
2028 }
2029 }
2030
Fyodor Kupolov82402752015-10-28 14:54:51 -07002031 private void writeBitmapLP(UserInfo info, Bitmap bitmap) {
Amith Yamasanib8151ec2012-04-18 18:02:48 -07002032 try {
2033 File dir = new File(mUsersDir, Integer.toString(info.id));
2034 File file = new File(dir, USER_PHOTO_FILENAME);
Adrian Roos1bdff912015-02-17 15:51:35 +01002035 File tmp = new File(dir, USER_PHOTO_FILENAME_TMP);
Amith Yamasanib8151ec2012-04-18 18:02:48 -07002036 if (!dir.exists()) {
2037 dir.mkdir();
2038 FileUtils.setPermissions(
2039 dir.getPath(),
2040 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2041 -1, -1);
2042 }
Amith Yamasanie928d7d2012-09-17 21:46:51 -07002043 FileOutputStream os;
Adrian Roos1bdff912015-02-17 15:51:35 +01002044 if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, os = new FileOutputStream(tmp))
Oleksandr Peletskyicd6fa302016-02-25 16:28:39 +01002045 && tmp.renameTo(file) && SELinux.restorecon(file)) {
Amith Yamasani3b49f072012-09-17 10:21:43 -07002046 info.iconPath = file.getAbsolutePath();
2047 }
Amith Yamasanie928d7d2012-09-17 21:46:51 -07002048 try {
2049 os.close();
2050 } catch (IOException ioe) {
2051 // What the ... !
2052 }
Adrian Roos1bdff912015-02-17 15:51:35 +01002053 tmp.delete();
Amith Yamasanib8151ec2012-04-18 18:02:48 -07002054 } catch (FileNotFoundException e) {
Amith Yamasani2a003292012-08-14 18:25:45 -07002055 Slog.w(LOG_TAG, "Error setting photo for user ", e);
Amith Yamasanib8151ec2012-04-18 18:02:48 -07002056 }
Amith Yamasanib8151ec2012-04-18 18:02:48 -07002057 }
2058
Amith Yamasani0b285492011-04-14 17:35:23 -07002059 /**
2060 * Returns an array of user ids. This array is cached here for quick access, so do not modify or
2061 * cache it elsewhere.
2062 * @return the array of user ids.
2063 */
Dianne Hackborn1676c852012-09-10 14:52:30 -07002064 public int[] getUserIds() {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002065 synchronized (mUsersLock) {
Dianne Hackborn7767eac2012-08-23 18:25:40 -07002066 return mUserIds;
2067 }
Amith Yamasani0b285492011-04-14 17:35:23 -07002068 }
2069
Andreas Gampe2e8c7672018-07-20 13:01:08 -07002070 @GuardedBy({"mRestrictionsLock", "mPackagesLock"})
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002071 private void readUserListLP() {
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002072 if (!mUserListFile.exists()) {
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002073 fallbackToSingleUserLP();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002074 return;
2075 }
2076 FileInputStream fis = null;
Amith Yamasani2a003292012-08-14 18:25:45 -07002077 AtomicFile userListFile = new AtomicFile(mUserListFile);
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002078 try {
Amith Yamasani2a003292012-08-14 18:25:45 -07002079 fis = userListFile.openRead();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002080 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01002081 parser.setInput(fis, StandardCharsets.UTF_8.name());
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002082 int type;
2083 while ((type = parser.next()) != XmlPullParser.START_TAG
2084 && type != XmlPullParser.END_DOCUMENT) {
Amith Yamasani12747872015-12-07 14:19:49 -08002085 // Skip
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002086 }
2087
2088 if (type != XmlPullParser.START_TAG) {
Amith Yamasani0b285492011-04-14 17:35:23 -07002089 Slog.e(LOG_TAG, "Unable to read user list");
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002090 fallbackToSingleUserLP();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002091 return;
2092 }
2093
Amith Yamasani2a003292012-08-14 18:25:45 -07002094 mNextSerialNumber = -1;
2095 if (parser.getName().equals(TAG_USERS)) {
2096 String lastSerialNumber = parser.getAttributeValue(null, ATTR_NEXT_SERIAL_NO);
2097 if (lastSerialNumber != null) {
2098 mNextSerialNumber = Integer.parseInt(lastSerialNumber);
2099 }
Amith Yamasani6f34b412012-10-22 18:19:27 -07002100 String versionNumber = parser.getAttributeValue(null, ATTR_USER_VERSION);
2101 if (versionNumber != null) {
2102 mUserVersion = Integer.parseInt(versionNumber);
2103 }
Amith Yamasani2a003292012-08-14 18:25:45 -07002104 }
2105
Pavel Grafov6a40f092016-10-25 15:46:51 +01002106 // Pre-O global user restriction were stored as a single bundle (as opposed to per-user
2107 // currently), take care of it in case of upgrade.
2108 Bundle oldDevicePolicyGlobalUserRestrictions = null;
Makoto Onuki1a2cd742015-11-16 13:51:27 -08002109
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002110 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
Amith Yamasanie4afaa32014-06-30 14:55:07 +05302111 if (type == XmlPullParser.START_TAG) {
2112 final String name = parser.getName();
2113 if (name.equals(TAG_USER)) {
2114 String id = parser.getAttributeValue(null, ATTR_ID);
Amith Yamasani6f34b412012-10-22 18:19:27 -07002115
Amith Yamasani12747872015-12-07 14:19:49 -08002116 UserData userData = readUserLP(Integer.parseInt(id));
2117
2118 if (userData != null) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07002119 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08002120 mUsers.put(userData.info.id, userData);
2121 if (mNextSerialNumber < 0
2122 || mNextSerialNumber <= userData.info.id) {
2123 mNextSerialNumber = userData.info.id + 1;
Fyodor Kupolov82402752015-10-28 14:54:51 -07002124 }
Amith Yamasanie4afaa32014-06-30 14:55:07 +05302125 }
Amith Yamasani2a003292012-08-14 18:25:45 -07002126 }
Amith Yamasanie4afaa32014-06-30 14:55:07 +05302127 } else if (name.equals(TAG_GUEST_RESTRICTIONS)) {
Amith Yamasanida0b1682014-11-21 12:58:17 -08002128 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2129 && type != XmlPullParser.END_TAG) {
2130 if (type == XmlPullParser.START_TAG) {
2131 if (parser.getName().equals(TAG_RESTRICTIONS)) {
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002132 synchronized (mGuestRestrictions) {
Fyodor Kupoloveafee022017-03-15 17:09:04 -07002133 UserRestrictionsUtils
2134 .readRestrictions(parser, mGuestRestrictions);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002135 }
Amith Yamasanida0b1682014-11-21 12:58:17 -08002136 }
2137 break;
2138 }
2139 }
Pavel Grafov6a40f092016-10-25 15:46:51 +01002140 } else if (name.equals(TAG_DEVICE_OWNER_USER_ID)
2141 // Legacy name, should only be encountered when upgrading from pre-O.
2142 || name.equals(TAG_GLOBAL_RESTRICTION_OWNER_ID)) {
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +01002143 String ownerUserId = parser.getAttributeValue(null, ATTR_ID);
2144 if (ownerUserId != null) {
Pavel Grafov6a40f092016-10-25 15:46:51 +01002145 mDeviceOwnerUserId = Integer.parseInt(ownerUserId);
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +01002146 }
Pavel Grafov6a40f092016-10-25 15:46:51 +01002147 } else if (name.equals(TAG_DEVICE_POLICY_RESTRICTIONS)) {
2148 // Should only happen when upgrading from pre-O (version < 7).
2149 oldDevicePolicyGlobalUserRestrictions =
2150 UserRestrictionsUtils.readRestrictions(parser);
Amith Yamasani258848d2012-08-10 17:06:33 -07002151 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002152 }
2153 }
Pavel Grafov6a40f092016-10-25 15:46:51 +01002154
Fyodor Kupolov82402752015-10-28 14:54:51 -07002155 updateUserIds();
Pavel Grafov6a40f092016-10-25 15:46:51 +01002156 upgradeIfNecessaryLP(oldDevicePolicyGlobalUserRestrictions);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002157 } catch (IOException | XmlPullParserException e) {
2158 fallbackToSingleUserLP();
Dianne Hackbornbfd89b32011-12-15 18:22:54 -08002159 } finally {
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002160 IoUtils.closeQuietly(fis);
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002161 }
2162 }
2163
Amith Yamasani6f34b412012-10-22 18:19:27 -07002164 /**
Amith Yamasanibc9625052012-11-15 14:39:18 -08002165 * Upgrade steps between versions, either for fixing bugs or changing the data format.
Pavel Grafov6a40f092016-10-25 15:46:51 +01002166 * @param oldGlobalUserRestrictions Pre-O global device policy restrictions.
Amith Yamasani6f34b412012-10-22 18:19:27 -07002167 */
Andreas Gampe2e8c7672018-07-20 13:01:08 -07002168 @GuardedBy({"mRestrictionsLock", "mPackagesLock"})
Pavel Grafov6a40f092016-10-25 15:46:51 +01002169 private void upgradeIfNecessaryLP(Bundle oldGlobalUserRestrictions) {
Bookatz75f0a072019-08-05 14:12:16 -07002170 Set<Integer> userIdsToWrite = new ArraySet<>();
Makoto Onuki1a2cd742015-11-16 13:51:27 -08002171 final int originalVersion = mUserVersion;
Amith Yamasani6f34b412012-10-22 18:19:27 -07002172 int userVersion = mUserVersion;
2173 if (userVersion < 1) {
2174 // Assign a proper name for the owner, if not initialized correctly before
Amith Yamasani12747872015-12-07 14:19:49 -08002175 UserData userData = getUserDataNoChecks(UserHandle.USER_SYSTEM);
2176 if ("Primary".equals(userData.info.name)) {
2177 userData.info.name =
2178 mContext.getResources().getString(com.android.internal.R.string.owner_name);
Bookatz75f0a072019-08-05 14:12:16 -07002179 userIdsToWrite.add(userData.info.id);
Amith Yamasani6f34b412012-10-22 18:19:27 -07002180 }
2181 userVersion = 1;
2182 }
2183
Amith Yamasanibc9625052012-11-15 14:39:18 -08002184 if (userVersion < 2) {
2185 // Owner should be marked as initialized
Amith Yamasani12747872015-12-07 14:19:49 -08002186 UserData userData = getUserDataNoChecks(UserHandle.USER_SYSTEM);
2187 if ((userData.info.flags & UserInfo.FLAG_INITIALIZED) == 0) {
2188 userData.info.flags |= UserInfo.FLAG_INITIALIZED;
Bookatz75f0a072019-08-05 14:12:16 -07002189 userIdsToWrite.add(userData.info.id);
Amith Yamasanibc9625052012-11-15 14:39:18 -08002190 }
2191 userVersion = 2;
2192 }
2193
Amith Yamasani350962c2013-08-06 11:18:53 -07002194
Amith Yamasani5e486f52013-08-07 11:06:44 -07002195 if (userVersion < 4) {
Amith Yamasani5e486f52013-08-07 11:06:44 -07002196 userVersion = 4;
2197 }
2198
Amith Yamasaniaa6634e2014-10-06 14:20:28 -07002199 if (userVersion < 5) {
2200 initDefaultGuestRestrictions();
2201 userVersion = 5;
2202 }
2203
Fyodor Kupolov1c363152015-09-02 13:27:21 -07002204 if (userVersion < 6) {
2205 final boolean splitSystemUser = UserManager.isSplitSystemUser();
Fyodor Kupolov82402752015-10-28 14:54:51 -07002206 synchronized (mUsersLock) {
2207 for (int i = 0; i < mUsers.size(); i++) {
Amith Yamasani12747872015-12-07 14:19:49 -08002208 UserData userData = mUsers.valueAt(i);
Fyodor Kupolov82402752015-10-28 14:54:51 -07002209 // In non-split mode, only user 0 can have restricted profiles
Amith Yamasani12747872015-12-07 14:19:49 -08002210 if (!splitSystemUser && userData.info.isRestricted()
2211 && (userData.info.restrictedProfileParentId
2212 == UserInfo.NO_PROFILE_GROUP_ID)) {
2213 userData.info.restrictedProfileParentId = UserHandle.USER_SYSTEM;
Bookatz75f0a072019-08-05 14:12:16 -07002214 userIdsToWrite.add(userData.info.id);
Fyodor Kupolov82402752015-10-28 14:54:51 -07002215 }
Fyodor Kupolov1c363152015-09-02 13:27:21 -07002216 }
2217 }
2218 userVersion = 6;
2219 }
2220
Pavel Grafov6a40f092016-10-25 15:46:51 +01002221 if (userVersion < 7) {
2222 // Previously only one user could enforce global restrictions, now it is per-user.
2223 synchronized (mRestrictionsLock) {
2224 if (!UserRestrictionsUtils.isEmpty(oldGlobalUserRestrictions)
2225 && mDeviceOwnerUserId != UserHandle.USER_NULL) {
2226 mDevicePolicyGlobalUserRestrictions.put(
2227 mDeviceOwnerUserId, oldGlobalUserRestrictions);
2228 }
2229 // ENSURE_VERIFY_APPS is now enforced globally even if put by profile owner, so move
2230 // it from local to global bundle for all users who set it.
2231 UserRestrictionsUtils.moveRestriction(UserManager.ENSURE_VERIFY_APPS,
2232 mDevicePolicyLocalUserRestrictions, mDevicePolicyGlobalUserRestrictions
2233 );
2234 }
2235 userVersion = 7;
2236 }
2237
Bookatz75f0a072019-08-05 14:12:16 -07002238 if (userVersion < 8) {
2239 // Added FLAG_FULL and FLAG_SYSTEM flags.
2240 synchronized (mUsersLock) {
2241 UserData userData = mUsers.get(UserHandle.USER_SYSTEM);
2242 userData.info.flags |= UserInfo.FLAG_SYSTEM;
2243 if (!UserManager.isHeadlessSystemUserMode()) {
2244 userData.info.flags |= UserInfo.FLAG_FULL;
2245 }
2246 userIdsToWrite.add(userData.info.id);
2247
2248 // Mark FULL all non-profile users except USER_SYSTEM.
2249 // Start index at 1 since USER_SYSTEM is the smallest userId and we're skipping it.
2250 for (int i = 1; i < mUsers.size(); i++) {
2251 userData = mUsers.valueAt(i);
2252 if ((userData.info.flags & UserInfo.FLAG_MANAGED_PROFILE) == 0) {
2253 userData.info.flags |= UserInfo.FLAG_FULL;
2254 userIdsToWrite.add(userData.info.id);
2255 }
2256 }
2257 }
2258 userVersion = 8;
2259 }
2260
Amith Yamasani6f34b412012-10-22 18:19:27 -07002261 if (userVersion < USER_VERSION) {
2262 Slog.w(LOG_TAG, "User version " + mUserVersion + " didn't upgrade as expected to "
2263 + USER_VERSION);
2264 } else {
2265 mUserVersion = userVersion;
Makoto Onuki1a2cd742015-11-16 13:51:27 -08002266
2267 if (originalVersion < mUserVersion) {
Bookatz75f0a072019-08-05 14:12:16 -07002268 for (int userId : userIdsToWrite) {
2269 UserData userData = getUserDataNoChecks(userId);
2270 if (userData != null) {
2271 writeUserLP(userData);
2272 }
2273 }
Makoto Onuki1a2cd742015-11-16 13:51:27 -08002274 writeUserListLP();
2275 }
Amith Yamasani6f34b412012-10-22 18:19:27 -07002276 }
2277 }
2278
Andreas Gampe2e8c7672018-07-20 13:01:08 -07002279 @GuardedBy({"mPackagesLock", "mRestrictionsLock"})
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002280 private void fallbackToSingleUserLP() {
Ying Zheng215116f2019-09-11 12:50:09 -07002281 int flags = UserInfo.FLAG_SYSTEM | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_ADMIN
2282 | UserInfo.FLAG_PRIMARY;
2283 // In headless system user mode, headless system user is not a full user.
Bookatz75f0a072019-08-05 14:12:16 -07002284 if (!UserManager.isHeadlessSystemUserMode()) {
Ying Zheng215116f2019-09-11 12:50:09 -07002285 flags |= UserInfo.FLAG_FULL;
Bookatz75f0a072019-08-05 14:12:16 -07002286 }
Xiaohui Chen70f6c382015-04-28 14:21:43 -07002287 // Create the system user
Amith Yamasani6f48d6e2016-03-23 14:28:25 -07002288 UserInfo system = new UserInfo(UserHandle.USER_SYSTEM, null, null, flags);
Fyodor Kupolov0f4533d2016-05-18 18:43:12 -07002289 UserData userData = putUserInfo(system);
Amith Yamasani634cf312012-10-04 17:34:21 -07002290 mNextSerialNumber = MIN_USER_ID;
Geoffrey Borggaard15b8b2c2013-08-28 22:11:10 -04002291 mUserVersion = USER_VERSION;
Amith Yamasani67df64b2012-12-14 12:09:36 -08002292
Geoffrey Borggaarde45e45e32013-01-24 10:03:20 -05002293 Bundle restrictions = new Bundle();
Mahaver Chopra3d9805d2016-07-07 16:25:05 +01002294 try {
2295 final String[] defaultFirstUserRestrictions = mContext.getResources().getStringArray(
2296 com.android.internal.R.array.config_defaultFirstUserRestrictions);
2297 for (String userRestriction : defaultFirstUserRestrictions) {
2298 if (UserRestrictionsUtils.isValidRestriction(userRestriction)) {
2299 restrictions.putBoolean(userRestriction, true);
2300 }
2301 }
2302 } catch (Resources.NotFoundException e) {
2303 Log.e(LOG_TAG, "Couldn't find resource: config_defaultFirstUserRestrictions", e);
2304 }
2305
Pavel Grafov6a40f092016-10-25 15:46:51 +01002306 if (!restrictions.isEmpty()) {
2307 synchronized (mRestrictionsLock) {
2308 mBaseUserRestrictions.append(UserHandle.USER_SYSTEM, restrictions);
2309 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07002310 }
Amith Yamasani67df64b2012-12-14 12:09:36 -08002311
Fyodor Kupolov82402752015-10-28 14:54:51 -07002312 updateUserIds();
Amith Yamasaniaa6634e2014-10-06 14:20:28 -07002313 initDefaultGuestRestrictions();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002314
Amith Yamasani12747872015-12-07 14:19:49 -08002315 writeUserLP(userData);
Jeff Sharkeycd575992016-03-29 14:12:49 -06002316 writeUserListLP();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002317 }
2318
Amith Yamasani6f48d6e2016-03-23 14:28:25 -07002319 private String getOwnerName() {
2320 return mContext.getResources().getString(com.android.internal.R.string.owner_name);
2321 }
2322
Bookatz75f0a072019-08-05 14:12:16 -07002323 private void scheduleWriteUser(UserData userData) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08002324 if (DBG) {
2325 debug("scheduleWriteUser");
2326 }
Makoto Onuki9e935a32015-11-06 14:24:24 -08002327 // No need to wrap it within a lock -- worst case, we'll just post the same message
2328 // twice.
Bookatz75f0a072019-08-05 14:12:16 -07002329 if (!mHandler.hasMessages(WRITE_USER_MSG, userData)) {
2330 Message msg = mHandler.obtainMessage(WRITE_USER_MSG, userData);
Fyodor Kupolov75d0ea82014-12-15 16:21:07 -08002331 mHandler.sendMessageDelayed(msg, WRITE_USER_DELAY);
2332 }
2333 }
2334
Amith Yamasani12747872015-12-07 14:19:49 -08002335 private void writeUserLP(UserData userData) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08002336 if (DBG) {
Amith Yamasani12747872015-12-07 14:19:49 -08002337 debug("writeUserLP " + userData);
Makoto Onuki1a2cd742015-11-16 13:51:27 -08002338 }
Amith Yamasani742a6712011-05-04 14:49:28 -07002339 FileOutputStream fos = null;
Amith Yamasani12747872015-12-07 14:19:49 -08002340 AtomicFile userFile = new AtomicFile(new File(mUsersDir, userData.info.id + XML_SUFFIX));
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002341 try {
Amith Yamasani2a003292012-08-14 18:25:45 -07002342 fos = userFile.startWrite();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002343 final BufferedOutputStream bos = new BufferedOutputStream(fos);
Kenny Guy02c89902016-11-15 19:36:38 +00002344 writeUserLP(userData, bos);
Amith Yamasani2a003292012-08-14 18:25:45 -07002345 userFile.finishWrite(fos);
2346 } catch (Exception ioe) {
Jeff Sharkeycd575992016-03-29 14:12:49 -06002347 Slog.e(LOG_TAG, "Error writing user info " + userData.info.id, ioe);
Amith Yamasani2a003292012-08-14 18:25:45 -07002348 userFile.failWrite(fos);
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002349 }
2350 }
2351
2352 /*
Kenny Guy02c89902016-11-15 19:36:38 +00002353 * Writes the user file in this format:
2354 *
2355 * <user flags="20039023" id="0">
2356 * <name>Primary</name>
2357 * </user>
2358 */
2359 @VisibleForTesting
2360 void writeUserLP(UserData userData, OutputStream os)
2361 throws IOException, XmlPullParserException {
2362 // XmlSerializer serializer = XmlUtils.serializerInstance();
2363 final XmlSerializer serializer = new FastXmlSerializer();
2364 serializer.setOutput(os, StandardCharsets.UTF_8.name());
2365 serializer.startDocument(null, true);
2366 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
2367
2368 final UserInfo userInfo = userData.info;
2369 serializer.startTag(null, TAG_USER);
2370 serializer.attribute(null, ATTR_ID, Integer.toString(userInfo.id));
2371 serializer.attribute(null, ATTR_SERIAL_NO, Integer.toString(userInfo.serialNumber));
2372 serializer.attribute(null, ATTR_FLAGS, Integer.toString(userInfo.flags));
2373 serializer.attribute(null, ATTR_CREATION_TIME, Long.toString(userInfo.creationTime));
2374 serializer.attribute(null, ATTR_LAST_LOGGED_IN_TIME,
2375 Long.toString(userInfo.lastLoggedInTime));
2376 if (userInfo.lastLoggedInFingerprint != null) {
2377 serializer.attribute(null, ATTR_LAST_LOGGED_IN_FINGERPRINT,
2378 userInfo.lastLoggedInFingerprint);
2379 }
2380 if (userInfo.iconPath != null) {
2381 serializer.attribute(null, ATTR_ICON_PATH, userInfo.iconPath);
2382 }
2383 if (userInfo.partial) {
2384 serializer.attribute(null, ATTR_PARTIAL, "true");
2385 }
Felipe Lemec1ca4412019-09-11 09:23:26 -07002386 if (userInfo.preCreated) {
2387 serializer.attribute(null, ATTR_PRE_CREATED, "true");
2388 }
Kenny Guy02c89902016-11-15 19:36:38 +00002389 if (userInfo.guestToRemove) {
2390 serializer.attribute(null, ATTR_GUEST_TO_REMOVE, "true");
2391 }
2392 if (userInfo.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID) {
2393 serializer.attribute(null, ATTR_PROFILE_GROUP_ID,
2394 Integer.toString(userInfo.profileGroupId));
2395 }
2396 serializer.attribute(null, ATTR_PROFILE_BADGE,
2397 Integer.toString(userInfo.profileBadge));
2398 if (userInfo.restrictedProfileParentId != UserInfo.NO_PROFILE_GROUP_ID) {
2399 serializer.attribute(null, ATTR_RESTRICTED_PROFILE_PARENT_ID,
2400 Integer.toString(userInfo.restrictedProfileParentId));
2401 }
2402 // Write seed data
2403 if (userData.persistSeedData) {
2404 if (userData.seedAccountName != null) {
2405 serializer.attribute(null, ATTR_SEED_ACCOUNT_NAME, userData.seedAccountName);
2406 }
2407 if (userData.seedAccountType != null) {
2408 serializer.attribute(null, ATTR_SEED_ACCOUNT_TYPE, userData.seedAccountType);
2409 }
2410 }
2411 if (userInfo.name != null) {
2412 serializer.startTag(null, TAG_NAME);
2413 serializer.text(userInfo.name);
2414 serializer.endTag(null, TAG_NAME);
2415 }
2416 synchronized (mRestrictionsLock) {
2417 UserRestrictionsUtils.writeRestrictions(serializer,
2418 mBaseUserRestrictions.get(userInfo.id), TAG_RESTRICTIONS);
2419 UserRestrictionsUtils.writeRestrictions(serializer,
2420 mDevicePolicyLocalUserRestrictions.get(userInfo.id),
2421 TAG_DEVICE_POLICY_RESTRICTIONS);
Pavel Grafov6a40f092016-10-25 15:46:51 +01002422 UserRestrictionsUtils.writeRestrictions(serializer,
2423 mDevicePolicyGlobalUserRestrictions.get(userInfo.id),
2424 TAG_DEVICE_POLICY_GLOBAL_RESTRICTIONS);
Kenny Guy02c89902016-11-15 19:36:38 +00002425 }
2426
2427 if (userData.account != null) {
2428 serializer.startTag(null, TAG_ACCOUNT);
2429 serializer.text(userData.account);
2430 serializer.endTag(null, TAG_ACCOUNT);
2431 }
2432
2433 if (userData.persistSeedData && userData.seedAccountOptions != null) {
2434 serializer.startTag(null, TAG_SEED_ACCOUNT_OPTIONS);
2435 userData.seedAccountOptions.saveToXml(serializer);
2436 serializer.endTag(null, TAG_SEED_ACCOUNT_OPTIONS);
2437 }
2438
arangelov9b632d72018-12-07 23:21:22 +00002439 if (userData.getLastRequestQuietModeEnabledMillis() != 0L) {
2440 serializer.startTag(/* namespace */ null, TAG_LAST_REQUEST_QUIET_MODE_ENABLED_CALL);
2441 serializer.text(String.valueOf(userData.getLastRequestQuietModeEnabledMillis()));
2442 serializer.endTag(/* namespace */ null, TAG_LAST_REQUEST_QUIET_MODE_ENABLED_CALL);
2443 }
2444
Kenny Guy02c89902016-11-15 19:36:38 +00002445 serializer.endTag(null, TAG_USER);
2446
2447 serializer.endDocument();
2448 }
2449
2450 /*
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002451 * Writes the user list file in this format:
2452 *
Amith Yamasani2a003292012-08-14 18:25:45 -07002453 * <users nextSerialNumber="3">
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002454 * <user id="0"></user>
2455 * <user id="2"></user>
2456 * </users>
2457 */
Andreas Gampe2e8c7672018-07-20 13:01:08 -07002458 @GuardedBy({"mRestrictionsLock", "mPackagesLock"})
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002459 private void writeUserListLP() {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08002460 if (DBG) {
2461 debug("writeUserList");
2462 }
Amith Yamasani742a6712011-05-04 14:49:28 -07002463 FileOutputStream fos = null;
Amith Yamasani2a003292012-08-14 18:25:45 -07002464 AtomicFile userListFile = new AtomicFile(mUserListFile);
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002465 try {
Amith Yamasani2a003292012-08-14 18:25:45 -07002466 fos = userListFile.startWrite();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002467 final BufferedOutputStream bos = new BufferedOutputStream(fos);
2468
2469 // XmlSerializer serializer = XmlUtils.serializerInstance();
2470 final XmlSerializer serializer = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01002471 serializer.setOutput(bos, StandardCharsets.UTF_8.name());
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002472 serializer.startDocument(null, true);
2473 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
2474
2475 serializer.startTag(null, TAG_USERS);
Amith Yamasani2a003292012-08-14 18:25:45 -07002476 serializer.attribute(null, ATTR_NEXT_SERIAL_NO, Integer.toString(mNextSerialNumber));
Amith Yamasani6f34b412012-10-22 18:19:27 -07002477 serializer.attribute(null, ATTR_USER_VERSION, Integer.toString(mUserVersion));
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002478
Adam Lesinskieddeb492014-09-08 17:50:03 -07002479 serializer.startTag(null, TAG_GUEST_RESTRICTIONS);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002480 synchronized (mGuestRestrictions) {
2481 UserRestrictionsUtils
2482 .writeRestrictions(serializer, mGuestRestrictions, TAG_RESTRICTIONS);
2483 }
Amith Yamasanie4afaa32014-06-30 14:55:07 +05302484 serializer.endTag(null, TAG_GUEST_RESTRICTIONS);
Pavel Grafov6a40f092016-10-25 15:46:51 +01002485 serializer.startTag(null, TAG_DEVICE_OWNER_USER_ID);
2486 serializer.attribute(null, ATTR_ID, Integer.toString(mDeviceOwnerUserId));
2487 serializer.endTag(null, TAG_DEVICE_OWNER_USER_ID);
Fyodor Kupolov82402752015-10-28 14:54:51 -07002488 int[] userIdsToWrite;
2489 synchronized (mUsersLock) {
2490 userIdsToWrite = new int[mUsers.size()];
2491 for (int i = 0; i < userIdsToWrite.length; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -08002492 UserInfo user = mUsers.valueAt(i).info;
Fyodor Kupolov82402752015-10-28 14:54:51 -07002493 userIdsToWrite[i] = user.id;
2494 }
2495 }
2496 for (int id : userIdsToWrite) {
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002497 serializer.startTag(null, TAG_USER);
Fyodor Kupolov82402752015-10-28 14:54:51 -07002498 serializer.attribute(null, ATTR_ID, Integer.toString(id));
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002499 serializer.endTag(null, TAG_USER);
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002500 }
2501
2502 serializer.endTag(null, TAG_USERS);
2503
2504 serializer.endDocument();
Amith Yamasani2a003292012-08-14 18:25:45 -07002505 userListFile.finishWrite(fos);
2506 } catch (Exception e) {
2507 userListFile.failWrite(fos);
Amith Yamasani0b285492011-04-14 17:35:23 -07002508 Slog.e(LOG_TAG, "Error writing user list");
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002509 }
2510 }
2511
Amith Yamasani12747872015-12-07 14:19:49 -08002512 private UserData readUserLP(int id) {
Kenny Guy02c89902016-11-15 19:36:38 +00002513 FileInputStream fis = null;
2514 try {
2515 AtomicFile userFile =
2516 new AtomicFile(new File(mUsersDir, Integer.toString(id) + XML_SUFFIX));
2517 fis = userFile.openRead();
2518 return readUserLP(id, fis);
2519 } catch (IOException ioe) {
2520 Slog.e(LOG_TAG, "Error reading user list");
2521 } catch (XmlPullParserException pe) {
2522 Slog.e(LOG_TAG, "Error reading user list");
2523 } finally {
2524 IoUtils.closeQuietly(fis);
2525 }
2526 return null;
2527 }
2528
2529 @VisibleForTesting
2530 UserData readUserLP(int id, InputStream is) throws IOException,
2531 XmlPullParserException {
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002532 int flags = 0;
Amith Yamasani2a003292012-08-14 18:25:45 -07002533 int serialNumber = id;
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002534 String name = null;
Xiaohui Chenb3b92582015-12-07 11:22:13 -08002535 String account = null;
Amith Yamasanib8151ec2012-04-18 18:02:48 -07002536 String iconPath = null;
Amith Yamasani920ace02012-09-20 22:15:37 -07002537 long creationTime = 0L;
2538 long lastLoggedInTime = 0L;
arangelov9b632d72018-12-07 23:21:22 +00002539 long lastRequestQuietModeEnabledTimestamp = 0L;
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06002540 String lastLoggedInFingerprint = null;
Kenny Guy2a764942014-04-02 13:29:20 +01002541 int profileGroupId = UserInfo.NO_PROFILE_GROUP_ID;
Kenny Guy02c89902016-11-15 19:36:38 +00002542 int profileBadge = 0;
Fyodor Kupolov06a484a2015-08-21 16:33:20 -07002543 int restrictedProfileParentId = UserInfo.NO_PROFILE_GROUP_ID;
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07002544 boolean partial = false;
Felipe Lemec1ca4412019-09-11 09:23:26 -07002545 boolean preCreated = false;
Adam Lesinskieddeb492014-09-08 17:50:03 -07002546 boolean guestToRemove = false;
Amith Yamasani12747872015-12-07 14:19:49 -08002547 boolean persistSeedData = false;
2548 String seedAccountName = null;
2549 String seedAccountType = null;
2550 PersistableBundle seedAccountOptions = null;
Pavel Grafov6a40f092016-10-25 15:46:51 +01002551 Bundle baseRestrictions = null;
2552 Bundle localRestrictions = null;
2553 Bundle globalRestrictions = null;
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002554
Kenny Guy02c89902016-11-15 19:36:38 +00002555 XmlPullParser parser = Xml.newPullParser();
2556 parser.setInput(is, StandardCharsets.UTF_8.name());
2557 int type;
2558 while ((type = parser.next()) != XmlPullParser.START_TAG
2559 && type != XmlPullParser.END_DOCUMENT) {
2560 // Skip
2561 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002562
Kenny Guy02c89902016-11-15 19:36:38 +00002563 if (type != XmlPullParser.START_TAG) {
2564 Slog.e(LOG_TAG, "Unable to read user " + id);
2565 return null;
2566 }
2567
2568 if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_USER)) {
2569 int storedId = readIntAttribute(parser, ATTR_ID, -1);
2570 if (storedId != id) {
2571 Slog.e(LOG_TAG, "User id does not match the file name");
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002572 return null;
2573 }
Kenny Guy02c89902016-11-15 19:36:38 +00002574 serialNumber = readIntAttribute(parser, ATTR_SERIAL_NO, id);
2575 flags = readIntAttribute(parser, ATTR_FLAGS, 0);
2576 iconPath = parser.getAttributeValue(null, ATTR_ICON_PATH);
2577 creationTime = readLongAttribute(parser, ATTR_CREATION_TIME, 0);
2578 lastLoggedInTime = readLongAttribute(parser, ATTR_LAST_LOGGED_IN_TIME, 0);
2579 lastLoggedInFingerprint = parser.getAttributeValue(null,
2580 ATTR_LAST_LOGGED_IN_FINGERPRINT);
2581 profileGroupId = readIntAttribute(parser, ATTR_PROFILE_GROUP_ID,
2582 UserInfo.NO_PROFILE_GROUP_ID);
2583 profileBadge = readIntAttribute(parser, ATTR_PROFILE_BADGE, 0);
2584 restrictedProfileParentId = readIntAttribute(parser,
2585 ATTR_RESTRICTED_PROFILE_PARENT_ID, UserInfo.NO_PROFILE_GROUP_ID);
2586 String valueString = parser.getAttributeValue(null, ATTR_PARTIAL);
2587 if ("true".equals(valueString)) {
2588 partial = true;
2589 }
Felipe Lemec1ca4412019-09-11 09:23:26 -07002590 valueString = parser.getAttributeValue(null, ATTR_PRE_CREATED);
2591 if ("true".equals(valueString)) {
2592 preCreated = true;
2593 }
Kenny Guy02c89902016-11-15 19:36:38 +00002594 valueString = parser.getAttributeValue(null, ATTR_GUEST_TO_REMOVE);
2595 if ("true".equals(valueString)) {
2596 guestToRemove = true;
2597 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002598
Kenny Guy02c89902016-11-15 19:36:38 +00002599 seedAccountName = parser.getAttributeValue(null, ATTR_SEED_ACCOUNT_NAME);
2600 seedAccountType = parser.getAttributeValue(null, ATTR_SEED_ACCOUNT_TYPE);
2601 if (seedAccountName != null || seedAccountType != null) {
2602 persistSeedData = true;
2603 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002604
Kenny Guy02c89902016-11-15 19:36:38 +00002605 int outerDepth = parser.getDepth();
2606 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2607 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2608 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2609 continue;
2610 }
2611 String tag = parser.getName();
2612 if (TAG_NAME.equals(tag)) {
2613 type = parser.next();
2614 if (type == XmlPullParser.TEXT) {
2615 name = parser.getText();
2616 }
2617 } else if (TAG_RESTRICTIONS.equals(tag)) {
Pavel Grafov6a40f092016-10-25 15:46:51 +01002618 baseRestrictions = UserRestrictionsUtils.readRestrictions(parser);
Kenny Guy02c89902016-11-15 19:36:38 +00002619 } else if (TAG_DEVICE_POLICY_RESTRICTIONS.equals(tag)) {
Pavel Grafov6a40f092016-10-25 15:46:51 +01002620 localRestrictions = UserRestrictionsUtils.readRestrictions(parser);
2621 } else if (TAG_DEVICE_POLICY_GLOBAL_RESTRICTIONS.equals(tag)) {
2622 globalRestrictions = UserRestrictionsUtils.readRestrictions(parser);
Kenny Guy02c89902016-11-15 19:36:38 +00002623 } else if (TAG_ACCOUNT.equals(tag)) {
2624 type = parser.next();
2625 if (type == XmlPullParser.TEXT) {
2626 account = parser.getText();
2627 }
2628 } else if (TAG_SEED_ACCOUNT_OPTIONS.equals(tag)) {
2629 seedAccountOptions = PersistableBundle.restoreFromXml(parser);
Amith Yamasani12747872015-12-07 14:19:49 -08002630 persistSeedData = true;
arangelov9b632d72018-12-07 23:21:22 +00002631 } else if (TAG_LAST_REQUEST_QUIET_MODE_ENABLED_CALL.equals(tag)) {
2632 type = parser.next();
2633 if (type == XmlPullParser.TEXT) {
2634 lastRequestQuietModeEnabledTimestamp = Long.parseLong(parser.getText());
2635 }
Amith Yamasani12747872015-12-07 14:19:49 -08002636 }
Dianne Hackbornbfd89b32011-12-15 18:22:54 -08002637 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002638 }
Kenny Guy02c89902016-11-15 19:36:38 +00002639
2640 // Create the UserInfo object that gets passed around
2641 UserInfo userInfo = new UserInfo(id, name, iconPath, flags);
2642 userInfo.serialNumber = serialNumber;
2643 userInfo.creationTime = creationTime;
2644 userInfo.lastLoggedInTime = lastLoggedInTime;
2645 userInfo.lastLoggedInFingerprint = lastLoggedInFingerprint;
2646 userInfo.partial = partial;
Felipe Lemec1ca4412019-09-11 09:23:26 -07002647 userInfo.preCreated = preCreated;
Kenny Guy02c89902016-11-15 19:36:38 +00002648 userInfo.guestToRemove = guestToRemove;
2649 userInfo.profileGroupId = profileGroupId;
2650 userInfo.profileBadge = profileBadge;
2651 userInfo.restrictedProfileParentId = restrictedProfileParentId;
2652
2653 // Create the UserData object that's internal to this class
2654 UserData userData = new UserData();
2655 userData.info = userInfo;
2656 userData.account = account;
2657 userData.seedAccountName = seedAccountName;
2658 userData.seedAccountType = seedAccountType;
2659 userData.persistSeedData = persistSeedData;
2660 userData.seedAccountOptions = seedAccountOptions;
arangelov9b632d72018-12-07 23:21:22 +00002661 userData.setLastRequestQuietModeEnabledMillis(lastRequestQuietModeEnabledTimestamp);
Kenny Guy02c89902016-11-15 19:36:38 +00002662
2663 synchronized (mRestrictionsLock) {
Pavel Grafov6a40f092016-10-25 15:46:51 +01002664 if (baseRestrictions != null) {
2665 mBaseUserRestrictions.put(id, baseRestrictions);
2666 }
2667 if (localRestrictions != null) {
2668 mDevicePolicyLocalUserRestrictions.put(id, localRestrictions);
2669 }
2670 if (globalRestrictions != null) {
2671 mDevicePolicyGlobalUserRestrictions.put(id, globalRestrictions);
2672 }
Kenny Guy02c89902016-11-15 19:36:38 +00002673 }
2674 return userData;
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002675 }
2676
Amith Yamasani920ace02012-09-20 22:15:37 -07002677 private int readIntAttribute(XmlPullParser parser, String attr, int defaultValue) {
2678 String valueString = parser.getAttributeValue(null, attr);
2679 if (valueString == null) return defaultValue;
2680 try {
2681 return Integer.parseInt(valueString);
2682 } catch (NumberFormatException nfe) {
2683 return defaultValue;
2684 }
2685 }
2686
2687 private long readLongAttribute(XmlPullParser parser, String attr, long defaultValue) {
2688 String valueString = parser.getAttributeValue(null, attr);
2689 if (valueString == null) return defaultValue;
2690 try {
2691 return Long.parseLong(valueString);
2692 } catch (NumberFormatException nfe) {
2693 return defaultValue;
2694 }
2695 }
2696
Amith Yamasanib82add22013-07-09 11:24:44 -07002697 /**
Amith Yamasani1a7472e2013-07-02 11:17:30 -07002698 * Removes the app restrictions file for a specific package and user id, if it exists.
2699 */
Bookatzf56f2582019-09-04 16:06:41 -07002700 private static void cleanAppRestrictionsForPackageLAr(String pkg, @UserIdInt int userId) {
Fyodor Kupolovd31cee92017-09-05 16:31:08 -07002701 File dir = Environment.getUserSystemDirectory(userId);
2702 File resFile = new File(dir, packageToRestrictionsFileName(pkg));
2703 if (resFile.exists()) {
2704 resFile.delete();
Amith Yamasani1a7472e2013-07-02 11:17:30 -07002705 }
2706 }
2707
Kenny Guya52dc3e2014-02-11 15:33:14 +00002708 @Override
Bookatzf56f2582019-09-04 16:06:41 -07002709 public UserInfo createProfileForUser(String name, int flags, @UserIdInt int userId,
Sudheer Shanka7cb54a32016-09-16 12:59:05 -07002710 String[] disallowedPackages) {
Sudheer Shankaf5cea032016-06-08 17:13:24 -07002711 checkManageOrCreateUsersPermission(flags);
Sudheer Shanka7cb54a32016-09-16 12:59:05 -07002712 return createUserInternal(name, flags, userId, disallowedPackages);
Kenny Guya52dc3e2014-02-11 15:33:14 +00002713 }
2714
Amith Yamasani258848d2012-08-10 17:06:33 -07002715 @Override
Bookatzf56f2582019-09-04 16:06:41 -07002716 public UserInfo createProfileForUserEvenWhenDisallowed(String name, int flags,
2717 @UserIdInt int userId, String[] disallowedPackages) {
Tony Mak6dc428f2016-10-10 15:48:27 +01002718 checkManageOrCreateUsersPermission(flags);
Felipe Lemec1ca4412019-09-11 09:23:26 -07002719 return createUserInternalUnchecked(name, flags, userId, /* preCreate= */ false,
2720 disallowedPackages);
Tony Mak6dc428f2016-10-10 15:48:27 +01002721 }
2722
2723 @Override
Bookatzf56f2582019-09-04 16:06:41 -07002724 public boolean removeUserEvenWhenDisallowed(@UserIdInt int userId) {
Nicolas Prevotd37c4a92017-01-23 11:56:00 +00002725 checkManageOrCreateUsersPermission("Only the system can remove users");
Bookatzf56f2582019-09-04 16:06:41 -07002726 return removeUserUnchecked(userId);
Nicolas Prevotd37c4a92017-01-23 11:56:00 +00002727 }
2728
2729 @Override
Amith Yamasani13593602012-03-22 16:16:17 -07002730 public UserInfo createUser(String name, int flags) {
Sudheer Shankaf5cea032016-06-08 17:13:24 -07002731 checkManageOrCreateUsersPermission(flags);
Nicolas Prevotc6d033e2014-02-27 13:11:09 +00002732 return createUserInternal(name, flags, UserHandle.USER_NULL);
Kenny Guya52dc3e2014-02-11 15:33:14 +00002733 }
Amith Yamasanifaea76f2012-09-11 10:59:48 -07002734
Felipe Lemec1ca4412019-09-11 09:23:26 -07002735 @Override
2736 public UserInfo preCreateUser(int flags) {
2737 checkManageOrCreateUsersPermission(flags);
2738
2739 Preconditions.checkArgument(!UserInfo.isManagedProfile(flags),
2740 "cannot pre-create managed profiles");
2741
2742 return createUserInternalUnchecked(/* name= */ null, flags,
2743 /* parentId= */ UserHandle.USER_NULL, /* preCreate= */ true,
2744 /* disallowedPackages= */ null);
2745 }
2746
2747 private UserInfo createUserInternal(@Nullable String name, @UserInfoFlag int flags,
2748 @UserIdInt int parentId) {
Sudheer Shanka7cb54a32016-09-16 12:59:05 -07002749 return createUserInternal(name, flags, parentId, null);
2750 }
2751
Felipe Lemec1ca4412019-09-11 09:23:26 -07002752 private UserInfo createUserInternal(@Nullable String name, @UserInfoFlag int flags,
2753 @UserIdInt int parentId, @Nullable String[] disallowedPackages) {
Esteban Talavera6c9116a2016-11-24 16:12:44 +00002754 String restriction = ((flags & UserInfo.FLAG_MANAGED_PROFILE) != 0)
2755 ? UserManager.DISALLOW_ADD_MANAGED_PROFILE
2756 : UserManager.DISALLOW_ADD_USER;
2757 if (hasUserRestriction(restriction, UserHandle.getCallingUserId())) {
2758 Log.w(LOG_TAG, "Cannot add user. " + restriction + " is enabled.");
Julia Reynolds75175022014-06-26 16:35:00 -04002759 return null;
2760 }
Felipe Lemec1ca4412019-09-11 09:23:26 -07002761 return createUserInternalUnchecked(name, flags, parentId, /* preCreate= */ false,
2762 disallowedPackages);
Tony Mak6dc428f2016-10-10 15:48:27 +01002763 }
2764
Felipe Lemec1ca4412019-09-11 09:23:26 -07002765 private UserInfo createUserInternalUnchecked(@Nullable String name, @UserInfoFlag int flags,
2766 @UserIdInt int parentId, boolean preCreate,
2767 @Nullable String[] disallowedPackages) {
2768 final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
2769 t.traceBegin("createUser-" + flags);
2770 try {
2771 return createUserInternalUncheckedNoTracing(name, flags, parentId, preCreate,
2772 disallowedPackages, t);
2773 } finally {
2774 t.traceEnd();
2775 }
jovanakdd7e4752019-09-04 12:35:45 -07002776 }
2777
Felipe Lemec1ca4412019-09-11 09:23:26 -07002778 private UserInfo createUserInternalUncheckedNoTracing(@Nullable String name,
2779 @UserInfoFlag int flags, @UserIdInt int parentId, boolean preCreate,
2780 @Nullable String[] disallowedPackages, @NonNull TimingsTraceAndSlog t) {
2781
2782 // First try to use a pre-created user (if available).
2783 // NOTE: currently we don't support pre-created managed profiles
2784 if (!preCreate && (parentId < 0 && !UserInfo.isManagedProfile(flags))) {
2785 final UserData preCreatedUserData;
2786 synchronized (mUsersLock) {
2787 preCreatedUserData = getPreCreatedUserLU(flags);
2788 }
2789 if (preCreatedUserData != null) {
2790 final UserInfo preCreatedUser = preCreatedUserData.info;
2791 Log.i(LOG_TAG, "Reusing pre-created user " + preCreatedUser.id + " for flags + "
2792 + UserInfo.flagsToString(flags));
2793 if (DBG) {
2794 Log.d(LOG_TAG, "pre-created user flags: "
2795 + UserInfo.flagsToString(preCreatedUser.flags)
2796 + " new-user flags: " + UserInfo.flagsToString(flags));
2797 }
2798 preCreatedUser.name = name;
2799 preCreatedUser.preCreated = false;
2800 preCreatedUser.creationTime = getCreationTime();
2801
2802 dispatchUserAddedIntent(preCreatedUser);
2803
2804 writeUserLP(preCreatedUserData);
2805 writeUserListLP();
2806
2807 return preCreatedUser;
2808 }
2809 }
2810
Suprabh Shuklac5e057c2016-08-08 16:22:44 -07002811 DeviceStorageMonitorInternal dsm = LocalServices
2812 .getService(DeviceStorageMonitorInternal.class);
2813 if (dsm.isMemoryLow()) {
2814 Log.w(LOG_TAG, "Cannot add user. Not enough space on disk.");
2815 return null;
2816 }
jovanakdd7e4752019-09-04 12:35:45 -07002817
Felipe Lemec1ca4412019-09-11 09:23:26 -07002818 final boolean isGuest = UserInfo.isGuest(flags);
2819 final boolean isManagedProfile = UserInfo.isManagedProfile(flags);
Fyodor Kupolov06a484a2015-08-21 16:33:20 -07002820 final boolean isRestricted = (flags & UserInfo.FLAG_RESTRICTED) != 0;
Amith Yamasani52c21e32016-05-31 09:12:20 -07002821 final boolean isDemo = (flags & UserInfo.FLAG_DEMO) != 0;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002822 final long ident = Binder.clearCallingIdentity();
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002823 UserInfo userInfo;
Amith Yamasani12747872015-12-07 14:19:49 -08002824 UserData userData;
Amith Yamasanibb054c92015-07-09 14:16:27 -07002825 final int userId;
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002826 try {
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002827 synchronized (mPackagesLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08002828 UserData parent = null;
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002829 if (parentId != UserHandle.USER_NULL) {
2830 synchronized (mUsersLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08002831 parent = getUserDataLU(parentId);
Nicolas Prevotc6d033e2014-02-27 13:11:09 +00002832 }
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002833 if (parent == null) return null;
2834 }
2835 if (isManagedProfile && !canAddMoreManagedProfiles(parentId, false)) {
2836 Log.e(LOG_TAG, "Cannot add more managed profiles for user " + parentId);
2837 return null;
2838 }
Amith Yamasani52c21e32016-05-31 09:12:20 -07002839 if (!isGuest && !isManagedProfile && !isDemo && isUserLimitReached()) {
Felipe Lemec1ca4412019-09-11 09:23:26 -07002840 // If we're not adding a guest/demo user or a managed profile,
2841 // and the limit has been reached, cannot add a user.
jovanaka6763a32018-12-03 17:23:20 -08002842 Log.e(LOG_TAG, "Cannot add user. Maximum user limit is reached.");
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002843 return null;
2844 }
2845 // If we're adding a guest and there already exists one, bail.
2846 if (isGuest && findCurrentGuestUser() != null) {
jovanaka6763a32018-12-03 17:23:20 -08002847 Log.e(LOG_TAG, "Cannot add guest user. Guest user already exists.");
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002848 return null;
2849 }
2850 // In legacy mode, restricted profile's parent can only be the owner user
2851 if (isRestricted && !UserManager.isSplitSystemUser()
2852 && (parentId != UserHandle.USER_SYSTEM)) {
2853 Log.w(LOG_TAG, "Cannot add restricted profile - parent user must be owner");
2854 return null;
2855 }
2856 if (isRestricted && UserManager.isSplitSystemUser()) {
2857 if (parent == null) {
2858 Log.w(LOG_TAG, "Cannot add restricted profile - parent user must be "
2859 + "specified");
Nicolas Prevot12678a92015-05-13 12:15:03 -07002860 return null;
2861 }
Amith Yamasani12747872015-12-07 14:19:49 -08002862 if (!parent.info.canHaveProfile()) {
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002863 Log.w(LOG_TAG, "Cannot add restricted profile - profiles cannot be "
2864 + "created for the specified parent user id " + parentId);
Amith Yamasani95ab7842014-08-11 17:09:26 -07002865 return null;
2866 }
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002867 }
Ying Zheng215116f2019-09-11 12:50:09 -07002868
Bookatz75f0a072019-08-05 14:12:16 -07002869 if (!isManagedProfile) {
2870 // New users cannot be system, and it's not a profile, so per-force it's FULL.
2871 flags |= UserInfo.FLAG_FULL;
2872 }
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01002873
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +01002874 userId = getNextAvailableId();
2875 Environment.getUserSystemDirectory(userId).mkdirs();
Felipe Lemec1ca4412019-09-11 09:23:26 -07002876 boolean ephemeralGuests = areGuestUsersEphemeral();
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +01002877
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002878 synchronized (mUsersLock) {
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +01002879 // Add ephemeral flag to guests/users if required. Also inherit it from parent.
2880 if ((isGuest && ephemeralGuests) || mForceEphemeralUsers
2881 || (parent != null && parent.info.isEphemeral())) {
2882 flags |= UserInfo.FLAG_EPHEMERAL;
2883 }
2884
2885 userInfo = new UserInfo(userId, name, null, flags);
2886 userInfo.serialNumber = mNextSerialNumber++;
Felipe Lemec1ca4412019-09-11 09:23:26 -07002887 userInfo.creationTime = getCreationTime();
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +01002888 userInfo.partial = true;
Felipe Lemec1ca4412019-09-11 09:23:26 -07002889 userInfo.preCreated = preCreate;
Fyodor Kupolov83c24242016-03-31 13:30:42 -07002890 userInfo.lastLoggedInFingerprint = Build.FINGERPRINT;
Kenny Guy02c89902016-11-15 19:36:38 +00002891 if (isManagedProfile && parentId != UserHandle.USER_NULL) {
2892 userInfo.profileBadge = getFreeProfileBadgeLU(parentId);
2893 }
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +01002894 userData = new UserData();
2895 userData.info = userInfo;
Amith Yamasani12747872015-12-07 14:19:49 -08002896 mUsers.put(userId, userData);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002897 }
Jeff Sharkeycd575992016-03-29 14:12:49 -06002898 writeUserLP(userData);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002899 writeUserListLP();
2900 if (parent != null) {
2901 if (isManagedProfile) {
Amith Yamasani12747872015-12-07 14:19:49 -08002902 if (parent.info.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
2903 parent.info.profileGroupId = parent.info.id;
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002904 writeUserLP(parent);
Kenny Guya52dc3e2014-02-11 15:33:14 +00002905 }
Amith Yamasani12747872015-12-07 14:19:49 -08002906 userInfo.profileGroupId = parent.info.profileGroupId;
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002907 } else if (isRestricted) {
Amith Yamasani12747872015-12-07 14:19:49 -08002908 if (parent.info.restrictedProfileParentId == UserInfo.NO_PROFILE_GROUP_ID) {
2909 parent.info.restrictedProfileParentId = parent.info.id;
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002910 writeUserLP(parent);
Jeff Sharkey6dce4962015-07-03 18:08:41 -07002911 }
Amith Yamasani12747872015-12-07 14:19:49 -08002912 userInfo.restrictedProfileParentId = parent.info.restrictedProfileParentId;
Makoto Onuki068c54a2015-10-13 14:34:03 -07002913 }
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002914 }
Dianne Hackborn4428e172012-08-24 17:43:05 -07002915 }
jovanakdd7e4752019-09-04 12:35:45 -07002916
2917 t.traceBegin("createUserKey");
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002918 final StorageManager storage = mContext.getSystemService(StorageManager.class);
Lenka Trochtovac4dd0212015-11-18 12:22:06 +01002919 storage.createUserKey(userId, userInfo.serialNumber, userInfo.isEphemeral());
jovanakdd7e4752019-09-04 12:35:45 -07002920 t.traceEnd();
2921
2922 t.traceBegin("prepareUserData");
Fyodor Kupolov5c0ecfd2017-01-27 11:11:57 -08002923 mUserDataPreparer.prepareUserData(userId, userInfo.serialNumber,
Jeff Sharkey47f71082016-02-01 17:03:54 -07002924 StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
jovanakdd7e4752019-09-04 12:35:45 -07002925 t.traceEnd();
2926
Bookatz04d7ae52019-08-05 14:07:12 -07002927 final Set<String> installablePackages =
2928 mSystemPackageInstaller.getInstallablePackagesForUserType(flags);
jovanakdd7e4752019-09-04 12:35:45 -07002929 t.traceBegin("PM.createNewUser");
Bookatz04d7ae52019-08-05 14:07:12 -07002930 mPm.createNewUser(userId, installablePackages, disallowedPackages);
jovanakdd7e4752019-09-04 12:35:45 -07002931 t.traceEnd();
2932
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002933 userInfo.partial = false;
2934 synchronized (mPackagesLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08002935 writeUserLP(userData);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002936 }
2937 updateUserIds();
2938 Bundle restrictions = new Bundle();
Fyodor Kupolove04462c2015-11-30 15:02:53 -08002939 if (isGuest) {
2940 synchronized (mGuestRestrictions) {
2941 restrictions.putAll(mGuestRestrictions);
2942 }
2943 }
Fyodor Kupolove80085d2015-11-06 18:21:39 -08002944 synchronized (mRestrictionsLock) {
2945 mBaseUserRestrictions.append(userId, restrictions);
2946 }
jovanakdd7e4752019-09-04 12:35:45 -07002947
2948 t.traceBegin("PM.onNewUserCreated");
Fyodor Kupolov5fd967d2016-07-12 14:46:19 -07002949 mPm.onNewUserCreated(userId);
jovanakdd7e4752019-09-04 12:35:45 -07002950
Felipe Lemec1ca4412019-09-11 09:23:26 -07002951 if (preCreate) {
2952 // Must start user (which will be stopped right away, through
2953 // UserController.finishUserUnlockedCompleted) so services can properly
2954 // intialize it.
2955 // TODO(b/140750212): in the long-term, we should add a onCreateUser() callback
2956 // on SystemService instead.
2957 Slog.i(LOG_TAG, "starting pre-created user " + userInfo.toFullString());
2958 final IActivityManager am = ActivityManager.getService();
2959 try {
2960 am.startUserInBackground(userId);
2961 } catch (RemoteException e) {
2962 Slog.w(LOG_TAG, "could not start pre-created user " + userId, e);
2963 }
2964 } else {
2965 dispatchUserAddedIntent(userInfo);
2966 }
2967
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07002968 } finally {
2969 Binder.restoreCallingIdentity(ident);
Amith Yamasani258848d2012-08-10 17:06:33 -07002970 }
Felipe Lemec1ca4412019-09-11 09:23:26 -07002971
2972 // TODO(b/140750212): it's possible to reach "max users overflow" when the user is created
2973 // "from scratch" (i.e., not from a pre-created user) and reaches the maximum number of
2974 // users without counting the pre-created one. Then when the pre-created is converted, the
2975 // "effective" number of max users is exceeds. Example:
2976 // Max: 3 Current: 2 full (u0 and u10) + 1 pre-created (u11)
2977 // Step 1: create(/* flags doesn't match u11 */): u12 is created, "effective max" is now 3
2978 // (u0, u10, u12) but "real" max is 4 (u0, u10, u11, u12)
2979 // Step 2: create(/* flags match u11 */): u11 is converted, now "effective max" is also 4
2980 // (u0, u10, u11, u12)
2981 // One way to avoid this issue is by removing a pre-created user from the pool when the
2982 // "real" max exceeds the max here.
2983
Amith Yamasani4b2e9342011-03-31 12:38:53 -07002984 return userInfo;
2985 }
2986
Bookatz04d7ae52019-08-05 14:07:12 -07002987 /** Install/uninstall system packages for all users based on their user-type, as applicable. */
2988 boolean installWhitelistedSystemPackages(boolean isFirstBoot, boolean isUpgrade) {
2989 return mSystemPackageInstaller.installWhitelistedSystemPackages(isFirstBoot, isUpgrade);
2990 }
2991
Felipe Lemec1ca4412019-09-11 09:23:26 -07002992 private long getCreationTime() {
2993 final long now = System.currentTimeMillis();
2994 return (now > EPOCH_PLUS_30_YEARS) ? now : 0;
2995 }
2996
2997 private void dispatchUserAddedIntent(@NonNull UserInfo userInfo) {
2998 Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
2999 addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userInfo.id);
3000 mContext.sendBroadcastAsUser(addedIntent, UserHandle.ALL,
3001 android.Manifest.permission.MANAGE_USERS);
3002 MetricsLogger.count(mContext, userInfo.isGuest() ? TRON_GUEST_CREATED
3003 : (userInfo.isDemo() ? TRON_DEMO_CREATED : TRON_USER_CREATED), 1);
3004 }
3005
3006 private boolean areGuestUsersEphemeral() {
3007 return Resources.getSystem()
3008 .getBoolean(com.android.internal.R.bool.config_guestUserEphemeral);
3009 }
3010
3011 /**
3012 * Gets a pre-created user for the given flag.
3013 *
3014 * <p>Should be used only during user creation, so the pre-created user can be used (instead of
3015 * creating and initializing a new user from scratch).
3016 */
3017 // TODO(b/140750212): add unit test
3018 @GuardedBy("mUsersLock")
3019 private @Nullable UserData getPreCreatedUserLU(@UserInfoFlag int flags) {
3020 if (DBG) {
3021 Slog.d(LOG_TAG, "getPreCreatedUser(): initialFlags= " + UserInfo.flagsToString(flags));
3022 }
3023 flags |= UserInfo.FLAG_FULL;
3024 if (UserInfo.isGuest(flags) && areGuestUsersEphemeral()) {
3025 flags |= UserInfo.FLAG_EPHEMERAL;
3026 }
3027 if (DBG) {
3028 Slog.d(LOG_TAG, "getPreCreatedUser(): targetFlags= " + UserInfo.flagsToString(flags));
3029 }
3030 final int userSize = mUsers.size();
3031 for (int i = 0; i < userSize; i++) {
3032 final UserData user = mUsers.valueAt(i);
3033 if (DBG) Slog.d(LOG_TAG, i + ":" + user.info.toFullString());
3034 if (user.info.preCreated
3035 && (user.info.flags & ~UserInfo.FLAG_INITIALIZED) == flags) {
3036 if (!user.info.isInitialized()) {
3037 Slog.w(LOG_TAG, "found pre-created user for flags "
3038 + "" + UserInfo.flagsToString(flags)
3039 + ", but it's not initialized yet: " + user.info.toFullString());
3040 continue;
3041 }
3042 return user;
3043 }
3044 }
3045 return null;
3046 }
3047
Fyodor Kupolov0f4533d2016-05-18 18:43:12 -07003048 @VisibleForTesting
3049 UserData putUserInfo(UserInfo userInfo) {
3050 final UserData userData = new UserData();
3051 userData.info = userInfo;
3052 synchronized (mUsers) {
3053 mUsers.put(userInfo.id, userData);
3054 }
3055 return userData;
3056 }
3057
3058 @VisibleForTesting
Bookatzf56f2582019-09-04 16:06:41 -07003059 void removeUserInfo(@UserIdInt int userId) {
Fyodor Kupolov0f4533d2016-05-18 18:43:12 -07003060 synchronized (mUsers) {
3061 mUsers.remove(userId);
3062 }
3063 }
3064
Amith Yamasani0b285492011-04-14 17:35:23 -07003065 /**
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -07003066 * @hide
3067 */
Amith Yamasani12747872015-12-07 14:19:49 -08003068 @Override
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -07003069 public UserInfo createRestrictedProfile(String name, int parentUserId) {
Sudheer Shanka53d41472016-06-16 09:11:08 -07003070 checkManageOrCreateUsersPermission("setupRestrictedProfile");
Sudheer Shanka7cb54a32016-09-16 12:59:05 -07003071 final UserInfo user = createProfileForUser(
3072 name, UserInfo.FLAG_RESTRICTED, parentUserId, null);
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -07003073 if (user == null) {
3074 return null;
3075 }
Fyodor Kupolov9e912ba2016-02-09 18:29:43 -08003076 long identity = Binder.clearCallingIdentity();
3077 try {
3078 setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user.id);
3079 // Change the setting before applying the DISALLOW_SHARE_LOCATION restriction, otherwise
3080 // the putIntForUser() will fail.
3081 android.provider.Settings.Secure.putIntForUser(mContext.getContentResolver(),
3082 android.provider.Settings.Secure.LOCATION_MODE,
3083 android.provider.Settings.Secure.LOCATION_MODE_OFF, user.id);
3084 setUserRestriction(UserManager.DISALLOW_SHARE_LOCATION, true, user.id);
3085 } finally {
3086 Binder.restoreCallingIdentity(identity);
3087 }
Fyodor Kupolov02cb6e72015-09-18 18:20:55 -07003088 return user;
3089 }
3090
3091 /**
Adam Lesinskieddeb492014-09-08 17:50:03 -07003092 * Find the current guest user. If the Guest user is partial,
3093 * then do not include it in the results as it is about to die.
Adam Lesinskieddeb492014-09-08 17:50:03 -07003094 */
Fyodor Kupolov82402752015-10-28 14:54:51 -07003095 private UserInfo findCurrentGuestUser() {
3096 synchronized (mUsersLock) {
3097 final int size = mUsers.size();
3098 for (int i = 0; i < size; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -08003099 final UserInfo user = mUsers.valueAt(i).info;
Fyodor Kupolov82402752015-10-28 14:54:51 -07003100 if (user.isGuest() && !user.guestToRemove && !mRemovingUserIds.get(user.id)) {
3101 return user;
3102 }
Adam Lesinskieddeb492014-09-08 17:50:03 -07003103 }
3104 }
3105 return null;
3106 }
3107
3108 /**
Amith Yamasani1df14732014-08-29 21:37:27 -07003109 * Mark this guest user for deletion to allow us to create another guest
3110 * and switch to that user before actually removing this guest.
Bookatzf56f2582019-09-04 16:06:41 -07003111 * @param userId the userid of the current guest
Amith Yamasani1df14732014-08-29 21:37:27 -07003112 * @return whether the user could be marked for deletion
3113 */
Amith Yamasani12747872015-12-07 14:19:49 -08003114 @Override
Bookatzf56f2582019-09-04 16:06:41 -07003115 public boolean markGuestForDeletion(@UserIdInt int userId) {
Amith Yamasani1df14732014-08-29 21:37:27 -07003116 checkManageUsersPermission("Only the system can remove users");
3117 if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(
3118 UserManager.DISALLOW_REMOVE_USER, false)) {
3119 Log.w(LOG_TAG, "Cannot remove user. DISALLOW_REMOVE_USER is enabled.");
3120 return false;
3121 }
3122
3123 long ident = Binder.clearCallingIdentity();
3124 try {
Amith Yamasani12747872015-12-07 14:19:49 -08003125 final UserData userData;
Amith Yamasani1df14732014-08-29 21:37:27 -07003126 synchronized (mPackagesLock) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07003127 synchronized (mUsersLock) {
Bookatzf56f2582019-09-04 16:06:41 -07003128 userData = mUsers.get(userId);
3129 if (userId == 0 || userData == null || mRemovingUserIds.get(userId)) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07003130 return false;
3131 }
Amith Yamasani1df14732014-08-29 21:37:27 -07003132 }
Amith Yamasani12747872015-12-07 14:19:49 -08003133 if (!userData.info.isGuest()) {
Amith Yamasani1df14732014-08-29 21:37:27 -07003134 return false;
3135 }
Adam Lesinskieddeb492014-09-08 17:50:03 -07003136 // We set this to a guest user that is to be removed. This is a temporary state
3137 // where we are allowed to add new Guest users, even if this one is still not
3138 // removed. This user will still show up in getUserInfo() calls.
3139 // If we don't get around to removing this Guest user, it will be purged on next
3140 // startup.
Amith Yamasani12747872015-12-07 14:19:49 -08003141 userData.info.guestToRemove = true;
Amith Yamasani1df14732014-08-29 21:37:27 -07003142 // Mark it as disabled, so that it isn't returned any more when
3143 // profiles are queried.
Amith Yamasani12747872015-12-07 14:19:49 -08003144 userData.info.flags |= UserInfo.FLAG_DISABLED;
3145 writeUserLP(userData);
Amith Yamasani1df14732014-08-29 21:37:27 -07003146 }
3147 } finally {
3148 Binder.restoreCallingIdentity(ident);
3149 }
3150 return true;
3151 }
3152
3153 /**
Amith Yamasani0b285492011-04-14 17:35:23 -07003154 * Removes a user and all data directories created for that user. This method should be called
3155 * after the user's processes have been terminated.
Bookatzf56f2582019-09-04 16:06:41 -07003156 * @param userId the user's id
Amith Yamasani0b285492011-04-14 17:35:23 -07003157 */
Amith Yamasani12747872015-12-07 14:19:49 -08003158 @Override
Bookatzf56f2582019-09-04 16:06:41 -07003159 public boolean removeUser(@UserIdInt int userId) {
3160 Slog.i(LOG_TAG, "removeUser u" + userId);
Sudheer Shankaf5cea032016-06-08 17:13:24 -07003161 checkManageOrCreateUsersPermission("Only the system can remove users");
Esteban Talavera6c9116a2016-11-24 16:12:44 +00003162
3163 final boolean isManagedProfile;
3164 synchronized (mUsersLock) {
Bookatzf56f2582019-09-04 16:06:41 -07003165 UserInfo userInfo = getUserInfoLU(userId);
Esteban Talavera6c9116a2016-11-24 16:12:44 +00003166 isManagedProfile = userInfo != null && userInfo.isManagedProfile();
3167 }
3168 String restriction = isManagedProfile
3169 ? UserManager.DISALLOW_REMOVE_MANAGED_PROFILE : UserManager.DISALLOW_REMOVE_USER;
3170 if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(restriction, false)) {
3171 Log.w(LOG_TAG, "Cannot remove user. " + restriction + " is enabled.");
Julia Reynolds4ac5f852014-06-23 17:38:51 -04003172 return false;
3173 }
Bookatzf56f2582019-09-04 16:06:41 -07003174 return removeUserUnchecked(userId);
Nicolas Prevotdf1b87d2016-10-25 13:57:08 +01003175 }
Julia Reynolds4ac5f852014-06-23 17:38:51 -04003176
Bookatzf56f2582019-09-04 16:06:41 -07003177 private boolean removeUserUnchecked(@UserIdInt int userId) {
Kenny Guyee58b4f2014-05-23 15:19:53 +01003178 long ident = Binder.clearCallingIdentity();
3179 try {
Amith Yamasani12747872015-12-07 14:19:49 -08003180 final UserData userData;
Fyodor Kupolov0df68cd2015-10-01 13:54:22 -07003181 int currentUser = ActivityManager.getCurrentUser();
Bookatzf56f2582019-09-04 16:06:41 -07003182 if (currentUser == userId) {
jovanaka6763a32018-12-03 17:23:20 -08003183 Log.w(LOG_TAG, "Current user cannot be removed.");
Fyodor Kupolov0df68cd2015-10-01 13:54:22 -07003184 return false;
3185 }
Kenny Guyee58b4f2014-05-23 15:19:53 +01003186 synchronized (mPackagesLock) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07003187 synchronized (mUsersLock) {
Bookatzf56f2582019-09-04 16:06:41 -07003188 userData = mUsers.get(userId);
3189 if (userId == UserHandle.USER_SYSTEM) {
jovanaka6763a32018-12-03 17:23:20 -08003190 Log.e(LOG_TAG, "System user cannot be removed.");
3191 return false;
3192 }
3193
3194 if (userData == null) {
3195 Log.e(LOG_TAG, String.format(
Bookatzf56f2582019-09-04 16:06:41 -07003196 "Cannot remove user %d, invalid user id provided.", userId));
jovanaka6763a32018-12-03 17:23:20 -08003197 return false;
3198 }
3199
Bookatzf56f2582019-09-04 16:06:41 -07003200 if (mRemovingUserIds.get(userId)) {
jovanaka6763a32018-12-03 17:23:20 -08003201 Log.e(LOG_TAG, String.format(
Bookatzf56f2582019-09-04 16:06:41 -07003202 "User %d is already scheduled for removal.", userId));
Fyodor Kupolov82402752015-10-28 14:54:51 -07003203 return false;
3204 }
Jeff Sharkey6eb09392014-11-14 15:57:59 -08003205
Bookatzf56f2582019-09-04 16:06:41 -07003206 addRemovingUserIdLocked(userId);
Fyodor Kupolov82402752015-10-28 14:54:51 -07003207 }
Jeff Sharkey6eb09392014-11-14 15:57:59 -08003208
Kenny Guyee58b4f2014-05-23 15:19:53 +01003209 // Set this to a partially created user, so that the user will be purged
3210 // on next startup, in case the runtime stops now before stopping and
3211 // removing the user completely.
Amith Yamasani12747872015-12-07 14:19:49 -08003212 userData.info.partial = true;
Kenny Guyee58b4f2014-05-23 15:19:53 +01003213 // Mark it as disabled, so that it isn't returned any more when
3214 // profiles are queried.
Amith Yamasani12747872015-12-07 14:19:49 -08003215 userData.info.flags |= UserInfo.FLAG_DISABLED;
3216 writeUserLP(userData);
Kenny Guyee58b4f2014-05-23 15:19:53 +01003217 }
Fyodor Kupolov6c96f7f2017-06-28 18:22:59 -07003218 try {
Bookatzf56f2582019-09-04 16:06:41 -07003219 mAppOpsService.removeUser(userId);
Fyodor Kupolov6c96f7f2017-06-28 18:22:59 -07003220 } catch (RemoteException e) {
jovanaka6763a32018-12-03 17:23:20 -08003221 Log.w(LOG_TAG, "Unable to notify AppOpsService of removing user.", e);
Fyodor Kupolov6c96f7f2017-06-28 18:22:59 -07003222 }
Kenny Guyee58b4f2014-05-23 15:19:53 +01003223
Amith Yamasani12747872015-12-07 14:19:49 -08003224 if (userData.info.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
3225 && userData.info.isManagedProfile()) {
Kenny Guyee58b4f2014-05-23 15:19:53 +01003226 // Send broadcast to notify system that the user removed was a
3227 // managed user.
Amith Yamasani12747872015-12-07 14:19:49 -08003228 sendProfileRemovedBroadcast(userData.info.profileGroupId, userData.info.id);
Kenny Guyee58b4f2014-05-23 15:19:53 +01003229 }
3230
Bookatzf56f2582019-09-04 16:06:41 -07003231 if (DBG) Slog.i(LOG_TAG, "Stopping user " + userId);
Kenny Guyee58b4f2014-05-23 15:19:53 +01003232 int res;
3233 try {
Bookatzf56f2582019-09-04 16:06:41 -07003234 res = ActivityManager.getService().stopUser(userId, /* force= */ true,
Fyodor Kupolov9cbfc9e2015-10-07 15:52:33 -07003235 new IStopUserCallback.Stub() {
Kenny Guyee58b4f2014-05-23 15:19:53 +01003236 @Override
Bookatzf56f2582019-09-04 16:06:41 -07003237 public void userStopped(int userIdParam) {
3238 finishRemoveUser(userIdParam);
Kenny Guyee58b4f2014-05-23 15:19:53 +01003239 }
3240 @Override
Bookatzf56f2582019-09-04 16:06:41 -07003241 public void userStopAborted(int userIdParam) {
Kenny Guyee58b4f2014-05-23 15:19:53 +01003242 }
3243 });
3244 } catch (RemoteException e) {
jovanaka6763a32018-12-03 17:23:20 -08003245 Log.w(LOG_TAG, "Failed to stop user during removal.", e);
Dianne Hackborn80a4af22012-08-27 19:18:31 -07003246 return false;
3247 }
Kenny Guyee58b4f2014-05-23 15:19:53 +01003248 return res == ActivityManager.USER_OP_SUCCESS;
3249 } finally {
3250 Binder.restoreCallingIdentity(ident);
Dianne Hackborn80a4af22012-08-27 19:18:31 -07003251 }
Dianne Hackborn80a4af22012-08-27 19:18:31 -07003252 }
3253
Andreas Gampea36dc622018-02-05 17:19:22 -08003254 @GuardedBy("mUsersLock")
Fyodor Kupolov0f4533d2016-05-18 18:43:12 -07003255 @VisibleForTesting
Bookatzf56f2582019-09-04 16:06:41 -07003256 void addRemovingUserIdLocked(@UserIdInt int userId) {
Fyodor Kupolov0f4533d2016-05-18 18:43:12 -07003257 // We remember deleted user IDs to prevent them from being
3258 // reused during the current boot; they can still be reused
3259 // after a reboot or recycling of userIds.
3260 mRemovingUserIds.put(userId, true);
3261 mRecentlyRemovedIds.add(userId);
3262 // Keep LRU queue of recently removed IDs for recycling
3263 if (mRecentlyRemovedIds.size() > MAX_RECENTLY_REMOVED_IDS_SIZE) {
3264 mRecentlyRemovedIds.removeFirst();
3265 }
3266 }
3267
Bookatzf56f2582019-09-04 16:06:41 -07003268 void finishRemoveUser(final @UserIdInt int userId) {
3269 if (DBG) Slog.i(LOG_TAG, "finishRemoveUser " + userId);
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07003270 // Let other services shutdown any activity and clean up their state before completely
3271 // wiping the user's system directory and removing from the user list
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07003272 long ident = Binder.clearCallingIdentity();
3273 try {
3274 Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
Bookatzf56f2582019-09-04 16:06:41 -07003275 addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07003276 mContext.sendOrderedBroadcastAsUser(addedIntent, UserHandle.ALL,
3277 android.Manifest.permission.MANAGE_USERS,
3278
3279 new BroadcastReceiver() {
3280 @Override
3281 public void onReceive(Context context, Intent intent) {
3282 if (DBG) {
3283 Slog.i(LOG_TAG,
3284 "USER_REMOVED broadcast sent, cleaning up user data "
Bookatzf56f2582019-09-04 16:06:41 -07003285 + userId);
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07003286 }
3287 new Thread() {
Amith Yamasani12747872015-12-07 14:19:49 -08003288 @Override
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07003289 public void run() {
Wale Ogunwalea6191b42018-05-09 07:41:32 -07003290 // Clean up any ActivityTaskManager state
3291 LocalServices.getService(ActivityTaskManagerInternal.class)
Bookatzf56f2582019-09-04 16:06:41 -07003292 .onUserStopped(userId);
3293 removeUserState(userId);
Amith Yamasanidb6a14c2012-10-17 21:16:52 -07003294 }
3295 }.start();
3296 }
3297 },
3298
3299 null, Activity.RESULT_OK, null, null);
Dianne Hackborn5dc5a002012-09-15 19:33:48 -07003300 } finally {
3301 Binder.restoreCallingIdentity(ident);
3302 }
Amith Yamasani2a003292012-08-14 18:25:45 -07003303 }
3304
Bookatzf56f2582019-09-04 16:06:41 -07003305 private void removeUserState(final @UserIdInt int userId) {
Paul Crowley91293792016-03-25 15:23:07 -07003306 try {
Bookatzf56f2582019-09-04 16:06:41 -07003307 mContext.getSystemService(StorageManager.class).destroyUserKey(userId);
Paul Crowley91293792016-03-25 15:23:07 -07003308 } catch (IllegalStateException e) {
3309 // This may be simply because the user was partially created.
Bookatzf56f2582019-09-04 16:06:41 -07003310 Slog.i(LOG_TAG, "Destroying key for user " + userId + " failed, continuing anyway", e);
Paul Crowley91293792016-03-25 15:23:07 -07003311 }
Jeff Sharkeyfcf1e552016-04-14 20:44:58 -06003312
Amith Yamasanid04aaa32016-06-13 12:09:36 -07003313 // Cleanup gatekeeper secure user id
3314 try {
3315 final IGateKeeperService gk = GateKeeper.getService();
3316 if (gk != null) {
Bookatzf56f2582019-09-04 16:06:41 -07003317 gk.clearSecureUserId(userId);
Amith Yamasanid04aaa32016-06-13 12:09:36 -07003318 }
3319 } catch (Exception ex) {
3320 Slog.w(LOG_TAG, "unable to clear GK secure user id");
3321 }
3322
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07003323 // Cleanup package manager settings
Bookatzf56f2582019-09-04 16:06:41 -07003324 mPm.cleanUpUser(this, userId);
Amith Yamasanid04aaa32016-06-13 12:09:36 -07003325
3326 // Clean up all data before removing metadata
Bookatzf56f2582019-09-04 16:06:41 -07003327 mUserDataPreparer.destroyUserData(userId,
Amith Yamasanid04aaa32016-06-13 12:09:36 -07003328 StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
3329
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07003330 // Remove this user from the list
Fyodor Kupolov82402752015-10-28 14:54:51 -07003331 synchronized (mUsersLock) {
Bookatzf56f2582019-09-04 16:06:41 -07003332 mUsers.remove(userId);
3333 mIsUserManaged.delete(userId);
Amith Yamasaniea1b9d72016-05-27 15:57:38 +00003334 }
3335 synchronized (mUserStates) {
Bookatzf56f2582019-09-04 16:06:41 -07003336 mUserStates.delete(userId);
Makoto Onukie7927da2015-11-25 10:05:17 -08003337 }
3338 synchronized (mRestrictionsLock) {
Bookatzf56f2582019-09-04 16:06:41 -07003339 mBaseUserRestrictions.remove(userId);
3340 mAppliedUserRestrictions.remove(userId);
3341 mCachedEffectiveUserRestrictions.remove(userId);
3342 mDevicePolicyLocalUserRestrictions.remove(userId);
3343 if (mDevicePolicyGlobalUserRestrictions.get(userId) != null) {
3344 mDevicePolicyGlobalUserRestrictions.remove(userId);
Pavel Grafov6a40f092016-10-25 15:46:51 +01003345 applyUserRestrictionsForAllUsersLR();
3346 }
Fyodor Kupolov82402752015-10-28 14:54:51 -07003347 }
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07003348 // Update the user list
Fyodor Kupolove80085d2015-11-06 18:21:39 -08003349 synchronized (mPackagesLock) {
3350 writeUserListLP();
3351 }
Jeff Sharkeycd575992016-03-29 14:12:49 -06003352 // Remove user file
Bookatzf56f2582019-09-04 16:06:41 -07003353 AtomicFile userFile = new AtomicFile(new File(mUsersDir, userId + XML_SUFFIX));
Jeff Sharkeycd575992016-03-29 14:12:49 -06003354 userFile.delete();
Fyodor Kupolov82402752015-10-28 14:54:51 -07003355 updateUserIds();
Fyodor Kupolov0f4533d2016-05-18 18:43:12 -07003356 if (RELEASE_DELETED_USER_ID) {
3357 synchronized (mUsers) {
Bookatzf56f2582019-09-04 16:06:41 -07003358 mRemovingUserIds.delete(userId);
Fyodor Kupolov0f4533d2016-05-18 18:43:12 -07003359 }
3360 }
Amith Yamasani61f57372012-08-31 12:12:28 -07003361 }
3362
Kenny Guyf8d3a232014-05-15 16:09:52 +01003363 private void sendProfileRemovedBroadcast(int parentUserId, int removedUserId) {
Adam Connors7b66ed52014-04-14 11:58:10 +01003364 Intent managedProfileIntent = new Intent(Intent.ACTION_MANAGED_PROFILE_REMOVED);
Adam Connorsd4b584e2014-06-09 13:55:47 +01003365 managedProfileIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY |
3366 Intent.FLAG_RECEIVER_FOREGROUND);
Kenny Guyf8d3a232014-05-15 16:09:52 +01003367 managedProfileIntent.putExtra(Intent.EXTRA_USER, new UserHandle(removedUserId));
Jeff Sharkeyaf6ec292015-12-17 11:19:00 -07003368 managedProfileIntent.putExtra(Intent.EXTRA_USER_HANDLE, removedUserId);
Kenny Guyf8d3a232014-05-15 16:09:52 +01003369 mContext.sendBroadcastAsUser(managedProfileIntent, new UserHandle(parentUserId), null);
Adam Connors7b66ed52014-04-14 11:58:10 +01003370 }
3371
Amith Yamasani2a003292012-08-14 18:25:45 -07003372 @Override
Amith Yamasani7e99bc02013-04-16 18:24:51 -07003373 public Bundle getApplicationRestrictions(String packageName) {
3374 return getApplicationRestrictionsForUser(packageName, UserHandle.getCallingUserId());
3375 }
3376
3377 @Override
Bookatzf56f2582019-09-04 16:06:41 -07003378 public Bundle getApplicationRestrictionsForUser(String packageName, @UserIdInt int userId) {
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003379 if (UserHandle.getCallingUserId() != userId
Amith Yamasani9429afb2013-04-10 18:40:51 -07003380 || !UserHandle.isSameApp(Binder.getCallingUid(), getUidForPackage(packageName))) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07003381 checkSystemOrRoot("get application restrictions for other user/app " + packageName);
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003382 }
Fyodor Kupolovd31cee92017-09-05 16:31:08 -07003383 synchronized (mAppRestrictionsLock) {
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003384 // Read the restrictions from XML
Fyodor Kupolovd31cee92017-09-05 16:31:08 -07003385 return readApplicationRestrictionsLAr(packageName, userId);
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003386 }
3387 }
3388
3389 @Override
Amith Yamasani7e99bc02013-04-16 18:24:51 -07003390 public void setApplicationRestrictions(String packageName, Bundle restrictions,
Bookatzf56f2582019-09-04 16:06:41 -07003391 @UserIdInt int userId) {
Esteban Talavera5b9f1672015-12-11 15:22:34 +00003392 checkSystemOrRoot("set application restrictions");
Fyodor Kupolov0d88d542016-04-19 11:37:22 -07003393 if (restrictions != null) {
3394 restrictions.setDefusable(true);
3395 }
Fyodor Kupolovd31cee92017-09-05 16:31:08 -07003396 synchronized (mAppRestrictionsLock) {
Kenny Guyd21b2182014-07-17 16:38:55 +01003397 if (restrictions == null || restrictions.isEmpty()) {
Fyodor Kupolovd31cee92017-09-05 16:31:08 -07003398 cleanAppRestrictionsForPackageLAr(packageName, userId);
Kenny Guyd21b2182014-07-17 16:38:55 +01003399 } else {
3400 // Write the restrictions to XML
Fyodor Kupolovd31cee92017-09-05 16:31:08 -07003401 writeApplicationRestrictionsLAr(packageName, restrictions, userId);
Kenny Guyd21b2182014-07-17 16:38:55 +01003402 }
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003403 }
Robin Lee66e5d962014-04-09 16:44:21 +01003404
Fyodor Kupolovd2846122016-02-11 18:06:34 -08003405 // Notify package of changes via an intent - only sent to explicitly registered receivers.
3406 Intent changeIntent = new Intent(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED);
3407 changeIntent.setPackage(packageName);
3408 changeIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
3409 mContext.sendBroadcastAsUser(changeIntent, UserHandle.of(userId));
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003410 }
3411
3412 private int getUidForPackage(String packageName) {
Amith Yamasani9429afb2013-04-10 18:40:51 -07003413 long ident = Binder.clearCallingIdentity();
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003414 try {
3415 return mContext.getPackageManager().getApplicationInfo(packageName,
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07003416 PackageManager.MATCH_ANY_USER).uid;
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003417 } catch (NameNotFoundException nnfe) {
3418 return -1;
Amith Yamasani9429afb2013-04-10 18:40:51 -07003419 } finally {
3420 Binder.restoreCallingIdentity(ident);
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003421 }
3422 }
3423
Fyodor Kupolovd31cee92017-09-05 16:31:08 -07003424 @GuardedBy("mAppRestrictionsLock")
Bookatzf56f2582019-09-04 16:06:41 -07003425 private static Bundle readApplicationRestrictionsLAr(String packageName,
3426 @UserIdInt int userId) {
Fyodor Kupolov262f9952015-03-23 18:55:11 -07003427 AtomicFile restrictionsFile =
3428 new AtomicFile(new File(Environment.getUserSystemDirectory(userId),
3429 packageToRestrictionsFileName(packageName)));
Fyodor Kupolovd31cee92017-09-05 16:31:08 -07003430 return readApplicationRestrictionsLAr(restrictionsFile);
Fyodor Kupolov262f9952015-03-23 18:55:11 -07003431 }
3432
3433 @VisibleForTesting
Fyodor Kupolovd31cee92017-09-05 16:31:08 -07003434 @GuardedBy("mAppRestrictionsLock")
3435 static Bundle readApplicationRestrictionsLAr(AtomicFile restrictionsFile) {
Amith Yamasani7e99bc02013-04-16 18:24:51 -07003436 final Bundle restrictions = new Bundle();
Fyodor Kupolov262f9952015-03-23 18:55:11 -07003437 final ArrayList<String> values = new ArrayList<>();
Fyodor Kupolov6f34d362015-04-02 12:42:13 -07003438 if (!restrictionsFile.getBaseFile().exists()) {
Fyodor Kupolovf6ee2242015-04-06 10:15:07 -07003439 return restrictions;
Fyodor Kupolov6f34d362015-04-02 12:42:13 -07003440 }
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003441
3442 FileInputStream fis = null;
3443 try {
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003444 fis = restrictionsFile.openRead();
3445 XmlPullParser parser = Xml.newPullParser();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01003446 parser.setInput(fis, StandardCharsets.UTF_8.name());
Fyodor Kupolov262f9952015-03-23 18:55:11 -07003447 XmlUtils.nextElement(parser);
3448 if (parser.getEventType() != XmlPullParser.START_TAG) {
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003449 Slog.e(LOG_TAG, "Unable to read restrictions file "
3450 + restrictionsFile.getBaseFile());
Amith Yamasani7e99bc02013-04-16 18:24:51 -07003451 return restrictions;
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003452 }
Fyodor Kupolov262f9952015-03-23 18:55:11 -07003453 while (parser.next() != XmlPullParser.END_DOCUMENT) {
3454 readEntry(restrictions, values, parser);
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003455 }
Fyodor Kupolov262f9952015-03-23 18:55:11 -07003456 } catch (IOException|XmlPullParserException e) {
3457 Log.w(LOG_TAG, "Error parsing " + restrictionsFile.getBaseFile(), e);
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003458 } finally {
Fyodor Kupolov262f9952015-03-23 18:55:11 -07003459 IoUtils.closeQuietly(fis);
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003460 }
Amith Yamasani7e99bc02013-04-16 18:24:51 -07003461 return restrictions;
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003462 }
3463
Fyodor Kupolov262f9952015-03-23 18:55:11 -07003464 private static void readEntry(Bundle restrictions, ArrayList<String> values,
3465 XmlPullParser parser) throws XmlPullParserException, IOException {
3466 int type = parser.getEventType();
3467 if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_ENTRY)) {
3468 String key = parser.getAttributeValue(null, ATTR_KEY);
3469 String valType = parser.getAttributeValue(null, ATTR_VALUE_TYPE);
3470 String multiple = parser.getAttributeValue(null, ATTR_MULTIPLE);
3471 if (multiple != null) {
3472 values.clear();
3473 int count = Integer.parseInt(multiple);
3474 while (count > 0 && (type = parser.next()) != XmlPullParser.END_DOCUMENT) {
3475 if (type == XmlPullParser.START_TAG
3476 && parser.getName().equals(TAG_VALUE)) {
3477 values.add(parser.nextText().trim());
3478 count--;
3479 }
3480 }
3481 String [] valueStrings = new String[values.size()];
3482 values.toArray(valueStrings);
3483 restrictions.putStringArray(key, valueStrings);
3484 } else if (ATTR_TYPE_BUNDLE.equals(valType)) {
3485 restrictions.putBundle(key, readBundleEntry(parser, values));
3486 } else if (ATTR_TYPE_BUNDLE_ARRAY.equals(valType)) {
3487 final int outerDepth = parser.getDepth();
3488 ArrayList<Bundle> bundleList = new ArrayList<>();
3489 while (XmlUtils.nextElementWithin(parser, outerDepth)) {
3490 Bundle childBundle = readBundleEntry(parser, values);
3491 bundleList.add(childBundle);
3492 }
3493 restrictions.putParcelableArray(key,
3494 bundleList.toArray(new Bundle[bundleList.size()]));
3495 } else {
3496 String value = parser.nextText().trim();
3497 if (ATTR_TYPE_BOOLEAN.equals(valType)) {
3498 restrictions.putBoolean(key, Boolean.parseBoolean(value));
3499 } else if (ATTR_TYPE_INTEGER.equals(valType)) {
3500 restrictions.putInt(key, Integer.parseInt(value));
3501 } else {
3502 restrictions.putString(key, value);
3503 }
3504 }
3505 }
3506 }
3507
3508 private static Bundle readBundleEntry(XmlPullParser parser, ArrayList<String> values)
3509 throws IOException, XmlPullParserException {
3510 Bundle childBundle = new Bundle();
3511 final int outerDepth = parser.getDepth();
3512 while (XmlUtils.nextElementWithin(parser, outerDepth)) {
3513 readEntry(childBundle, values, parser);
3514 }
3515 return childBundle;
3516 }
3517
Fyodor Kupolovd31cee92017-09-05 16:31:08 -07003518 @GuardedBy("mAppRestrictionsLock")
3519 private static void writeApplicationRestrictionsLAr(String packageName,
Bookatzf56f2582019-09-04 16:06:41 -07003520 Bundle restrictions, @UserIdInt int userId) {
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003521 AtomicFile restrictionsFile = new AtomicFile(
3522 new File(Environment.getUserSystemDirectory(userId),
Amith Yamasanifc95e702013-09-26 13:20:17 -07003523 packageToRestrictionsFileName(packageName)));
Fyodor Kupolovd31cee92017-09-05 16:31:08 -07003524 writeApplicationRestrictionsLAr(restrictions, restrictionsFile);
Fyodor Kupolov262f9952015-03-23 18:55:11 -07003525 }
3526
3527 @VisibleForTesting
Fyodor Kupolovd31cee92017-09-05 16:31:08 -07003528 @GuardedBy("mAppRestrictionsLock")
3529 static void writeApplicationRestrictionsLAr(Bundle restrictions, AtomicFile restrictionsFile) {
Fyodor Kupolov262f9952015-03-23 18:55:11 -07003530 FileOutputStream fos = null;
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003531 try {
3532 fos = restrictionsFile.startWrite();
3533 final BufferedOutputStream bos = new BufferedOutputStream(fos);
3534
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003535 final XmlSerializer serializer = new FastXmlSerializer();
Wojciech Staszkiewicz9e9e2e72015-05-08 14:58:46 +01003536 serializer.setOutput(bos, StandardCharsets.UTF_8.name());
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003537 serializer.startDocument(null, true);
3538 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
3539
3540 serializer.startTag(null, TAG_RESTRICTIONS);
Fyodor Kupolov262f9952015-03-23 18:55:11 -07003541 writeBundle(restrictions, serializer);
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003542 serializer.endTag(null, TAG_RESTRICTIONS);
3543
3544 serializer.endDocument();
3545 restrictionsFile.finishWrite(fos);
3546 } catch (Exception e) {
3547 restrictionsFile.failWrite(fos);
Fyodor Kupolov262f9952015-03-23 18:55:11 -07003548 Slog.e(LOG_TAG, "Error writing application restrictions list", e);
3549 }
3550 }
3551
3552 private static void writeBundle(Bundle restrictions, XmlSerializer serializer)
3553 throws IOException {
3554 for (String key : restrictions.keySet()) {
3555 Object value = restrictions.get(key);
3556 serializer.startTag(null, TAG_ENTRY);
3557 serializer.attribute(null, ATTR_KEY, key);
3558
3559 if (value instanceof Boolean) {
3560 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BOOLEAN);
3561 serializer.text(value.toString());
3562 } else if (value instanceof Integer) {
3563 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_INTEGER);
3564 serializer.text(value.toString());
3565 } else if (value == null || value instanceof String) {
3566 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_STRING);
3567 serializer.text(value != null ? (String) value : "");
3568 } else if (value instanceof Bundle) {
3569 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BUNDLE);
3570 writeBundle((Bundle) value, serializer);
3571 } else if (value instanceof Parcelable[]) {
3572 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BUNDLE_ARRAY);
3573 Parcelable[] array = (Parcelable[]) value;
3574 for (Parcelable parcelable : array) {
3575 if (!(parcelable instanceof Bundle)) {
3576 throw new IllegalArgumentException("bundle-array can only hold Bundles");
3577 }
3578 serializer.startTag(null, TAG_ENTRY);
3579 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BUNDLE);
3580 writeBundle((Bundle) parcelable, serializer);
3581 serializer.endTag(null, TAG_ENTRY);
3582 }
3583 } else {
3584 serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_STRING_ARRAY);
3585 String[] values = (String[]) value;
3586 serializer.attribute(null, ATTR_MULTIPLE, Integer.toString(values.length));
3587 for (String choice : values) {
3588 serializer.startTag(null, TAG_VALUE);
3589 serializer.text(choice != null ? choice : "");
3590 serializer.endTag(null, TAG_VALUE);
3591 }
3592 }
3593 serializer.endTag(null, TAG_ENTRY);
Amith Yamasanidf2e92a2013-03-01 17:04:38 -08003594 }
3595 }
3596
3597 @Override
Bookatzf56f2582019-09-04 16:06:41 -07003598 public int getUserSerialNumber(@UserIdInt int userId) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07003599 synchronized (mUsersLock) {
Bookatzf56f2582019-09-04 16:06:41 -07003600 final UserInfo userInfo = getUserInfoLU(userId);
Pavel Grafov9c295d42019-03-26 19:42:08 +00003601 return userInfo != null ? userInfo.serialNumber : -1;
Amith Yamasani2a003292012-08-14 18:25:45 -07003602 }
3603 }
3604
3605 @Override
Bookatzf56f2582019-09-04 16:06:41 -07003606 public boolean isUserNameSet(@UserIdInt int userId) {
Fyodor Kupolov605b12a2017-05-10 15:58:09 -07003607 synchronized (mUsersLock) {
Bookatzf56f2582019-09-04 16:06:41 -07003608 final UserInfo userInfo = getUserInfoLU(userId);
Fyodor Kupolov605b12a2017-05-10 15:58:09 -07003609 return userInfo != null && userInfo.name != null;
3610 }
3611 }
3612
3613 @Override
Amith Yamasani2a003292012-08-14 18:25:45 -07003614 public int getUserHandle(int userSerialNumber) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07003615 synchronized (mUsersLock) {
Amith Yamasani2a003292012-08-14 18:25:45 -07003616 for (int userId : mUserIds) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07003617 UserInfo info = getUserInfoLU(userId);
Kenny Guy945f8832015-02-10 15:17:26 +00003618 if (info != null && info.serialNumber == userSerialNumber) return userId;
Amith Yamasani2a003292012-08-14 18:25:45 -07003619 }
3620 // Not found
3621 return -1;
Amith Yamasani13593602012-03-22 16:16:17 -07003622 }
3623 }
3624
Fyodor Kupolovff7233e2015-04-08 11:28:52 -07003625 @Override
Bookatzf56f2582019-09-04 16:06:41 -07003626 public long getUserCreationTime(@UserIdInt int userId) {
Fyodor Kupolovff7233e2015-04-08 11:28:52 -07003627 int callingUserId = UserHandle.getCallingUserId();
3628 UserInfo userInfo = null;
Fyodor Kupolov82402752015-10-28 14:54:51 -07003629 synchronized (mUsersLock) {
Bookatzf56f2582019-09-04 16:06:41 -07003630 if (callingUserId == userId) {
3631 userInfo = getUserInfoLU(userId);
Fyodor Kupolovff7233e2015-04-08 11:28:52 -07003632 } else {
Bookatzf56f2582019-09-04 16:06:41 -07003633 UserInfo parent = getProfileParentLU(userId);
Fyodor Kupolovff7233e2015-04-08 11:28:52 -07003634 if (parent != null && parent.id == callingUserId) {
Bookatzf56f2582019-09-04 16:06:41 -07003635 userInfo = getUserInfoLU(userId);
Fyodor Kupolovff7233e2015-04-08 11:28:52 -07003636 }
3637 }
3638 }
3639 if (userInfo == null) {
Bookatzf56f2582019-09-04 16:06:41 -07003640 throw new SecurityException("userId can only be the calling user or a managed "
Fyodor Kupolovff7233e2015-04-08 11:28:52 -07003641 + "profile associated with this user");
3642 }
3643 return userInfo.creationTime;
3644 }
3645
Amith Yamasani0b285492011-04-14 17:35:23 -07003646 /**
3647 * Caches the list of user ids in an array, adjusting the array size when necessary.
3648 */
Fyodor Kupolov82402752015-10-28 14:54:51 -07003649 private void updateUserIds() {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07003650 int num = 0;
Fyodor Kupolov82402752015-10-28 14:54:51 -07003651 synchronized (mUsersLock) {
3652 final int userSize = mUsers.size();
3653 for (int i = 0; i < userSize; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -08003654 if (!mUsers.valueAt(i).info.partial) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07003655 num++;
3656 }
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07003657 }
Fyodor Kupolov82402752015-10-28 14:54:51 -07003658 final int[] newUsers = new int[num];
3659 int n = 0;
3660 for (int i = 0; i < userSize; i++) {
Amith Yamasani12747872015-12-07 14:19:49 -08003661 if (!mUsers.valueAt(i).info.partial) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07003662 newUsers[n++] = mUsers.keyAt(i);
3663 }
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -07003664 }
Fyodor Kupolov82402752015-10-28 14:54:51 -07003665 mUserIds = newUsers;
Amith Yamasani0b285492011-04-14 17:35:23 -07003666 }
3667 }
3668
3669 /**
Jeff Sharkey0e62384c2016-01-13 18:52:55 -07003670 * Called right before a user is started. This gives us a chance to prepare
3671 * app storage and apply any user restrictions.
Makoto Onuki1a2cd742015-11-16 13:51:27 -08003672 */
Bookatzf56f2582019-09-04 16:06:41 -07003673 public void onBeforeStartUser(@UserIdInt int userId) {
Fyodor Kupolovd80c3622016-07-19 17:22:09 -07003674 UserInfo userInfo = getUserInfo(userId);
3675 if (userInfo == null) {
3676 return;
3677 }
Felipe Leme3aad1be2019-05-31 11:43:12 -07003678 TimingsTraceAndSlog t = new TimingsTraceAndSlog();
3679 t.traceBegin("onBeforeStartUser-" + userId);
Fyodor Kupolovd80c3622016-07-19 17:22:09 -07003680 final int userSerial = userInfo.serialNumber;
3681 // Migrate only if build fingerprints mismatch
3682 boolean migrateAppsData = !Build.FINGERPRINT.equals(userInfo.lastLoggedInFingerprint);
Felipe Leme3aad1be2019-05-31 11:43:12 -07003683 t.traceBegin("prepareUserData");
Fyodor Kupolov5c0ecfd2017-01-27 11:11:57 -08003684 mUserDataPreparer.prepareUserData(userId, userSerial, StorageManager.FLAG_STORAGE_DE);
Felipe Leme3aad1be2019-05-31 11:43:12 -07003685 t.traceEnd();
3686 t.traceBegin("reconcileAppsData");
Fyodor Kupolovd80c3622016-07-19 17:22:09 -07003687 mPm.reconcileAppsData(userId, StorageManager.FLAG_STORAGE_DE, migrateAppsData);
Felipe Leme3aad1be2019-05-31 11:43:12 -07003688 t.traceEnd();
Jeff Sharkey0e62384c2016-01-13 18:52:55 -07003689
3690 if (userId != UserHandle.USER_SYSTEM) {
Felipe Leme3aad1be2019-05-31 11:43:12 -07003691 t.traceBegin("applyUserRestrictions");
Jeff Sharkey0e62384c2016-01-13 18:52:55 -07003692 synchronized (mRestrictionsLock) {
3693 applyUserRestrictionsLR(userId);
3694 }
Felipe Leme3aad1be2019-05-31 11:43:12 -07003695 t.traceEnd();
Makoto Onuki1a2cd742015-11-16 13:51:27 -08003696 }
Felipe Leme3aad1be2019-05-31 11:43:12 -07003697 t.traceEnd(); // onBeforeStartUser
Makoto Onuki1a2cd742015-11-16 13:51:27 -08003698 }
3699
3700 /**
Jeff Sharkey0e62384c2016-01-13 18:52:55 -07003701 * Called right before a user is unlocked. This gives us a chance to prepare
3702 * app storage.
3703 */
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06003704 public void onBeforeUnlockUser(@UserIdInt int userId) {
Fyodor Kupolovd80c3622016-07-19 17:22:09 -07003705 UserInfo userInfo = getUserInfo(userId);
3706 if (userInfo == null) {
3707 return;
3708 }
3709 final int userSerial = userInfo.serialNumber;
3710 // Migrate only if build fingerprints mismatch
3711 boolean migrateAppsData = !Build.FINGERPRINT.equals(userInfo.lastLoggedInFingerprint);
Fyodor Kupolov5c0ecfd2017-01-27 11:11:57 -08003712 mUserDataPreparer.prepareUserData(userId, userSerial, StorageManager.FLAG_STORAGE_CE);
Fyodor Kupolovd80c3622016-07-19 17:22:09 -07003713 mPm.reconcileAppsData(userId, StorageManager.FLAG_STORAGE_CE, migrateAppsData);
Jeff Sharkey0e62384c2016-01-13 18:52:55 -07003714 }
3715
3716 /**
Fyodor Kupolov50979d12017-01-27 17:36:32 -08003717 * Examine all users present on given mounted volume, and destroy data
3718 * belonging to users that are no longer valid, or whose user ID has been
3719 * recycled.
3720 */
3721 void reconcileUsers(String volumeUuid) {
3722 mUserDataPreparer.reconcileUsers(volumeUuid, getUsers(true /* excludeDying */));
3723 }
3724
3725 /**
Amith Yamasani1a7472e2013-07-02 11:17:30 -07003726 * Make a note of the last started time of a user and do some cleanup.
Amith Yamasanieb437d42016-04-29 09:31:25 -07003727 * This is called with ActivityManagerService lock held.
Amith Yamasani920ace02012-09-20 22:15:37 -07003728 * @param userId the user that was just foregrounded
3729 */
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06003730 public void onUserLoggedIn(@UserIdInt int userId) {
Amith Yamasani12747872015-12-07 14:19:49 -08003731 UserData userData = getUserDataNoChecks(userId);
3732 if (userData == null || userData.info.partial) {
Fyodor Kupolove80085d2015-11-06 18:21:39 -08003733 Slog.w(LOG_TAG, "userForeground: unknown user #" + userId);
3734 return;
3735 }
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06003736
3737 final long now = System.currentTimeMillis();
Fyodor Kupolove80085d2015-11-06 18:21:39 -08003738 if (now > EPOCH_PLUS_30_YEARS) {
Amith Yamasani12747872015-12-07 14:19:49 -08003739 userData.info.lastLoggedInTime = now;
Amith Yamasani920ace02012-09-20 22:15:37 -07003740 }
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06003741 userData.info.lastLoggedInFingerprint = Build.FINGERPRINT;
3742 scheduleWriteUser(userData);
Amith Yamasani920ace02012-09-20 22:15:37 -07003743 }
3744
3745 /**
Amith Yamasani0b285492011-04-14 17:35:23 -07003746 * Returns the next available user id, filling in any holes in the ids.
Amith Yamasani0b285492011-04-14 17:35:23 -07003747 */
Fyodor Kupolov0f4533d2016-05-18 18:43:12 -07003748 @VisibleForTesting
3749 int getNextAvailableId() {
3750 int nextId;
Fyodor Kupolov82402752015-10-28 14:54:51 -07003751 synchronized (mUsersLock) {
Fyodor Kupolov0f4533d2016-05-18 18:43:12 -07003752 nextId = scanNextAvailableIdLocked();
3753 if (nextId >= 0) {
3754 return nextId;
3755 }
3756 // All ids up to MAX_USER_ID were used. Remove all mRemovingUserIds,
3757 // except most recently removed
3758 if (mRemovingUserIds.size() > 0) {
3759 Slog.i(LOG_TAG, "All available IDs are used. Recycling LRU ids.");
3760 mRemovingUserIds.clear();
3761 for (Integer recentlyRemovedId : mRecentlyRemovedIds) {
3762 mRemovingUserIds.put(recentlyRemovedId, true);
Amith Yamasani195263742012-08-21 15:40:12 -07003763 }
Fyodor Kupolov0f4533d2016-05-18 18:43:12 -07003764 nextId = scanNextAvailableIdLocked();
Amith Yamasani4b2e9342011-03-31 12:38:53 -07003765 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07003766 }
Fyodor Kupolov0f4533d2016-05-18 18:43:12 -07003767 if (nextId < 0) {
3768 throw new IllegalStateException("No user id available!");
3769 }
3770 return nextId;
3771 }
3772
Andreas Gampea36dc622018-02-05 17:19:22 -08003773 @GuardedBy("mUsersLock")
Fyodor Kupolov0f4533d2016-05-18 18:43:12 -07003774 private int scanNextAvailableIdLocked() {
3775 for (int i = MIN_USER_ID; i < MAX_USER_ID; i++) {
3776 if (mUsers.indexOfKey(i) < 0 && !mRemovingUserIds.get(i)) {
3777 return i;
3778 }
3779 }
3780 return -1;
Amith Yamasani4b2e9342011-03-31 12:38:53 -07003781 }
Amith Yamasani920ace02012-09-20 22:15:37 -07003782
Fyodor Kupolovd31cee92017-09-05 16:31:08 -07003783 private static String packageToRestrictionsFileName(String packageName) {
Amith Yamasanifc95e702013-09-26 13:20:17 -07003784 return RESTRICTIONS_FILE_PREFIX + packageName + XML_SUFFIX;
3785 }
3786
Amith Yamasani920ace02012-09-20 22:15:37 -07003787 @Override
Bookatzf56f2582019-09-04 16:06:41 -07003788 public void setSeedAccountData(@UserIdInt int userId, String accountName, String accountType,
Amith Yamasani12747872015-12-07 14:19:49 -08003789 PersistableBundle accountOptions, boolean persist) {
3790 checkManageUsersPermission("Require MANAGE_USERS permission to set user seed data");
3791 synchronized (mPackagesLock) {
3792 final UserData userData;
3793 synchronized (mUsersLock) {
3794 userData = getUserDataLU(userId);
3795 if (userData == null) {
3796 Slog.e(LOG_TAG, "No such user for settings seed data u=" + userId);
3797 return;
3798 }
3799 userData.seedAccountName = accountName;
3800 userData.seedAccountType = accountType;
3801 userData.seedAccountOptions = accountOptions;
3802 userData.persistSeedData = persist;
3803 }
3804 if (persist) {
3805 writeUserLP(userData);
3806 }
3807 }
3808 }
3809
3810 @Override
3811 public String getSeedAccountName() throws RemoteException {
3812 checkManageUsersPermission("Cannot get seed account information");
3813 synchronized (mUsersLock) {
3814 UserData userData = getUserDataLU(UserHandle.getCallingUserId());
3815 return userData.seedAccountName;
3816 }
3817 }
3818
3819 @Override
3820 public String getSeedAccountType() throws RemoteException {
3821 checkManageUsersPermission("Cannot get seed account information");
3822 synchronized (mUsersLock) {
3823 UserData userData = getUserDataLU(UserHandle.getCallingUserId());
3824 return userData.seedAccountType;
3825 }
3826 }
3827
3828 @Override
3829 public PersistableBundle getSeedAccountOptions() throws RemoteException {
3830 checkManageUsersPermission("Cannot get seed account information");
3831 synchronized (mUsersLock) {
3832 UserData userData = getUserDataLU(UserHandle.getCallingUserId());
3833 return userData.seedAccountOptions;
3834 }
3835 }
3836
3837 @Override
3838 public void clearSeedAccountData() throws RemoteException {
3839 checkManageUsersPermission("Cannot clear seed account information");
3840 synchronized (mPackagesLock) {
3841 UserData userData;
3842 synchronized (mUsersLock) {
3843 userData = getUserDataLU(UserHandle.getCallingUserId());
3844 if (userData == null) return;
3845 userData.clearSeedAccountData();
3846 }
3847 writeUserLP(userData);
3848 }
3849 }
3850
3851 @Override
3852 public boolean someUserHasSeedAccount(String accountName, String accountType)
3853 throws RemoteException {
3854 checkManageUsersPermission("Cannot check seed account information");
3855 synchronized (mUsersLock) {
3856 final int userSize = mUsers.size();
3857 for (int i = 0; i < userSize; i++) {
3858 final UserData data = mUsers.valueAt(i);
3859 if (data.info.isInitialized()) continue;
3860 if (data.seedAccountName == null || !data.seedAccountName.equals(accountName)) {
3861 continue;
3862 }
3863 if (data.seedAccountType == null || !data.seedAccountType.equals(accountType)) {
3864 continue;
3865 }
3866 return true;
3867 }
3868 }
3869 return false;
3870 }
3871
3872 @Override
Todd Kennedy60459ab2015-10-30 11:32:16 -07003873 public void onShellCommand(FileDescriptor in, FileDescriptor out,
Dianne Hackborn354736e2016-08-22 17:00:05 -07003874 FileDescriptor err, String[] args, ShellCallback callback,
3875 ResultReceiver resultReceiver) {
3876 (new Shell()).exec(this, in, out, err, args, callback, resultReceiver);
Todd Kennedy60459ab2015-10-30 11:32:16 -07003877 }
3878
3879 int onShellCommand(Shell shell, String cmd) {
3880 if (cmd == null) {
3881 return shell.handleDefaultCommands(cmd);
3882 }
3883
3884 final PrintWriter pw = shell.getOutPrintWriter();
3885 try {
3886 switch(cmd) {
3887 case "list":
Felipe Lemec1ca4412019-09-11 09:23:26 -07003888 return runList(pw, shell);
Hui Yu8ba65972018-04-16 18:45:48 -07003889 default:
3890 return shell.handleDefaultCommands(cmd);
Todd Kennedy60459ab2015-10-30 11:32:16 -07003891 }
3892 } catch (RemoteException e) {
3893 pw.println("Remote exception: " + e);
3894 }
3895 return -1;
3896 }
3897
Felipe Lemec1ca4412019-09-11 09:23:26 -07003898 private int runList(PrintWriter pw, Shell shell) throws RemoteException {
3899 boolean all = false;
3900 boolean verbose = false;
3901 String opt;
3902 while ((opt = shell.getNextOption()) != null) {
3903 switch (opt) {
3904 case "-v":
3905 verbose = true;
3906 break;
3907 case "--all":
3908 all = true;
3909 break;
3910 default:
3911 pw.println("Invalid option: " + opt);
3912 return -1;
3913 }
3914 }
Sudheer Shankadc589ac2016-11-10 15:30:17 -08003915 final IActivityManager am = ActivityManager.getService();
Felipe Lemec1ca4412019-09-11 09:23:26 -07003916 final List<UserInfo> users = getUsers(/* excludePartial= */ !all,
3917 /* excludingDying=*/ false, /* excludePreCreated= */ !all);
Todd Kennedy60459ab2015-10-30 11:32:16 -07003918 if (users == null) {
3919 pw.println("Error: couldn't get users");
3920 return 1;
3921 } else {
Felipe Lemec1ca4412019-09-11 09:23:26 -07003922 final int size = users.size();
3923 int currentUser = UserHandle.USER_NULL;
3924 if (verbose) {
3925 pw.printf("%d users:\n\n", size);
3926 currentUser = am.getCurrentUser().id;
3927 } else {
3928 // NOTE: the standard "list users" command is used by integration tests and
3929 // hence should not be changed. If you need to add more info, use the
3930 // verbose option.
3931 pw.println("Users:");
3932 }
3933 for (int i = 0; i < size; i++) {
3934 final UserInfo user = users.get(i);
3935 final boolean running = am.isUserRunning(user.id, 0);
3936 final boolean current = user.id == currentUser;
3937 if (verbose) {
3938 pw.printf("%d: id=%d, name=%s, flags=%s%s%s%s%s\n", i, user.id, user.name,
3939 UserInfo.flagsToString(user.flags),
3940 running ? " (running)" : "",
3941 user.partial ? " (partial)" : "",
3942 user.preCreated ? " (pre-created)" : "",
3943 current ? " (current)" : "");
3944 } else {
3945 // NOTE: the standard "list users" command is used by integration tests and
3946 // hence should not be changed. If you need to add more info, use the
3947 // verbose option.
3948 pw.printf("\t%s%s\n", user, running ? " running" : "");
3949 }
Todd Kennedy60459ab2015-10-30 11:32:16 -07003950 }
3951 return 0;
3952 }
3953 }
3954
3955 @Override
Amith Yamasani920ace02012-09-20 22:15:37 -07003956 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06003957 if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
Amith Yamasani920ace02012-09-20 22:15:37 -07003958
3959 long now = System.currentTimeMillis();
Makoto Onuki73dded22017-12-20 13:14:48 +09003960 final long nowRealtime = SystemClock.elapsedRealtime();
Felipe Lemed7b88382019-06-12 17:40:53 -07003961
3962 final int currentUser = LocalServices.getService(ActivityManagerInternal.class)
3963 .getCurrentUserId();
3964 pw.print("Current user: "); pw.println(currentUser);
3965
Amith Yamasani920ace02012-09-20 22:15:37 -07003966 StringBuilder sb = new StringBuilder();
3967 synchronized (mPackagesLock) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07003968 synchronized (mUsersLock) {
3969 pw.println("Users:");
3970 for (int i = 0; i < mUsers.size(); i++) {
Amith Yamasani12747872015-12-07 14:19:49 -08003971 UserData userData = mUsers.valueAt(i);
3972 if (userData == null) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07003973 continue;
3974 }
Amith Yamasani12747872015-12-07 14:19:49 -08003975 UserInfo userInfo = userData.info;
3976 final int userId = userInfo.id;
3977 pw.print(" "); pw.print(userInfo);
3978 pw.print(" serialNo="); pw.print(userInfo.serialNumber);
Felipe Lemed7b88382019-06-12 17:40:53 -07003979 pw.print(" isPrimary="); pw.print(userInfo.isPrimary());
Makoto Onukie7927da2015-11-25 10:05:17 -08003980 if (mRemovingUserIds.get(userId)) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07003981 pw.print(" <removing> ");
3982 }
Amith Yamasani12747872015-12-07 14:19:49 -08003983 if (userInfo.partial) {
Fyodor Kupolov82402752015-10-28 14:54:51 -07003984 pw.print(" <partial>");
3985 }
Felipe Lemec1ca4412019-09-11 09:23:26 -07003986 if (userInfo.preCreated) {
3987 pw.print(" <pre-created>");
3988 }
Fyodor Kupolov82402752015-10-28 14:54:51 -07003989 pw.println();
Felipe Lemee5434c32019-08-13 09:28:33 -07003990 pw.print(" Flags: "); pw.print(userInfo.flags); pw.print(" (");
3991 pw.print(UserInfo.flagsToString(userInfo.flags)); pw.println(")");
Makoto Onuki88aef752017-03-29 16:52:03 -07003992 pw.print(" State: ");
3993 final int state;
3994 synchronized (mUserStates) {
3995 state = mUserStates.get(userId, -1);
3996 }
3997 pw.println(UserState.stateToString(state));
Fyodor Kupolov82402752015-10-28 14:54:51 -07003998 pw.print(" Created: ");
Makoto Onuki73dded22017-12-20 13:14:48 +09003999 dumpTimeAgo(pw, sb, now, userInfo.creationTime);
4000
Fyodor Kupolov82402752015-10-28 14:54:51 -07004001 pw.print(" Last logged in: ");
Makoto Onuki73dded22017-12-20 13:14:48 +09004002 dumpTimeAgo(pw, sb, now, userInfo.lastLoggedInTime);
4003
Jeff Sharkeybd91e2f2016-03-22 15:32:31 -06004004 pw.print(" Last logged in fingerprint: ");
4005 pw.println(userInfo.lastLoggedInFingerprint);
Makoto Onuki73dded22017-12-20 13:14:48 +09004006
4007 pw.print(" Start time: ");
4008 dumpTimeAgo(pw, sb, nowRealtime, userData.startRealtime);
4009
4010 pw.print(" Unlock time: ");
4011 dumpTimeAgo(pw, sb, nowRealtime, userData.unlockRealtime);
4012
Makoto Onukie7927da2015-11-25 10:05:17 -08004013 pw.print(" Has profile owner: ");
4014 pw.println(mIsUserManaged.get(userId));
Fyodor Kupolov82402752015-10-28 14:54:51 -07004015 pw.println(" Restrictions:");
4016 synchronized (mRestrictionsLock) {
4017 UserRestrictionsUtils.dumpRestrictions(
Amith Yamasani12747872015-12-07 14:19:49 -08004018 pw, " ", mBaseUserRestrictions.get(userInfo.id));
Pavel Grafov6a40f092016-10-25 15:46:51 +01004019 pw.println(" Device policy global restrictions:");
4020 UserRestrictionsUtils.dumpRestrictions(
4021 pw, " ", mDevicePolicyGlobalUserRestrictions.get(userInfo.id));
Makoto Onuki1a2cd742015-11-16 13:51:27 -08004022 pw.println(" Device policy local restrictions:");
4023 UserRestrictionsUtils.dumpRestrictions(
Amith Yamasani12747872015-12-07 14:19:49 -08004024 pw, " ", mDevicePolicyLocalUserRestrictions.get(userInfo.id));
Fyodor Kupolov82402752015-10-28 14:54:51 -07004025 pw.println(" Effective restrictions:");
4026 UserRestrictionsUtils.dumpRestrictions(
Amith Yamasani12747872015-12-07 14:19:49 -08004027 pw, " ", mCachedEffectiveUserRestrictions.get(userInfo.id));
Fyodor Kupolov82402752015-10-28 14:54:51 -07004028 }
Amith Yamasani12747872015-12-07 14:19:49 -08004029
4030 if (userData.account != null) {
4031 pw.print(" Account name: " + userData.account);
Xiaohui Chenb3b92582015-12-07 11:22:13 -08004032 pw.println();
4033 }
Amith Yamasani12747872015-12-07 14:19:49 -08004034
4035 if (userData.seedAccountName != null) {
4036 pw.print(" Seed account name: " + userData.seedAccountName);
4037 pw.println();
4038 if (userData.seedAccountType != null) {
4039 pw.print(" account type: " + userData.seedAccountType);
4040 pw.println();
4041 }
4042 if (userData.seedAccountOptions != null) {
4043 pw.print(" account options exist");
4044 pw.println();
4045 }
4046 }
Amith Yamasani920ace02012-09-20 22:15:37 -07004047 }
Amith Yamasani920ace02012-09-20 22:15:37 -07004048 }
Amith Yamasani12747872015-12-07 14:19:49 -08004049 pw.println();
Pavel Grafov6a40f092016-10-25 15:46:51 +01004050 pw.println(" Device owner id:" + mDeviceOwnerUserId);
Zoltan Szatmary-Bane7834602016-04-08 18:41:11 +01004051 pw.println();
Makoto Onuki1a2cd742015-11-16 13:51:27 -08004052 pw.println(" Guest restrictions:");
Fyodor Kupolove80085d2015-11-06 18:21:39 -08004053 synchronized (mGuestRestrictions) {
Makoto Onuki1a2cd742015-11-16 13:51:27 -08004054 UserRestrictionsUtils.dumpRestrictions(pw, " ", mGuestRestrictions);
Fyodor Kupolove80085d2015-11-06 18:21:39 -08004055 }
Makoto Onukie7927da2015-11-25 10:05:17 -08004056 synchronized (mUsersLock) {
4057 pw.println();
4058 pw.println(" Device managed: " + mIsDeviceManaged);
Fyodor Kupolov0f4533d2016-05-18 18:43:12 -07004059 if (mRemovingUserIds.size() > 0) {
4060 pw.println();
4061 pw.println(" Recently removed userIds: " + mRecentlyRemovedIds);
4062 }
Makoto Onukie7927da2015-11-25 10:05:17 -08004063 }
Amith Yamasaniea1b9d72016-05-27 15:57:38 +00004064 synchronized (mUserStates) {
4065 pw.println(" Started users state: " + mUserStates);
4066 }
Felipe Lemed7b88382019-06-12 17:40:53 -07004067 } // synchronized (mPackagesLock)
4068
4069 // Dump some capabilities
4070 pw.println();
Felipe Lemec1ca4412019-09-11 09:23:26 -07004071 pw.print(" Max users: " + UserManager.getMaxSupportedUsers());
4072 pw.println(" (limit reached: " + isUserLimitReached() + ")");
Felipe Lemed7b88382019-06-12 17:40:53 -07004073 pw.println(" Supports switchable users: " + UserManager.supportsMultipleUsers());
Felipe Lemec1ca4412019-09-11 09:23:26 -07004074 pw.println(" All guests ephemeral: " + areGuestUsersEphemeral());
Felipe Lemed7b88382019-06-12 17:40:53 -07004075 pw.println(" Is split-system user: " + UserManager.isSplitSystemUser());
Felipe Lemee5434c32019-08-13 09:28:33 -07004076 pw.println(" Is headless-system mode: " + UserManager.isHeadlessSystemUserMode());
4077 pw.println(" User version: " + mUserVersion);
Bookatz04d7ae52019-08-05 14:07:12 -07004078
4079 // Dump package whitelist
4080 pw.println();
4081 mSystemPackageInstaller.dump(pw);
Amith Yamasani920ace02012-09-20 22:15:37 -07004082 }
Fyodor Kupolov75d0ea82014-12-15 16:21:07 -08004083
Makoto Onuki73dded22017-12-20 13:14:48 +09004084 private static void dumpTimeAgo(PrintWriter pw, StringBuilder sb, long nowTime, long time) {
4085 if (time == 0) {
4086 pw.println("<unknown>");
4087 } else {
4088 sb.setLength(0);
4089 TimeUtils.formatDuration(nowTime - time, sb);
4090 sb.append(" ago");
4091 pw.println(sb);
4092 }
4093 }
4094
Fyodor Kupolov75d0ea82014-12-15 16:21:07 -08004095 final class MainHandler extends Handler {
4096
4097 @Override
4098 public void handleMessage(Message msg) {
4099 switch (msg.what) {
4100 case WRITE_USER_MSG:
4101 removeMessages(WRITE_USER_MSG, msg.obj);
4102 synchronized (mPackagesLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08004103 int userId = ((UserData) msg.obj).info.id;
4104 UserData userData = getUserDataNoChecks(userId);
4105 if (userData != null) {
4106 writeUserLP(userData);
Fyodor Kupolov75d0ea82014-12-15 16:21:07 -08004107 }
4108 }
4109 }
4110 }
4111 }
Amith Yamasanibb054c92015-07-09 14:16:27 -07004112
4113 /**
4114 * @param userId
4115 * @return whether the user has been initialized yet
4116 */
Bookatzf56f2582019-09-04 16:06:41 -07004117 boolean isUserInitialized(@UserIdInt int userId) {
Todd Kennedy0eb97382017-10-03 16:57:22 -07004118 return mLocalService.isUserInitialized(userId);
Amith Yamasanibb054c92015-07-09 14:16:27 -07004119 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07004120
4121 private class LocalService extends UserManagerInternal {
Makoto Onuki068c54a2015-10-13 14:34:03 -07004122 @Override
Bookatzf56f2582019-09-04 16:06:41 -07004123 public void setDevicePolicyUserRestrictions(@UserIdInt int userId,
4124 @Nullable Bundle restrictions, boolean isDeviceOwner, int cameraRestrictionScope) {
Pavel Grafov6a40f092016-10-25 15:46:51 +01004125 UserManagerService.this.setDevicePolicyUserRestrictionsInner(userId, restrictions,
4126 isDeviceOwner, cameraRestrictionScope);
Makoto Onuki068c54a2015-10-13 14:34:03 -07004127 }
4128
4129 @Override
Bookatzf56f2582019-09-04 16:06:41 -07004130 public Bundle getBaseUserRestrictions(@UserIdInt int userId) {
Makoto Onuki068c54a2015-10-13 14:34:03 -07004131 synchronized (mRestrictionsLock) {
4132 return mBaseUserRestrictions.get(userId);
4133 }
4134 }
4135
4136 @Override
4137 public void setBaseUserRestrictionsByDpmsForMigration(
Bookatzf56f2582019-09-04 16:06:41 -07004138 @UserIdInt int userId, Bundle baseRestrictions) {
Makoto Onuki068c54a2015-10-13 14:34:03 -07004139 synchronized (mRestrictionsLock) {
Pavel Grafov6a40f092016-10-25 15:46:51 +01004140 if (updateRestrictionsIfNeededLR(
4141 userId, new Bundle(baseRestrictions), mBaseUserRestrictions)) {
4142 invalidateEffectiveUserRestrictionsLR(userId);
4143 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07004144 }
4145
Amith Yamasani12747872015-12-07 14:19:49 -08004146 final UserData userData = getUserDataNoChecks(userId);
Makoto Onuki068c54a2015-10-13 14:34:03 -07004147 synchronized (mPackagesLock) {
Amith Yamasani12747872015-12-07 14:19:49 -08004148 if (userData != null) {
4149 writeUserLP(userData);
Makoto Onuki068c54a2015-10-13 14:34:03 -07004150 } else {
4151 Slog.w(LOG_TAG, "UserInfo not found for " + userId);
4152 }
4153 }
4154 }
Makoto Onukid45a4a22015-11-02 17:17:38 -08004155
4156 @Override
Bookatzf56f2582019-09-04 16:06:41 -07004157 public boolean getUserRestriction(@UserIdInt int userId, String key) {
Makoto Onukid45a4a22015-11-02 17:17:38 -08004158 return getUserRestrictions(userId).getBoolean(key);
4159 }
4160
4161 @Override
4162 public void addUserRestrictionsListener(UserRestrictionsListener listener) {
4163 synchronized (mUserRestrictionsListeners) {
4164 mUserRestrictionsListeners.add(listener);
4165 }
4166 }
4167
4168 @Override
4169 public void removeUserRestrictionsListener(UserRestrictionsListener listener) {
4170 synchronized (mUserRestrictionsListeners) {
4171 mUserRestrictionsListeners.remove(listener);
4172 }
4173 }
Makoto Onukie7927da2015-11-25 10:05:17 -08004174
4175 @Override
4176 public void setDeviceManaged(boolean isManaged) {
4177 synchronized (mUsersLock) {
4178 mIsDeviceManaged = isManaged;
4179 }
4180 }
4181
4182 @Override
Rubin Xu0f1e56d2019-08-23 13:34:25 +01004183 public boolean isDeviceManaged() {
4184 synchronized (mUsersLock) {
4185 return mIsDeviceManaged;
4186 }
4187 }
4188
4189 @Override
Bookatzf56f2582019-09-04 16:06:41 -07004190 public void setUserManaged(@UserIdInt int userId, boolean isManaged) {
Makoto Onukie7927da2015-11-25 10:05:17 -08004191 synchronized (mUsersLock) {
4192 mIsUserManaged.put(userId, isManaged);
4193 }
4194 }
Oleksandr Peletskyi7f1f1df2016-01-18 15:40:21 +01004195
4196 @Override
Rubin Xu0f1e56d2019-08-23 13:34:25 +01004197 public boolean isUserManaged(@UserIdInt int userId) {
4198 synchronized (mUsersLock) {
4199 return mIsUserManaged.get(userId);
4200 }
4201 }
4202
4203 @Override
Bookatzf56f2582019-09-04 16:06:41 -07004204 public void setUserIcon(@UserIdInt int userId, Bitmap bitmap) {
Oleksandr Peletskyi7f1f1df2016-01-18 15:40:21 +01004205 long ident = Binder.clearCallingIdentity();
4206 try {
4207 synchronized (mPackagesLock) {
4208 UserData userData = getUserDataNoChecks(userId);
4209 if (userData == null || userData.info.partial) {
4210 Slog.w(LOG_TAG, "setUserIcon: unknown user #" + userId);
4211 return;
4212 }
4213 writeBitmapLP(userData.info, bitmap);
4214 writeUserLP(userData);
4215 }
4216 sendUserInfoChangedBroadcast(userId);
4217 } finally {
4218 Binder.restoreCallingIdentity(ident);
4219 }
4220 }
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +01004221
4222 @Override
4223 public void setForceEphemeralUsers(boolean forceEphemeralUsers) {
4224 synchronized (mUsersLock) {
4225 mForceEphemeralUsers = forceEphemeralUsers;
4226 }
4227 }
4228
4229 @Override
4230 public void removeAllUsers() {
4231 if (UserHandle.USER_SYSTEM == ActivityManager.getCurrentUser()) {
4232 // Remove the non-system users straight away.
4233 removeNonSystemUsers();
4234 } else {
4235 // Switch to the system user first and then remove the other users.
4236 BroadcastReceiver userSwitchedReceiver = new BroadcastReceiver() {
4237 @Override
4238 public void onReceive(Context context, Intent intent) {
4239 int userId =
4240 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
4241 if (userId != UserHandle.USER_SYSTEM) {
4242 return;
4243 }
4244 mContext.unregisterReceiver(this);
4245 removeNonSystemUsers();
4246 }
4247 };
4248 IntentFilter userSwitchedFilter = new IntentFilter();
4249 userSwitchedFilter.addAction(Intent.ACTION_USER_SWITCHED);
4250 mContext.registerReceiver(
4251 userSwitchedReceiver, userSwitchedFilter, null, mHandler);
4252
4253 // Switch to the system user.
4254 ActivityManager am =
4255 (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
4256 am.switchUser(UserHandle.USER_SYSTEM);
4257 }
4258 }
phweisse9c44062016-02-10 12:57:38 +01004259
4260 @Override
Bookatzf56f2582019-09-04 16:06:41 -07004261 public void onEphemeralUserStop(@UserIdInt int userId) {
Lenka Trochtova1ddda472016-02-12 10:42:12 +01004262 synchronized (mUsersLock) {
4263 UserInfo userInfo = getUserInfoLU(userId);
4264 if (userInfo != null && userInfo.isEphemeral()) {
4265 // Do not allow switching back to the ephemeral user again as the user is going
4266 // to be deleted.
4267 userInfo.flags |= UserInfo.FLAG_DISABLED;
4268 if (userInfo.isGuest()) {
4269 // Indicate that the guest will be deleted after it stops.
4270 userInfo.guestToRemove = true;
4271 }
4272 }
4273 }
4274 }
4275
4276 @Override
Alex Chaub6a9f942017-11-07 11:28:56 +08004277 public UserInfo createUserEvenWhenDisallowed(String name, int flags,
4278 String[] disallowedPackages) {
4279 UserInfo user = createUserInternalUnchecked(name, flags, UserHandle.USER_NULL,
Felipe Lemec1ca4412019-09-11 09:23:26 -07004280 /* preCreated= */ false, disallowedPackages);
phweisse9c44062016-02-10 12:57:38 +01004281 // Keep this in sync with UserManager.createUser
Christine Franks97a54802017-08-09 10:06:43 -07004282 if (user != null && !user.isAdmin() && !user.isDemo()) {
phweisse9c44062016-02-10 12:57:38 +01004283 setUserRestriction(UserManager.DISALLOW_SMS, true, user.id);
4284 setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, true, user.id);
4285 }
4286 return user;
4287 }
Fyodor Kupolov6c915ea2016-05-09 19:10:53 -07004288
4289 @Override
Bookatzf56f2582019-09-04 16:06:41 -07004290 public boolean removeUserEvenWhenDisallowed(@UserIdInt int userId) {
Nicolas Prevotdf1b87d2016-10-25 13:57:08 +01004291 return removeUserUnchecked(userId);
4292 }
4293
4294 @Override
Bookatzf56f2582019-09-04 16:06:41 -07004295 public boolean isUserRunning(@UserIdInt int userId) {
Amith Yamasaniea1b9d72016-05-27 15:57:38 +00004296 synchronized (mUserStates) {
4297 return mUserStates.get(userId, -1) >= 0;
4298 }
4299 }
4300
4301 @Override
Bookatzf56f2582019-09-04 16:06:41 -07004302 public void setUserState(@UserIdInt int userId, int userState) {
Amith Yamasaniea1b9d72016-05-27 15:57:38 +00004303 synchronized (mUserStates) {
4304 mUserStates.put(userId, userState);
4305 }
4306 }
4307
4308 @Override
Bookatzf56f2582019-09-04 16:06:41 -07004309 public void removeUserState(@UserIdInt int userId) {
Amith Yamasaniea1b9d72016-05-27 15:57:38 +00004310 synchronized (mUserStates) {
4311 mUserStates.delete(userId);
Fyodor Kupolov6c915ea2016-05-09 19:10:53 -07004312 }
4313 }
4314
4315 @Override
Michael Wachenschwanz3f2b6552017-05-15 13:53:09 -07004316 public int[] getUserIds() {
4317 return UserManagerService.this.getUserIds();
4318 }
4319
4320 @Override
Bookatzf56f2582019-09-04 16:06:41 -07004321 public boolean isUserUnlockingOrUnlocked(@UserIdInt int userId) {
Fyodor Kupolov0468ee92017-05-25 17:06:17 -07004322 int state;
Amith Yamasaniea1b9d72016-05-27 15:57:38 +00004323 synchronized (mUserStates) {
Fyodor Kupolov0468ee92017-05-25 17:06:17 -07004324 state = mUserStates.get(userId, -1);
Fyodor Kupolov6c915ea2016-05-09 19:10:53 -07004325 }
Fyodor Kupolov0468ee92017-05-25 17:06:17 -07004326 // Special case, in the stopping/shutdown state user key can still be unlocked
4327 if (state == UserState.STATE_STOPPING || state == UserState.STATE_SHUTDOWN) {
4328 return StorageManager.isUserKeyUnlocked(userId);
4329 }
4330 return (state == UserState.STATE_RUNNING_UNLOCKING)
4331 || (state == UserState.STATE_RUNNING_UNLOCKED);
Fyodor Kupolov6c915ea2016-05-09 19:10:53 -07004332 }
Fyodor Kupolov2e7e0962016-12-01 18:09:17 -08004333
4334 @Override
Bookatzf56f2582019-09-04 16:06:41 -07004335 public boolean isUserUnlocked(@UserIdInt int userId) {
Fyodor Kupolov0468ee92017-05-25 17:06:17 -07004336 int state;
Fyodor Kupolov2e7e0962016-12-01 18:09:17 -08004337 synchronized (mUserStates) {
Fyodor Kupolov0468ee92017-05-25 17:06:17 -07004338 state = mUserStates.get(userId, -1);
Fyodor Kupolov2e7e0962016-12-01 18:09:17 -08004339 }
Fyodor Kupolov0468ee92017-05-25 17:06:17 -07004340 // Special case, in the stopping/shutdown state user key can still be unlocked
4341 if (state == UserState.STATE_STOPPING || state == UserState.STATE_SHUTDOWN) {
4342 return StorageManager.isUserKeyUnlocked(userId);
4343 }
4344 return state == UserState.STATE_RUNNING_UNLOCKED;
Fyodor Kupolov2e7e0962016-12-01 18:09:17 -08004345 }
Todd Kennedy0eb97382017-10-03 16:57:22 -07004346
4347 @Override
Bookatzf56f2582019-09-04 16:06:41 -07004348 public boolean isUserInitialized(@UserIdInt int userId) {
Todd Kennedy0eb97382017-10-03 16:57:22 -07004349 return (getUserInfo(userId).flags & UserInfo.FLAG_INITIALIZED) != 0;
4350 }
4351
4352 @Override
Bookatzf56f2582019-09-04 16:06:41 -07004353 public boolean exists(@UserIdInt int userId) {
Todd Kennedy0eb97382017-10-03 16:57:22 -07004354 return getUserInfoNoChecks(userId) != null;
4355 }
Sunny Goyal145c8f82018-02-15 14:27:09 -08004356
4357 @Override
4358 public boolean isProfileAccessible(int callingUserId, int targetUserId, String debugMsg,
4359 boolean throwSecurityException) {
4360 if (targetUserId == callingUserId) {
4361 return true;
4362 }
4363 synchronized (mUsersLock) {
4364 UserInfo callingUserInfo = getUserInfoLU(callingUserId);
4365 if (callingUserInfo == null || callingUserInfo.isManagedProfile()) {
4366 if (throwSecurityException) {
4367 throw new SecurityException(
4368 debugMsg + " for another profile "
4369 + targetUserId + " from " + callingUserId);
4370 }
4371 }
4372
4373 UserInfo targetUserInfo = getUserInfoLU(targetUserId);
4374 if (targetUserInfo == null || !targetUserInfo.isEnabled()) {
4375 // Do not throw any exception here as this could happen due to race conditions
4376 // between the system updating its state and the client getting notified.
4377 if (throwSecurityException) {
4378 Slog.w(LOG_TAG, debugMsg + " for disabled profile "
4379 + targetUserId + " from " + callingUserId);
4380 }
4381 return false;
4382 }
4383
4384 if (targetUserInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID ||
4385 targetUserInfo.profileGroupId != callingUserInfo.profileGroupId) {
4386 if (throwSecurityException) {
4387 throw new SecurityException(
4388 debugMsg + " for unrelated profile " + targetUserId);
4389 }
4390 return false;
4391 }
4392 }
4393 return true;
4394 }
4395
4396 @Override
Bookatzf56f2582019-09-04 16:06:41 -07004397 public int getProfileParentId(@UserIdInt int userId) {
Sunny Goyal145c8f82018-02-15 14:27:09 -08004398 synchronized (mUsersLock) {
4399 UserInfo profileParent = getProfileParentLU(userId);
4400 if (profileParent == null) {
4401 return userId;
4402 }
4403 return profileParent.id;
4404 }
4405 }
yuemingw1d13eae2018-01-30 17:27:54 +00004406
4407 @Override
4408 public boolean isSettingRestrictedForUser(String setting, @UserIdInt int userId,
4409 String value, int callingUid) {
4410 return UserRestrictionsUtils.isSettingRestrictedForUser(mContext, setting, userId,
4411 value, callingUid);
4412 }
Patrick Baumann2f2fd712019-07-31 15:18:53 -07004413
4414 @Override
Bookatzf56f2582019-09-04 16:06:41 -07004415 public boolean hasUserRestriction(String restrictionKey, @UserIdInt int userId) {
Patrick Baumann2f2fd712019-07-31 15:18:53 -07004416 if (!UserRestrictionsUtils.isValidRestriction(restrictionKey)) {
4417 return false;
4418 }
4419 Bundle restrictions = getEffectiveUserRestrictions(userId);
4420 return restrictions != null && restrictions.getBoolean(restrictionKey);
4421 }
Felipe Lemee5434c32019-08-13 09:28:33 -07004422
Rubin Xu0f1e56d2019-08-23 13:34:25 +01004423 @Override
Felipe Lemee5434c32019-08-13 09:28:33 -07004424 public @Nullable UserInfo getUserInfo(@UserIdInt int userId) {
4425 UserData userData;
4426 synchronized (mUsersLock) {
4427 userData = mUsers.get(userId);
4428 }
4429 return userData == null ? null : userData.info;
4430 }
Felipe Leme987655d2019-08-26 10:45:24 -07004431
4432 public @NonNull UserInfo[] getUserInfos() {
4433 synchronized (mUsersLock) {
4434 int userSize = mUsers.size();
4435 UserInfo[] allInfos = new UserInfo[userSize];
4436 for (int i = 0; i < userSize; i++) {
4437 allInfos[i] = mUsers.valueAt(i).info;
4438 }
4439 return allInfos;
4440 }
4441 }
Lenka Trochtovaf348e8e2016-01-07 17:20:34 +01004442 }
4443
4444 /* Remove all the users except of the system one. */
4445 private void removeNonSystemUsers() {
4446 ArrayList<UserInfo> usersToRemove = new ArrayList<>();
4447 synchronized (mUsersLock) {
4448 final int userSize = mUsers.size();
4449 for (int i = 0; i < userSize; i++) {
4450 UserInfo ui = mUsers.valueAt(i).info;
4451 if (ui.id != UserHandle.USER_SYSTEM) {
4452 usersToRemove.add(ui);
4453 }
4454 }
4455 }
4456 for (UserInfo ui: usersToRemove) {
4457 removeUser(ui.id);
4458 }
Makoto Onuki068c54a2015-10-13 14:34:03 -07004459 }
Todd Kennedy60459ab2015-10-30 11:32:16 -07004460
4461 private class Shell extends ShellCommand {
4462 @Override
4463 public int onCommand(String cmd) {
4464 return onShellCommand(this, cmd);
4465 }
4466
4467 @Override
4468 public void onHelp() {
4469 final PrintWriter pw = getOutPrintWriter();
4470 pw.println("User manager (user) commands:");
4471 pw.println(" help");
4472 pw.println(" Print this help text.");
4473 pw.println("");
Felipe Lemec1ca4412019-09-11 09:23:26 -07004474 pw.println(" list [-v] [-all]");
Todd Kennedy60459ab2015-10-30 11:32:16 -07004475 pw.println(" Prints all users on the system.");
4476 }
4477 }
Makoto Onuki1a2cd742015-11-16 13:51:27 -08004478
4479 private static void debug(String message) {
4480 Log.d(LOG_TAG, message +
4481 (DBG_WITH_STACKTRACE ? " called at\n" + Debug.getCallers(10, " ") : ""));
4482 }
Kenny Guy02c89902016-11-15 19:36:38 +00004483
4484 @VisibleForTesting
4485 static int getMaxManagedProfiles() {
4486 // Allow overriding max managed profiles on debuggable builds for testing
4487 // of multiple profiles.
4488 if (!Build.IS_DEBUGGABLE) {
4489 return MAX_MANAGED_PROFILES;
4490 } else {
4491 return SystemProperties.getInt("persist.sys.max_profiles",
4492 MAX_MANAGED_PROFILES);
4493 }
4494 }
4495
Andreas Gampe2e8c7672018-07-20 13:01:08 -07004496 @GuardedBy("mUsersLock")
Kenny Guy02c89902016-11-15 19:36:38 +00004497 @VisibleForTesting
4498 int getFreeProfileBadgeLU(int parentUserId) {
4499 int maxManagedProfiles = getMaxManagedProfiles();
4500 boolean[] usedBadges = new boolean[maxManagedProfiles];
4501 final int userSize = mUsers.size();
4502 for (int i = 0; i < userSize; i++) {
4503 UserInfo ui = mUsers.valueAt(i).info;
4504 // Check which badge indexes are already used by this profile group.
4505 if (ui.isManagedProfile()
4506 && ui.profileGroupId == parentUserId
4507 && !mRemovingUserIds.get(ui.id)
4508 && ui.profileBadge < maxManagedProfiles) {
4509 usedBadges[ui.profileBadge] = true;
4510 }
4511 }
4512 for (int i = 0; i < maxManagedProfiles; i++) {
4513 if (!usedBadges[i]) {
4514 return i;
4515 }
4516 }
4517 return 0;
4518 }
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07004519
4520 /**
4521 * Checks if the given user has a managed profile associated with it.
4522 * @param userId The parent user
4523 * @return
4524 */
Bookatzf56f2582019-09-04 16:06:41 -07004525 boolean hasManagedProfile(@UserIdInt int userId) {
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07004526 synchronized (mUsersLock) {
4527 UserInfo userInfo = getUserInfoLU(userId);
4528 final int userSize = mUsers.size();
4529 for (int i = 0; i < userSize; i++) {
4530 UserInfo profile = mUsers.valueAt(i).info;
4531 if (userId != profile.id && isProfileOf(userInfo, profile)) {
4532 return true;
4533 }
4534 }
4535 return false;
4536 }
4537 }
Tony Makd390ae92017-12-28 13:23:10 +00004538
4539 /**
4540 * Check if the calling package name matches with the calling UID, throw
4541 * {@link SecurityException} if not.
4542 */
4543 private void verifyCallingPackage(String callingPackage, int callingUid) {
4544 int packageUid = mPm.getPackageUid(callingPackage, 0, UserHandle.getUserId(callingUid));
4545 if (packageUid != callingUid) {
4546 throw new SecurityException("Specified package " + callingPackage
4547 + " does not match the calling uid " + callingUid);
4548 }
4549 }
Amith Yamasani4b2e9342011-03-31 12:38:53 -07004550}