blob: 778bdb3077cf3e5cb633a56b5bbebcf3c51c3870 [file] [log] [blame]
Ying Zhengd3cb98e2018-05-11 11:42:48 -07001/*
2 * Copyright (C) 2018 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.car.user;
18
Eric Jeong1545f3b2019-09-16 13:56:52 -070019import static com.android.car.CarLog.TAG_USER;
20
21import android.annotation.NonNull;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070022import android.annotation.Nullable;
Eric Jeong1545f3b2019-09-16 13:56:52 -070023import android.annotation.UserIdInt;
Keun young Parkfb656372019-03-12 18:37:55 -070024import android.app.ActivityManager;
25import android.app.IActivityManager;
Eric Jeong1545f3b2019-09-16 13:56:52 -070026import android.car.ICarUserService;
jovanak24470652018-09-11 17:51:57 -070027import android.car.settings.CarSettings;
Eric Jeong3a793b02019-09-30 16:12:53 -070028import android.car.userlib.CarUserManagerHelper;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070029import android.content.Context;
Eric Jeong1545f3b2019-09-16 13:56:52 -070030import android.content.pm.UserInfo;
Anthony Hugh6fed1e92019-10-22 16:22:03 -070031import android.graphics.Bitmap;
Ying Zheng1ab32b62018-06-26 12:47:26 -070032import android.location.LocationManager;
Eric Jeong1545f3b2019-09-16 13:56:52 -070033import android.os.Binder;
Keun young Parkfb656372019-03-12 18:37:55 -070034import android.os.RemoteException;
Ying Zhengcf20f442018-06-22 16:54:51 -070035import android.os.UserHandle;
Ying Zheng8f90edb2018-06-13 12:42:31 -070036import android.os.UserManager;
jovanak24470652018-09-11 17:51:57 -070037import android.provider.Settings;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070038import android.util.Log;
39
40import com.android.car.CarServiceBase;
Keun-young Parkd462a912019-02-11 08:53:42 -080041import com.android.internal.annotations.GuardedBy;
Keun young Parkf3523cd2019-04-08 10:09:17 -070042import com.android.internal.annotations.VisibleForTesting;
Eric Jeong1545f3b2019-09-16 13:56:52 -070043import com.android.internal.util.Preconditions;
Anthony Hugh6fed1e92019-10-22 16:22:03 -070044import com.android.internal.util.UserIcons;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070045
46import java.io.PrintWriter;
Keun-young Parkd462a912019-02-11 08:53:42 -080047import java.util.ArrayList;
felipeal2d0483c2019-11-02 14:07:22 -070048import java.util.Arrays;
Eric Jeong1545f3b2019-09-16 13:56:52 -070049import java.util.Iterator;
50import java.util.List;
Pavel Maltsev17e81832019-04-04 14:38:41 -070051import java.util.concurrent.CopyOnWriteArrayList;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070052
53/**
54 * User service for cars. Manages users at boot time. Including:
55 *
56 * <ol>
Eric Jeong1545f3b2019-09-16 13:56:52 -070057 * <li> Creates a user used as driver.
58 * <li> Creates a user used as passenger.
Ying Zhengd3cb98e2018-05-11 11:42:48 -070059 * <li> Creates a secondary admin user on first run.
Eric Jeong1545f3b2019-09-16 13:56:52 -070060 * <li> Switch drivers.
Ying Zhengd3cb98e2018-05-11 11:42:48 -070061 * <ol/>
62 */
Eric Jeong1545f3b2019-09-16 13:56:52 -070063public final class CarUserService extends ICarUserService.Stub implements CarServiceBase {
Ying Zhengd3cb98e2018-05-11 11:42:48 -070064 private final Context mContext;
Eric Jeong3a793b02019-09-30 16:12:53 -070065 private final CarUserManagerHelper mCarUserManagerHelper;
Keun young Parkfb656372019-03-12 18:37:55 -070066 private final IActivityManager mAm;
Anthony Hugh9932a252019-06-12 16:19:56 -070067 private final UserManager mUserManager;
68 private final int mMaxRunningUsers;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070069
Keun-young Parkd462a912019-02-11 08:53:42 -080070 private final Object mLock = new Object();
71 @GuardedBy("mLock")
72 private boolean mUser0Unlocked;
73 @GuardedBy("mLock")
74 private final ArrayList<Runnable> mUser0UnlockTasks = new ArrayList<>();
Keun young Parkf3523cd2019-04-08 10:09:17 -070075 /**
76 * Background users that will be restarted in garage mode. This list can include the
77 * current foreground user bit the current foreground user should not be restarted.
78 */
Keun young Parkfb656372019-03-12 18:37:55 -070079 @GuardedBy("mLock")
Keun young Parkf3523cd2019-04-08 10:09:17 -070080 private final ArrayList<Integer> mBackgroundUsersToRestart = new ArrayList<>();
81 /**
82 * Keep the list of background users started here. This is wholly for debugging purpose.
83 */
84 @GuardedBy("mLock")
85 private final ArrayList<Integer> mBackgroundUsersRestartedHere = new ArrayList<>();
86
Pavel Maltsev17e81832019-04-04 14:38:41 -070087 private final CopyOnWriteArrayList<UserCallback> mUserCallbacks = new CopyOnWriteArrayList<>();
88
89 /** Interface for callbacks related to user activities. */
90 public interface UserCallback {
91 /** Gets called when user lock status has been changed. */
Eric Jeong1545f3b2019-09-16 13:56:52 -070092 void onUserLockChanged(@UserIdInt int userId, boolean unlocked);
Pavel Maltsev17e81832019-04-04 14:38:41 -070093 /** Called when new foreground user started to boot. */
Eric Jeong1545f3b2019-09-16 13:56:52 -070094 void onSwitchUser(@UserIdInt int userId);
Pavel Maltsev17e81832019-04-04 14:38:41 -070095 }
96
Eric Jeong3a793b02019-09-30 16:12:53 -070097 public CarUserService(
98 @NonNull Context context, @NonNull CarUserManagerHelper carUserManagerHelper,
99 @NonNull UserManager userManager, @NonNull IActivityManager am, int maxRunningUsers) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700100 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
101 Log.d(TAG_USER, "constructed");
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700102 }
103 mContext = context;
Eric Jeong3a793b02019-09-30 16:12:53 -0700104 mCarUserManagerHelper = carUserManagerHelper;
Keun young Parkf3523cd2019-04-08 10:09:17 -0700105 mAm = am;
106 mMaxRunningUsers = maxRunningUsers;
Anthony Hugh9932a252019-06-12 16:19:56 -0700107 mUserManager = userManager;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700108 }
109
110 @Override
111 public void init() {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700112 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
113 Log.d(TAG_USER, "init");
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700114 }
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700115 }
116
117 @Override
118 public void release() {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700119 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
120 Log.d(TAG_USER, "release");
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700121 }
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700122 }
123
124 @Override
Eric Jeong1545f3b2019-09-16 13:56:52 -0700125 public void dump(@NonNull PrintWriter writer) {
felipeal2d0483c2019-11-02 14:07:22 -0700126 checkAtLeastOnePermission("dump()", android.Manifest.permission.DUMP);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700127 writer.println("*CarUserService*");
Keun-young Parkd462a912019-02-11 08:53:42 -0800128 synchronized (mLock) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700129 writer.println("User0Unlocked: " + mUser0Unlocked);
130 writer.println("MaxRunningUsers: " + mMaxRunningUsers);
131 writer.println("BackgroundUsersToRestart: " + mBackgroundUsersToRestart);
132 writer.println("BackgroundUsersRestarted: " + mBackgroundUsersRestartedHere);
felipeal2d0483c2019-11-02 14:07:22 -0700133 List<UserInfo> allDrivers = getAllDrivers();
134 int driversSize = allDrivers.size();
135 writer.println("NumberOfDrivers: " + driversSize);
136 String prefix = " ";
137 for (int i = 0; i < driversSize; i++) {
138 int driverId = allDrivers.get(i).id;
139 writer.print(prefix + "#" + i + ": id=" + driverId);
140 List<UserInfo> passengers = getPassengers(driverId);
141 int passengersSize = passengers.size();
142 writer.print(" NumberPassengers: " + passengersSize);
143 if (passengersSize > 0) {
144 writer.print(" [");
145 for (int j = 0; j < passengersSize; j++) {
146 writer.print(passengers.get(j).id);
147 if (j < passengersSize - 1) {
148 writer.print(" ");
149 }
150 }
151 writer.print("]");
152 }
153 writer.println();
154 }
Keun-young Parkd462a912019-02-11 08:53:42 -0800155 }
Eric Jeong1545f3b2019-09-16 13:56:52 -0700156 }
157
158 /**
159 * @see CarUserManager.createDriver
160 */
161 @Override
162 @Nullable
163 public UserInfo createDriver(@NonNull String name, boolean admin) {
164 checkManageUsersPermission("createDriver");
165 Preconditions.checkNotNull(name, "name cannot be null");
166 if (admin) {
167 return createNewAdminUser(name);
168 }
Eric Jeong3a793b02019-09-30 16:12:53 -0700169 return mCarUserManagerHelper.createNewNonAdminUser(name);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700170 }
171
172 /**
173 * @see CarUserManager.createPassenger
174 */
175 @Override
176 @Nullable
177 public UserInfo createPassenger(@NonNull String name, @UserIdInt int driverId) {
178 checkManageUsersPermission("createPassenger");
179 Preconditions.checkNotNull(name, "name cannot be null");
180 UserInfo driver = mUserManager.getUserInfo(driverId);
181 if (driver == null) {
182 Log.w(TAG_USER, "the driver is invalid");
183 return null;
184 }
185 if (driver.isGuest()) {
186 Log.w(TAG_USER, "a guest driver cannot create a passenger");
187 return null;
188 }
189 UserInfo user = mUserManager.createProfileForUser(name, UserInfo.FLAG_MANAGED_PROFILE,
190 driverId);
191 if (user == null) {
192 // Couldn't create user, most likely because there are too many.
193 Log.w(TAG_USER, "can't create a profile for user" + driverId);
194 return null;
195 }
196 // Passenger user should be a non-admin user.
Eric Jeong3a793b02019-09-30 16:12:53 -0700197 mCarUserManagerHelper.setDefaultNonAdminRestrictions(user, /* enable= */ true);
Anthony Hugh6fed1e92019-10-22 16:22:03 -0700198 assignDefaultIcon(user);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700199 return user;
200 }
201
202 /**
203 * @see CarUserManager.switchDriver
204 */
205 @Override
206 public boolean switchDriver(@UserIdInt int driverId) {
207 checkManageUsersPermission("switchDriver");
208 if (driverId == UserHandle.USER_SYSTEM && UserManager.isHeadlessSystemUserMode()) {
209 // System user doesn't associate with real person, can not be switched to.
210 Log.w(TAG_USER, "switching to system user in headless system user mode is not allowed");
211 return false;
212 }
213 int userSwitchable = mUserManager.getUserSwitchability();
214 if (userSwitchable != UserManager.SWITCHABILITY_STATUS_OK) {
215 Log.w(TAG_USER, "current process is not allowed to switch user");
216 return false;
217 }
Anthony Hughfbb67762019-10-15 12:54:54 -0700218 if (driverId == ActivityManager.getCurrentUser()) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700219 // The current user is already the given user.
220 return true;
221 }
222 try {
223 return mAm.switchUser(driverId);
224 } catch (RemoteException e) {
225 // ignore
226 Log.w(TAG_USER, "error while switching user", e);
227 }
228 return false;
229 }
230
231 /**
232 * @see CarUserManager.getAllDrivers
233 */
234 @Override
235 @NonNull
236 public List<UserInfo> getAllDrivers() {
felipeal2d0483c2019-11-02 14:07:22 -0700237 checkManageUsersOrDumpPermission("getAllDrivers");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700238 return getUsers((user) -> {
239 return !isSystemUser(user.id) && user.isEnabled() && !user.isManagedProfile()
240 && !user.isEphemeral();
241 });
242 }
243
244 /**
245 * @see CarUserManager.getPassengers
Eric Jeong1545f3b2019-09-16 13:56:52 -0700246 */
247 @Override
248 @NonNull
249 public List<UserInfo> getPassengers(@UserIdInt int driverId) {
felipeal2d0483c2019-11-02 14:07:22 -0700250 checkManageUsersOrDumpPermission("getPassengers");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700251 return getUsers((user) -> {
252 return !isSystemUser(user.id) && user.isEnabled() && user.isManagedProfile()
253 && user.profileGroupId == driverId;
254 });
255 }
256
257 /**
258 * @see CarUserManager.startPassenger
259 */
260 @Override
261 public boolean startPassenger(@UserIdInt int passengerId, int zoneId) {
262 checkManageUsersPermission("startPassenger");
263 // TODO(b/139190199): this method will be implemented when dynamic profile group is enabled.
264 return false;
265 }
266
267 /**
268 * @see CarUserManager.stopPassenger
269 */
270 @Override
271 public boolean stopPassenger(@UserIdInt int passengerId) {
272 checkManageUsersPermission("stopPassenger");
273 // TODO(b/139190199): this method will be implemented when dynamic profile group is enabled.
274 return false;
275 }
276
277 /** Returns whether the given user is a system user. */
278 private static boolean isSystemUser(@UserIdInt int userId) {
279 return userId == UserHandle.USER_SYSTEM;
280 }
281
Keun young Park13a7a822019-04-04 15:53:08 -0700282 private void updateDefaultUserRestriction() {
283 // We want to set restrictions on system and guest users only once. These are persisted
284 // onto disk, so it's sufficient to do it once + we minimize the number of disk writes.
285 if (Settings.Global.getInt(mContext.getContentResolver(),
Eric Jeong1545f3b2019-09-16 13:56:52 -0700286 CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, /* default= */ 0) != 0) {
287 return;
Keun young Park13a7a822019-04-04 15:53:08 -0700288 }
Eric Jeong1545f3b2019-09-16 13:56:52 -0700289 // Only apply the system user restrictions if the system user is headless.
290 if (UserManager.isHeadlessSystemUserMode()) {
291 setSystemUserRestrictions();
292 }
Eric Jeong3a793b02019-09-30 16:12:53 -0700293 mCarUserManagerHelper.initDefaultGuestRestrictions();
Eric Jeong1545f3b2019-09-16 13:56:52 -0700294 Settings.Global.putInt(mContext.getContentResolver(),
295 CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, 1);
Keun young Park13a7a822019-04-04 15:53:08 -0700296 }
297
Eric Jeong1545f3b2019-09-16 13:56:52 -0700298 private boolean isPersistentUser(@UserIdInt int userId) {
Anthony Hugh9932a252019-06-12 16:19:56 -0700299 return !mUserManager.getUserInfo(userId).isEphemeral();
300 }
301
Eric Jeong1545f3b2019-09-16 13:56:52 -0700302 /** Adds callback to listen to user activity events. */
303 public void addUserCallback(@NonNull UserCallback callback) {
304 Preconditions.checkNotNull(callback, "callback cannot be null");
Pavel Maltsev17e81832019-04-04 14:38:41 -0700305 mUserCallbacks.add(callback);
306 }
307
Yabin Huang27712d72019-06-26 12:46:30 -0700308 /** Removes previously added callback to listen user events. */
Eric Jeong1545f3b2019-09-16 13:56:52 -0700309 public void removeUserCallback(@NonNull UserCallback callback) {
310 Preconditions.checkNotNull(callback, "callback cannot be null");
Pavel Maltsev38da4312019-04-08 10:38:38 -0700311 mUserCallbacks.remove(callback);
312 }
313
Keun-young Parkd462a912019-02-11 08:53:42 -0800314 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -0700315 * Sets user lock/unlocking status. This is coming from system server through ICar binder call.
316 *
317 * @param userId User id whoes lock status is changed.
318 * @param unlocked Unlocked (={@code true}) or locked (={@code false}).
Keun-young Parkd462a912019-02-11 08:53:42 -0800319 */
Eric Jeong1545f3b2019-09-16 13:56:52 -0700320 public void setUserLockStatus(@UserIdInt int userId, boolean unlocked) {
Pavel Maltsev17e81832019-04-04 14:38:41 -0700321 for (UserCallback callback : mUserCallbacks) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700322 callback.onUserLockChanged(userId, unlocked);
Pavel Maltsev17e81832019-04-04 14:38:41 -0700323 }
Keun young Parkf3523cd2019-04-08 10:09:17 -0700324 if (!unlocked) { // nothing else to do when it is locked back.
325 return;
326 }
Keun-young Parkd462a912019-02-11 08:53:42 -0800327 ArrayList<Runnable> tasks = null;
328 synchronized (mLock) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700329 if (userId == UserHandle.USER_SYSTEM) {
Keun young Parkf3523cd2019-04-08 10:09:17 -0700330 if (!mUser0Unlocked) { // user 0, unlocked, do this only once
331 updateDefaultUserRestriction();
332 tasks = new ArrayList<>(mUser0UnlockTasks);
333 mUser0UnlockTasks.clear();
334 mUser0Unlocked = unlocked;
335 }
336 } else { // none user0
Eric Jeong1545f3b2019-09-16 13:56:52 -0700337 Integer user = userId;
338 if (isPersistentUser(userId)) {
Keun young Parkf3523cd2019-04-08 10:09:17 -0700339 // current foreground user should stay in top priority.
Anthony Hughfbb67762019-10-15 12:54:54 -0700340 if (userId == ActivityManager.getCurrentUser()) {
Keun young Parkf3523cd2019-04-08 10:09:17 -0700341 mBackgroundUsersToRestart.remove(user);
342 mBackgroundUsersToRestart.add(0, user);
343 }
344 // -1 for user 0
345 if (mBackgroundUsersToRestart.size() > (mMaxRunningUsers - 1)) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700346 int userToDrop = mBackgroundUsersToRestart.get(
Keun young Parkf3523cd2019-04-08 10:09:17 -0700347 mBackgroundUsersToRestart.size() - 1);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700348 Log.i(TAG_USER, "New user unlocked:" + userId
Keun young Parkf3523cd2019-04-08 10:09:17 -0700349 + ", dropping least recently user from restart list:" + userToDrop);
350 // Drop the least recently used user.
351 mBackgroundUsersToRestart.remove(mBackgroundUsersToRestart.size() - 1);
352 }
353 }
Keun-young Parkd462a912019-02-11 08:53:42 -0800354 }
355 }
356 if (tasks != null && tasks.size() > 0) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700357 Log.d(TAG_USER, "User0 unlocked, run queued tasks:" + tasks.size());
Keun-young Parkd462a912019-02-11 08:53:42 -0800358 for (Runnable r : tasks) {
359 r.run();
360 }
361 }
362 }
363
364 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -0700365 * Starts all background users that were active in system.
366 *
Keun young Parkfb656372019-03-12 18:37:55 -0700367 * @return list of background users started successfully.
368 */
Eric Jeong1545f3b2019-09-16 13:56:52 -0700369 @NonNull
Keun young Parkfb656372019-03-12 18:37:55 -0700370 public ArrayList<Integer> startAllBackgroundUsers() {
371 ArrayList<Integer> users;
372 synchronized (mLock) {
Keun young Parkf3523cd2019-04-08 10:09:17 -0700373 users = new ArrayList<>(mBackgroundUsersToRestart);
374 mBackgroundUsersRestartedHere.clear();
375 mBackgroundUsersRestartedHere.addAll(mBackgroundUsersToRestart);
Keun young Parkfb656372019-03-12 18:37:55 -0700376 }
377 ArrayList<Integer> startedUsers = new ArrayList<>();
378 for (Integer user : users) {
Anthony Hughfbb67762019-10-15 12:54:54 -0700379 if (user == ActivityManager.getCurrentUser()) {
Keun young Parkfb656372019-03-12 18:37:55 -0700380 continue;
381 }
382 try {
383 if (mAm.startUserInBackground(user)) {
Keun young Parkf3523cd2019-04-08 10:09:17 -0700384 if (mUserManager.isUserUnlockingOrUnlocked(user)) {
385 // already unlocked / unlocking. No need to unlock.
Keun young Parkfb656372019-03-12 18:37:55 -0700386 startedUsers.add(user);
Keun young Parkf3523cd2019-04-08 10:09:17 -0700387 } else if (mAm.unlockUser(user, null, null, null)) {
388 startedUsers.add(user);
389 } else { // started but cannot unlock
Eric Jeong1545f3b2019-09-16 13:56:52 -0700390 Log.w(TAG_USER, "Background user started but cannot be unlocked:" + user);
Keun young Parkf3523cd2019-04-08 10:09:17 -0700391 if (mUserManager.isUserRunning(user)) {
392 // add to started list so that it can be stopped later.
393 startedUsers.add(user);
394 }
Keun young Parkfb656372019-03-12 18:37:55 -0700395 }
396 }
397 } catch (RemoteException e) {
398 // ignore
Eric Jeong1545f3b2019-09-16 13:56:52 -0700399 Log.w(TAG_USER, "error while starting user in background", e);
Keun young Parkfb656372019-03-12 18:37:55 -0700400 }
401 }
Keun young Parkf3523cd2019-04-08 10:09:17 -0700402 // Keep only users that were re-started in mBackgroundUsersRestartedHere
403 synchronized (mLock) {
404 ArrayList<Integer> usersToRemove = new ArrayList<>();
405 for (Integer user : mBackgroundUsersToRestart) {
406 if (!startedUsers.contains(user)) {
407 usersToRemove.add(user);
408 }
409 }
410 mBackgroundUsersRestartedHere.removeAll(usersToRemove);
411 }
Keun young Parkfb656372019-03-12 18:37:55 -0700412 return startedUsers;
413 }
414
415 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -0700416 * Stops all background users that were active in system.
417 *
418 * @return whether stopping succeeds.
Keun young Parkfb656372019-03-12 18:37:55 -0700419 */
Eric Jeong1545f3b2019-09-16 13:56:52 -0700420 public boolean stopBackgroundUser(@UserIdInt int userId) {
Keun young Parkf3523cd2019-04-08 10:09:17 -0700421 if (userId == UserHandle.USER_SYSTEM) {
422 return false;
423 }
Anthony Hughfbb67762019-10-15 12:54:54 -0700424 if (userId == ActivityManager.getCurrentUser()) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700425 Log.i(TAG_USER, "stopBackgroundUser, already a FG user:" + userId);
Keun young Parkfb656372019-03-12 18:37:55 -0700426 return false;
427 }
428 try {
429 int r = mAm.stopUser(userId, true, null);
Keun young Parkf3523cd2019-04-08 10:09:17 -0700430 if (r == ActivityManager.USER_OP_SUCCESS) {
431 synchronized (mLock) {
432 Integer user = userId;
433 mBackgroundUsersRestartedHere.remove(user);
434 }
435 } else if (r == ActivityManager.USER_OP_IS_CURRENT) {
436 return false;
437 } else {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700438 Log.i(TAG_USER, "stopBackgroundUser failed, user:" + userId + " err:" + r);
Keun young Parkfb656372019-03-12 18:37:55 -0700439 return false;
440 }
441 } catch (RemoteException e) {
442 // ignore
Eric Jeong1545f3b2019-09-16 13:56:52 -0700443 Log.w(TAG_USER, "error while stopping user", e);
Keun young Parkfb656372019-03-12 18:37:55 -0700444 }
445 return true;
446 }
447
448 /**
Pavel Maltsev17e81832019-04-04 14:38:41 -0700449 * Called when new foreground user started to boot.
450 *
Eric Jeong1545f3b2019-09-16 13:56:52 -0700451 * @param userId User id of new user.
Pavel Maltsev17e81832019-04-04 14:38:41 -0700452 */
Eric Jeong1545f3b2019-09-16 13:56:52 -0700453 public void onSwitchUser(@UserIdInt int userId) {
454 if (!isSystemUser(userId) && isPersistentUser(userId)) {
Eric Jeong3a793b02019-09-30 16:12:53 -0700455 mCarUserManagerHelper.setLastActiveUser(userId);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700456 }
Pavel Maltsev17e81832019-04-04 14:38:41 -0700457 for (UserCallback callback : mUserCallbacks) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700458 callback.onSwitchUser(userId);
Pavel Maltsev17e81832019-04-04 14:38:41 -0700459 }
460 }
461
462 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -0700463 * Runs the given runnable when user 0 is unlocked. If user 0 is already unlocked, it is
Keun-young Parkd462a912019-02-11 08:53:42 -0800464 * run inside this call.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700465 *
Keun-young Parkd462a912019-02-11 08:53:42 -0800466 * @param r Runnable to run.
467 */
Eric Jeong1545f3b2019-09-16 13:56:52 -0700468 public void runOnUser0Unlock(@NonNull Runnable r) {
469 Preconditions.checkNotNull(r, "runnable cannot be null");
Keun-young Parkd462a912019-02-11 08:53:42 -0800470 boolean runNow = false;
471 synchronized (mLock) {
472 if (mUser0Unlocked) {
473 runNow = true;
474 } else {
475 mUser0UnlockTasks.add(r);
476 }
477 }
478 if (runNow) {
479 r.run();
480 }
481 }
482
Keun young Parkf3523cd2019-04-08 10:09:17 -0700483 @VisibleForTesting
Eric Jeong1545f3b2019-09-16 13:56:52 -0700484 @NonNull
485 ArrayList<Integer> getBackgroundUsersToRestart() {
486 ArrayList<Integer> backgroundUsersToRestart = null;
Keun young Parkf3523cd2019-04-08 10:09:17 -0700487 synchronized (mLock) {
488 backgroundUsersToRestart = new ArrayList<>(mBackgroundUsersToRestart);
489 }
490 return backgroundUsersToRestart;
491 }
492
Ying Zheng1ab32b62018-06-26 12:47:26 -0700493 private void setSystemUserRestrictions() {
494 // Disable adding accounts for system user.
Anthony Hugh9932a252019-06-12 16:19:56 -0700495 UserHandle systemUserHandle = UserHandle.of(UserHandle.USER_SYSTEM);
496 mUserManager.setUserRestriction(
497 UserManager.DISALLOW_MODIFY_ACCOUNTS, /* value= */ true, systemUserHandle);
Ying Zheng1ab32b62018-06-26 12:47:26 -0700498
499 // Disable Location service for system user.
500 LocationManager locationManager =
501 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
Anthony Hugh9932a252019-06-12 16:19:56 -0700502 locationManager.setLocationEnabledForUser(/* enabled= */ false, systemUserHandle);
Ying Zheng1ab32b62018-06-26 12:47:26 -0700503 }
Eric Jeong1545f3b2019-09-16 13:56:52 -0700504
505 /**
506 * Creates a new user on the system, the created user would be granted admin role.
507 *
508 * @param name Name to be given to the newly created user.
Eric Jeong3a793b02019-09-30 16:12:53 -0700509 * @return newly created admin user, {@code null} if it fails to create a user.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700510 */
511 @Nullable
512 private UserInfo createNewAdminUser(String name) {
513 if (!(mUserManager.isAdminUser() || mUserManager.isSystemUser())) {
514 // Only admins or system user can create other privileged users.
515 Log.e(TAG_USER, "Only admin users and system user can create other admins.");
516 return null;
517 }
518
519 UserInfo user = mUserManager.createUser(name, UserInfo.FLAG_ADMIN);
520 if (user == null) {
521 // Couldn't create user, most likely because there are too many.
522 Log.w(TAG_USER, "can't create admin user.");
523 return null;
524 }
Anthony Hugh6fed1e92019-10-22 16:22:03 -0700525 assignDefaultIcon(user);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700526
527 return user;
528 }
529
Anthony Hugh6fed1e92019-10-22 16:22:03 -0700530 /**
531 * Assigns a default icon to a user according to the user's id.
532 *
533 * @param userInfo User whose avatar is set to default icon.
534 * @return Bitmap of the user icon.
535 */
536 private Bitmap assignDefaultIcon(UserInfo userInfo) {
537 int idForIcon = userInfo.isGuest() ? UserHandle.USER_NULL : userInfo.id;
538 Bitmap bitmap = UserIcons.convertToBitmap(
539 UserIcons.getDefaultUserIcon(mContext.getResources(), idForIcon, false));
540 mUserManager.setUserIcon(userInfo.id, bitmap);
541 return bitmap;
542 }
543
Eric Jeong1545f3b2019-09-16 13:56:52 -0700544 private interface UserFilter {
545 boolean isEligibleUser(UserInfo user);
546 }
547
548 /** Returns all users who are matched by the given filter. */
549 private List<UserInfo> getUsers(UserFilter filter) {
550 List<UserInfo> users = mUserManager.getUsers(/* excludeDying= */ true);
551
552 for (Iterator<UserInfo> iterator = users.iterator(); iterator.hasNext(); ) {
553 UserInfo user = iterator.next();
554 if (!filter.isEligibleUser(user)) {
555 iterator.remove();
556 }
557 }
558 return users;
559 }
560
561 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -0700562 * Enforces that apps which have the
563 * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS}
564 * can make certain calls to the CarUserManager.
565 *
566 * @param message used as message if SecurityException is thrown.
567 * @throws SecurityException if the caller is not system or root.
568 */
569 private static void checkManageUsersPermission(String message) {
felipeal2d0483c2019-11-02 14:07:22 -0700570 checkAtLeastOnePermission(message, android.Manifest.permission.MANAGE_USERS);
571 }
572
573 private static void checkManageUsersOrDumpPermission(String message) {
574 checkAtLeastOnePermission(message,
575 android.Manifest.permission.MANAGE_USERS,
576 android.Manifest.permission.DUMP);
577 }
578
579 private static void checkAtLeastOnePermission(String message, String...permissions) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700580 int callingUid = Binder.getCallingUid();
felipeal2d0483c2019-11-02 14:07:22 -0700581 if (!hasAtLeastOnePermissionGranted(callingUid, permissions)) {
582 throw new SecurityException("You need one of " + Arrays.toString(permissions)
583 + " to: " + message);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700584 }
585 }
586
felipeal2d0483c2019-11-02 14:07:22 -0700587 private static boolean hasAtLeastOnePermissionGranted(int uid, String... permissions) {
588 for (String permission : permissions) {
589 if (ActivityManager.checkComponentPermission(permission, uid, /* owningUid = */-1,
590 /* exported = */ true)
591 == android.content.pm.PackageManager.PERMISSION_GRANTED) {
592 return true;
593 }
594 }
595 return false;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700596 }
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700597}