blob: de5739aff32026ff8e480896171f9114debc9f46 [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
Felipe Leme17799202020-09-03 12:55:53 -070019import static android.Manifest.permission.CREATE_USERS;
20import static android.Manifest.permission.MANAGE_USERS;
Felipe Leme5d5ab142020-10-27 13:49:10 -070021import static android.car.drivingstate.CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP;
Felipe Leme17799202020-09-03 12:55:53 -070022
Felipe Leme55236722020-10-16 16:54:32 -070023import static com.android.car.PermissionHelper.checkHasAtLeastOnePermissionGranted;
24import static com.android.car.PermissionHelper.checkHasDumpPermissionGranted;
Eric Jeong1545f3b2019-09-16 13:56:52 -070025
26import android.annotation.NonNull;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070027import android.annotation.Nullable;
Eric Jeong1545f3b2019-09-16 13:56:52 -070028import android.annotation.UserIdInt;
Keun young Parkfb656372019-03-12 18:37:55 -070029import android.app.ActivityManager;
Louis Chang3bf2f202020-08-18 13:04:28 +080030import android.app.ActivityTaskManager.RootTaskInfo;
Keun young Parkfb656372019-03-12 18:37:55 -070031import android.app.IActivityManager;
Eric Jeongc91f9452019-08-30 15:04:21 -070032import android.car.CarOccupantZoneManager;
33import android.car.CarOccupantZoneManager.OccupantTypeEnum;
34import android.car.CarOccupantZoneManager.OccupantZoneInfo;
Eric Jeong1545f3b2019-09-16 13:56:52 -070035import android.car.ICarUserService;
Felipe Leme5d5ab142020-10-27 13:49:10 -070036import android.car.drivingstate.CarUxRestrictions;
Felipe Leme56ef9ad2020-11-05 18:39:03 -080037import android.car.drivingstate.ICarUxRestrictionsChangeListener;
jovanak24470652018-09-11 17:51:57 -070038import android.car.settings.CarSettings;
Felipe Leme5528ff72020-02-10 19:05:14 -080039import android.car.user.CarUserManager;
Mayank Garg3f566582020-10-02 22:10:16 -070040import android.car.user.CarUserManager.UserIdentificationAssociationSetValue;
41import android.car.user.CarUserManager.UserIdentificationAssociationType;
Antonio Kantekc8114752020-03-05 21:37:39 -080042import android.car.user.CarUserManager.UserLifecycleEvent;
43import android.car.user.CarUserManager.UserLifecycleListener;
felipealdfdf8512020-06-01 09:35:45 -070044import android.car.user.UserCreationResult;
felipeal159a2a42020-05-08 10:32:11 -070045import android.car.user.UserIdentificationAssociationResponse;
Mayank Garga55c3092020-05-28 03:19:24 -070046import android.car.user.UserRemovalResult;
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -070047import android.car.user.UserStartResult;
bkchoid77d0bc2021-04-22 13:43:03 -070048import android.car.user.UserStopResult;
felipeale5bf0322020-04-16 15:10:57 -070049import android.car.user.UserSwitchResult;
felipeal19e3d732020-03-18 12:07:32 -070050import android.car.userlib.HalCallback;
51import android.car.userlib.UserHalHelper;
Mayank Garge90a4082020-09-30 12:57:34 -070052import android.car.userlib.UserHelper;
Mayank Garga480dd92020-05-14 03:14:57 -070053import android.content.ComponentName;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070054import android.content.Context;
Mayank Garga480dd92020-05-14 03:14:57 -070055import android.content.pm.PackageManager;
56import android.content.pm.PackageManager.NameNotFoundException;
Eric Jeong1545f3b2019-09-16 13:56:52 -070057import android.content.pm.UserInfo;
felipealdfdf8512020-06-01 09:35:45 -070058import android.content.pm.UserInfo.UserInfoFlag;
Felipe Leme315a53b2020-03-12 10:51:04 -070059import android.content.res.Resources;
Anthony Hugh6fed1e92019-10-22 16:22:03 -070060import android.graphics.Bitmap;
felipealdfdf8512020-06-01 09:35:45 -070061import android.hardware.automotive.vehicle.V2_0.CreateUserRequest;
62import android.hardware.automotive.vehicle.V2_0.CreateUserStatus;
Mayank Garg70732a82020-08-05 20:17:47 -070063import android.hardware.automotive.vehicle.V2_0.InitialUserInfoRequestType;
Felipe Lemec6e3c2a2020-02-19 16:53:57 -080064import android.hardware.automotive.vehicle.V2_0.InitialUserInfoResponseAction;
Mayank Garga55c3092020-05-28 03:19:24 -070065import android.hardware.automotive.vehicle.V2_0.RemoveUserRequest;
Mayank Gargeb37d092020-06-02 14:37:57 -070066import android.hardware.automotive.vehicle.V2_0.SwitchUserRequest;
Mayank Garg59f22192020-03-27 00:51:45 -070067import android.hardware.automotive.vehicle.V2_0.SwitchUserStatus;
felipeal5e3ede42020-04-23 18:04:07 -070068import android.hardware.automotive.vehicle.V2_0.UserIdentificationGetRequest;
69import android.hardware.automotive.vehicle.V2_0.UserIdentificationResponse;
felipeal159a2a42020-05-08 10:32:11 -070070import android.hardware.automotive.vehicle.V2_0.UserIdentificationSetAssociation;
71import android.hardware.automotive.vehicle.V2_0.UserIdentificationSetRequest;
Felipe Lemec6e3c2a2020-02-19 16:53:57 -080072import android.hardware.automotive.vehicle.V2_0.UsersInfo;
Ying Zheng1ab32b62018-06-26 12:47:26 -070073import android.location.LocationManager;
Eric Jeong1545f3b2019-09-16 13:56:52 -070074import android.os.Binder;
Felipe Leme5528ff72020-02-10 19:05:14 -080075import android.os.Bundle;
Antonio Kantek7236a5b2020-04-06 19:53:55 -070076import android.os.Handler;
77import android.os.HandlerThread;
Felipe Leme17799202020-09-03 12:55:53 -070078import android.os.Process;
Keun young Parkfb656372019-03-12 18:37:55 -070079import android.os.RemoteException;
Mayank Garg31e73042020-01-23 00:10:38 -080080import android.os.Trace;
Ying Zhengcf20f442018-06-22 16:54:51 -070081import android.os.UserHandle;
Ying Zheng8f90edb2018-06-13 12:42:31 -070082import android.os.UserManager;
jovanak24470652018-09-11 17:51:57 -070083import android.provider.Settings;
Felipe Lemee3cab982020-03-12 11:39:29 -070084import android.sysprop.CarProperties;
felipeal159a2a42020-05-08 10:32:11 -070085import android.text.TextUtils;
felipeal312416a2020-04-14 12:28:24 -070086import android.util.EventLog;
Felipe Leme176a5fd2021-01-20 15:48:33 -080087import android.util.IndentingPrintWriter;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070088import android.util.Log;
Eric Jeongf75d4132020-12-21 13:48:23 -080089import android.util.Slog;
Felipe Leme5528ff72020-02-10 19:05:14 -080090import android.util.SparseArray;
Felipe Leme6b34fc32020-10-26 15:49:17 -070091import android.util.SparseBooleanArray;
Mayank Garg31e73042020-01-23 00:10:38 -080092import android.util.TimingsTraceLog;
Felipe Leme56ef9ad2020-11-05 18:39:03 -080093import android.view.Display;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070094
Mayank Garg72c71d22021-02-03 23:54:45 -080095import com.android.car.CarLog;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070096import com.android.car.CarServiceBase;
Keun young Parkb241d022020-04-20 20:31:34 -070097import com.android.car.CarServiceUtils;
Felipe Leme5d5ab142020-10-27 13:49:10 -070098import com.android.car.CarUxRestrictionsManagerService;
Eric Jeongc91f9452019-08-30 15:04:21 -070099import com.android.car.R;
Felipe Leme58412202020-01-09 13:45:33 -0800100import com.android.car.hal.UserHalService;
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800101import com.android.car.internal.ICarServiceHelper;
Mayank Gargf59f95b2020-10-01 14:55:11 -0700102import com.android.car.internal.common.CommonConstants.UserLifecycleEventType;
Mayank Garg801ea6a2020-09-29 15:43:49 -0700103import com.android.car.internal.common.EventLogTags;
104import com.android.car.internal.common.UserHelperLite;
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700105import com.android.car.power.CarPowerManagementService;
Mayank Garg665c20b2020-08-07 16:19:28 -0700106import com.android.car.user.InitialUserSetter.InitialUserInfo;
Keun-young Parkd462a912019-02-11 08:53:42 -0800107import com.android.internal.annotations.GuardedBy;
Keun young Parkf3523cd2019-04-08 10:09:17 -0700108import com.android.internal.annotations.VisibleForTesting;
felipeale5bf0322020-04-16 15:10:57 -0700109import com.android.internal.infra.AndroidFuture;
Felipe Leme5528ff72020-02-10 19:05:14 -0800110import com.android.internal.os.IResultReceiver;
felipeal5e3ede42020-04-23 18:04:07 -0700111import com.android.internal.util.ArrayUtils;
felipeal2a84d512020-04-06 18:52:15 -0700112import com.android.internal.util.FunctionalUtils;
Mayank Garge19c2922020-03-30 18:05:53 -0700113import com.android.internal.util.Preconditions;
Anthony Hugh6fed1e92019-10-22 16:22:03 -0700114import com.android.internal.util.UserIcons;
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -0700115import com.android.server.utils.Slogf;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700116
117import java.io.PrintWriter;
Keun-young Parkd462a912019-02-11 08:53:42 -0800118import java.util.ArrayList;
felipeal2d0483c2019-11-02 14:07:22 -0700119import java.util.Arrays;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700120import java.util.Iterator;
121import java.util.List;
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +0000122import java.util.Objects;
Pavel Maltsev17e81832019-04-04 14:38:41 -0700123import java.util.concurrent.CopyOnWriteArrayList;
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700124import java.util.concurrent.CountDownLatch;
125import java.util.concurrent.TimeUnit;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700126
127/**
128 * User service for cars. Manages users at boot time. Including:
129 *
130 * <ol>
Eric Jeong1545f3b2019-09-16 13:56:52 -0700131 * <li> Creates a user used as driver.
132 * <li> Creates a user used as passenger.
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700133 * <li> Creates a secondary admin user on first run.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700134 * <li> Switch drivers.
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700135 * <ol/>
136 */
Eric Jeong1545f3b2019-09-16 13:56:52 -0700137public final class CarUserService extends ICarUserService.Stub implements CarServiceBase {
Felipe Leme5528ff72020-02-10 19:05:14 -0800138
Mayank Garg72c71d22021-02-03 23:54:45 -0800139 private static final String TAG = CarLog.tagFor(CarUserService.class);
felipealf7368962020-04-16 12:55:19 -0700140
Felipe Lemeabbf2da2020-02-24 18:25:29 -0800141 /** {@code int} extra used to represent a user id in a {@link IResultReceiver} response. */
Mayank Garg8f932822020-09-17 16:09:12 -0700142 public static final String BUNDLE_USER_ID = "user.id";
Felipe Lemeabbf2da2020-02-24 18:25:29 -0800143 /** {@code int} extra used to represent user flags in a {@link IResultReceiver} response. */
Mayank Garg8f932822020-09-17 16:09:12 -0700144 public static final String BUNDLE_USER_FLAGS = "user.flags";
Felipe Lemeabbf2da2020-02-24 18:25:29 -0800145 /** {@code String} extra used to represent a user name in a {@link IResultReceiver} response. */
Mayank Garg8f932822020-09-17 16:09:12 -0700146 public static final String BUNDLE_USER_NAME = "user.name";
felipeala68ecef2020-05-19 12:46:08 -0700147 /**
148 * {@code int} extra used to represent the user locales in a {@link IResultReceiver} response.
149 */
Mayank Garg8f932822020-09-17 16:09:12 -0700150 public static final String BUNDLE_USER_LOCALES = "user.locales";
felipeala68ecef2020-05-19 12:46:08 -0700151 /**
152 * {@code int} extra used to represent the info action in a {@link IResultReceiver} response.
153 */
Mayank Garg8f932822020-09-17 16:09:12 -0700154 public static final String BUNDLE_INITIAL_INFO_ACTION = "initial_info.action";
Felipe Leme5528ff72020-02-10 19:05:14 -0800155
Mayank Garg9ed099e2020-06-04 16:05:20 -0700156 public static final String VEHICLE_HAL_NOT_SUPPORTED = "Vehicle Hal not supported.";
157
Mayank Garg02576972021-02-18 16:46:07 -0800158 public static final String HANDLER_THREAD_NAME = "UserService";
159
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700160 private final Context mContext;
Keun young Parkfb656372019-03-12 18:37:55 -0700161 private final IActivityManager mAm;
Anthony Hugh9932a252019-06-12 16:19:56 -0700162 private final UserManager mUserManager;
163 private final int mMaxRunningUsers;
Mayank Garg70732a82020-08-05 20:17:47 -0700164 private final InitialUserSetter mInitialUserSetter;
Eric Jeongc91f9452019-08-30 15:04:21 -0700165 private final boolean mEnablePassengerSupport;
Mayank Garg9732d602020-08-09 21:02:40 -0700166 private final UserPreCreator mUserPreCreator;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700167
Eric Jeongc91f9452019-08-30 15:04:21 -0700168 private final Object mLockUser = new Object();
169 @GuardedBy("mLockUser")
Keun-young Parkd462a912019-02-11 08:53:42 -0800170 private boolean mUser0Unlocked;
Eric Jeongc91f9452019-08-30 15:04:21 -0700171 @GuardedBy("mLockUser")
Keun-young Parkd462a912019-02-11 08:53:42 -0800172 private final ArrayList<Runnable> mUser0UnlockTasks = new ArrayList<>();
Eric Jeongc91f9452019-08-30 15:04:21 -0700173 // Only one passenger is supported.
174 @GuardedBy("mLockUser")
175 private @UserIdInt int mLastPassengerId;
Keun young Parkf3523cd2019-04-08 10:09:17 -0700176 /**
177 * Background users that will be restarted in garage mode. This list can include the
Mayank Garg31e73042020-01-23 00:10:38 -0800178 * current foreground user but the current foreground user should not be restarted.
Keun young Parkf3523cd2019-04-08 10:09:17 -0700179 */
Eric Jeongc91f9452019-08-30 15:04:21 -0700180 @GuardedBy("mLockUser")
Keun young Parkf3523cd2019-04-08 10:09:17 -0700181 private final ArrayList<Integer> mBackgroundUsersToRestart = new ArrayList<>();
182 /**
183 * Keep the list of background users started here. This is wholly for debugging purpose.
184 */
Eric Jeongc91f9452019-08-30 15:04:21 -0700185 @GuardedBy("mLockUser")
Keun young Parkf3523cd2019-04-08 10:09:17 -0700186 private final ArrayList<Integer> mBackgroundUsersRestartedHere = new ArrayList<>();
187
Felipe Leme58412202020-01-09 13:45:33 -0800188 private final UserHalService mHal;
189
Keun young Parkb241d022020-04-20 20:31:34 -0700190 private final HandlerThread mHandlerThread = CarServiceUtils.getHandlerThread(
Mayank Garg02576972021-02-18 16:46:07 -0800191 HANDLER_THREAD_NAME);
192 private final Handler mHandler;
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700193
Felipe Leme5528ff72020-02-10 19:05:14 -0800194 /**
Antonio Kantekc8114752020-03-05 21:37:39 -0800195 * List of listeners to be notified on new user activities events.
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700196 * This collection should be accessed and manipulated by mHandlerThread only.
Antonio Kantekc8114752020-03-05 21:37:39 -0800197 */
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700198 private final List<UserLifecycleListener> mUserLifecycleListeners = new ArrayList<>();
Antonio Kantekc8114752020-03-05 21:37:39 -0800199
200 /**
Felipe Leme5528ff72020-02-10 19:05:14 -0800201 * List of lifecycle listeners by uid.
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700202 * This collection should be accessed and manipulated by mHandlerThread only.
Felipe Leme5528ff72020-02-10 19:05:14 -0800203 */
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700204 private final SparseArray<IResultReceiver> mAppLifecycleListeners = new SparseArray<>();
Felipe Leme5528ff72020-02-10 19:05:14 -0800205
Mayank Garg7a114c82020-04-08 21:25:06 -0700206 /**
207 * User Id for the user switch in process, if any.
208 */
209 @GuardedBy("mLockUser")
felipealf7368962020-04-16 12:55:19 -0700210 private int mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
Mayank Garg7a114c82020-04-08 21:25:06 -0700211 /**
212 * Request Id for the user switch in process, if any.
213 */
214 @GuardedBy("mLockUser")
felipealf7368962020-04-16 12:55:19 -0700215 private int mRequestIdForUserSwitchInProcess;
Felipe Lemee3cab982020-03-12 11:39:29 -0700216 private final int mHalTimeoutMs = CarProperties.user_hal_timeout().orElse(5_000);
217
Eric Jeongc91f9452019-08-30 15:04:21 -0700218 private final CopyOnWriteArrayList<PassengerCallback> mPassengerCallbacks =
219 new CopyOnWriteArrayList<>();
220
Mayank Garg7e1450b2020-08-07 18:15:15 -0700221 // TODO(b/163566866): Use mSwitchGuestUserBeforeSleep for new create guest request
222 private final boolean mSwitchGuestUserBeforeSleep;
223
felipeal61ce3732020-04-03 11:01:00 -0700224 @Nullable
225 @GuardedBy("mLockUser")
226 private UserInfo mInitialUser;
227
Mayank Garg587f1942020-05-06 01:41:34 -0700228 private IResultReceiver mUserSwitchUiReceiver;
229
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800230 private final CarUxRestrictionsManagerService mCarUxRestrictionService;
231
232 /**
233 * Whether some operations - like user switch - are restricted by driving safety constraints.
234 */
235 @GuardedBy("mLockUser")
236 private boolean mUxRestricted;
237
238 /**
Mayank Garg784a0862021-05-26 00:20:50 -0700239 * If {@code false}, garage mode operations (background users start at garage mode entry and
240 * background users stop at garage mode exit) will be skipped. Controlled using car shell
241 * command {@code adb shell set-start-bg-users-on-garage-mode [true|false]}
242 * Purpose: Garage mode testing and simulation
243 */
244 @GuardedBy("mLockUser")
245 private boolean mStartBackgroundUsersOnGarageMode = true;
246
247 /**
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800248 * Callback to notify {@code CarServiceHelper} about driving safety changes (through
249 * {@link ICarServiceHelper#setSafetyMode(boolean).
250 *
251 * <p>NOTE: in theory, that logic should belong to {@code CarDevicePolicyService}, but it's
252 * simpler to do it here (and that service already depends on this one).
253 */
254 @GuardedBy("mLockUser")
255 private ICarServiceHelper mICarServiceHelper;
256
257 private final ICarUxRestrictionsChangeListener mCarUxRestrictionsChangeListener =
258 new ICarUxRestrictionsChangeListener.Stub() {
259 @Override
260 public void onUxRestrictionsChanged(CarUxRestrictions restrictions) {
261 setUxRestrictions(restrictions);
262 }
263 };
Felipe Leme5d5ab142020-10-27 13:49:10 -0700264
Eric Jeongc91f9452019-08-30 15:04:21 -0700265 /** Interface for callbaks related to passenger activities. */
266 public interface PassengerCallback {
267 /** Called when passenger is started at a certain zone. */
268 void onPassengerStarted(@UserIdInt int passengerId, int zoneId);
269 /** Called when passenger is stopped. */
270 void onPassengerStopped(@UserIdInt int passengerId);
271 }
272
273 /** Interface for delegating zone-related implementation to CarOccupantZoneService. */
274 public interface ZoneUserBindingHelper {
275 /** Gets occupant zones corresponding to the occupant type. */
276 @NonNull
277 List<OccupantZoneInfo> getOccupantZones(@OccupantTypeEnum int occupantType);
278 /** Assigns the user to the occupant zone. */
279 boolean assignUserToOccupantZone(@UserIdInt int userId, int zoneId);
280 /** Makes the occupant zone unoccupied. */
281 boolean unassignUserFromOccupantZone(@UserIdInt int userId);
282 /** Returns whether there is a passenger display. */
283 boolean isPassengerDisplayAvailable();
284 }
285
286 private final Object mLockHelper = new Object();
287 @GuardedBy("mLockHelper")
288 private ZoneUserBindingHelper mZoneUserBindingHelper;
289
Felipe Leme6b34fc32020-10-26 15:49:17 -0700290 /** Map used to avoid calling UserHAL when a user was removed because HAL creation failed. */
291 @GuardedBy("mLockUser")
292 private final SparseBooleanArray mFailedToCreateUserIds = new SparseBooleanArray(1);
293
Felipe Leme58412202020-01-09 13:45:33 -0800294 public CarUserService(@NonNull Context context, @NonNull UserHalService hal,
Mayank Garge90a4082020-09-30 12:57:34 -0700295 @NonNull UserManager userManager,
Felipe Leme5d5ab142020-10-27 13:49:10 -0700296 @NonNull IActivityManager am, int maxRunningUsers,
297 @NonNull CarUxRestrictionsManagerService uxRestrictionService) {
Mayank Garge90a4082020-09-30 12:57:34 -0700298 this(context, hal, userManager, am, maxRunningUsers,
Mayank Garg02576972021-02-18 16:46:07 -0800299 /* initialUserSetter= */ null, /* userPreCreator= */ null, uxRestrictionService,
300 null);
Mayank Garg71661ea2020-04-29 01:25:03 -0700301 }
302
303 @VisibleForTesting
304 CarUserService(@NonNull Context context, @NonNull UserHalService hal,
Mayank Garge90a4082020-09-30 12:57:34 -0700305 @NonNull UserManager userManager,
Mayank Gargccad8062020-08-30 15:05:10 -0700306 @NonNull IActivityManager am, int maxRunningUsers,
Mayank Garg1bb1c382020-09-03 17:11:11 -0700307 @Nullable InitialUserSetter initialUserSetter,
Felipe Leme5d5ab142020-10-27 13:49:10 -0700308 @Nullable UserPreCreator userPreCreator,
Mayank Garg02576972021-02-18 16:46:07 -0800309 @NonNull CarUxRestrictionsManagerService uxRestrictionService,
310 @Nullable Handler handler) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800311 if (Log.isLoggable(TAG, Log.DEBUG)) {
Felipe Leme8725a2f2020-12-09 16:04:51 -0800312 Slog.d(TAG, "constructed for user " + context.getUserId());
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700313 }
314 mContext = context;
Felipe Leme58412202020-01-09 13:45:33 -0800315 mHal = hal;
Keun young Parkf3523cd2019-04-08 10:09:17 -0700316 mAm = am;
317 mMaxRunningUsers = maxRunningUsers;
Anthony Hugh9932a252019-06-12 16:19:56 -0700318 mUserManager = userManager;
Eric Jeongc91f9452019-08-30 15:04:21 -0700319 mLastPassengerId = UserHandle.USER_NULL;
Mayank Garg02576972021-02-18 16:46:07 -0800320 mHandler = handler == null ? new Handler(mHandlerThread.getLooper()) : handler;
Mayank Garg1bb1c382020-09-03 17:11:11 -0700321 mInitialUserSetter =
Felipe Lemecceb2992020-11-18 18:22:44 -0800322 initialUserSetter == null ? new InitialUserSetter(context, this,
323 (u) -> setInitialUser(u)) : initialUserSetter;
Mayank Garg1bb1c382020-09-03 17:11:11 -0700324 mUserPreCreator =
325 userPreCreator == null ? new UserPreCreator(mUserManager) : userPreCreator;
Mayank Garg7e1450b2020-08-07 18:15:15 -0700326 Resources resources = context.getResources();
327 mEnablePassengerSupport = resources.getBoolean(R.bool.enablePassengerSupport);
328 mSwitchGuestUserBeforeSleep = resources.getBoolean(
329 R.bool.config_switchGuestUserBeforeGoingSleep);
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800330 mCarUxRestrictionService = uxRestrictionService;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700331 }
332
333 @Override
334 public void init() {
Eric Jeongf75d4132020-12-21 13:48:23 -0800335 if (Log.isLoggable(TAG, Log.DEBUG)) {
336 Slog.d(TAG, "init()");
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700337 }
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800338 mCarUxRestrictionService.registerUxRestrictionsChangeListener(
339 mCarUxRestrictionsChangeListener, Display.DEFAULT_DISPLAY);
340
341 setUxRestrictions(mCarUxRestrictionService.getCurrentUxRestrictions());
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700342 }
343
344 @Override
345 public void release() {
Eric Jeongf75d4132020-12-21 13:48:23 -0800346 if (Log.isLoggable(TAG, Log.DEBUG)) {
347 Slog.d(TAG, "release()");
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700348 }
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800349 mCarUxRestrictionService
350 .unregisterUxRestrictionsChangeListener(mCarUxRestrictionsChangeListener);
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700351 }
352
353 @Override
Felipe Leme176a5fd2021-01-20 15:48:33 -0800354 public void dump(@NonNull IndentingPrintWriter writer) {
Felipe Leme55236722020-10-16 16:54:32 -0700355 checkHasDumpPermissionGranted("dump()");
356
Eric Jeong1545f3b2019-09-16 13:56:52 -0700357 writer.println("*CarUserService*");
Felipe Leme5528ff72020-02-10 19:05:14 -0800358 String indent = " ";
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700359 handleDumpListeners(writer, indent);
Mayank Garg587f1942020-05-06 01:41:34 -0700360 writer.printf("User switch UI receiver %s\n", mUserSwitchUiReceiver);
Eric Jeongc91f9452019-08-30 15:04:21 -0700361 synchronized (mLockUser) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700362 writer.println("User0Unlocked: " + mUser0Unlocked);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700363 writer.println("BackgroundUsersToRestart: " + mBackgroundUsersToRestart);
364 writer.println("BackgroundUsersRestarted: " + mBackgroundUsersRestartedHere);
Felipe Leme6b34fc32020-10-26 15:49:17 -0700365 if (mFailedToCreateUserIds.size() > 0) {
366 writer.println("FailedToCreateUserIds: " + mFailedToCreateUserIds);
367 }
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800368 writer.printf("Is UX restricted: %b\n", mUxRestricted);
Mayank Garg784a0862021-05-26 00:20:50 -0700369 writer.printf("Start Background Users On Garage Mode=%s\n",
370 mStartBackgroundUsersOnGarageMode);
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700371 }
Mayank Garg02576972021-02-18 16:46:07 -0800372
373 writer.println("SwitchGuestUserBeforeSleep: " + mSwitchGuestUserBeforeSleep);
Mayank Garg02576972021-02-18 16:46:07 -0800374
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700375 writer.println("MaxRunningUsers: " + mMaxRunningUsers);
376 List<UserInfo> allDrivers = getAllDrivers();
377 int driversSize = allDrivers.size();
378 writer.println("NumberOfDrivers: " + driversSize);
379 for (int i = 0; i < driversSize; i++) {
380 int driverId = allDrivers.get(i).id;
381 writer.print(indent + "#" + i + ": id=" + driverId);
382 List<UserInfo> passengers = getPassengers(driverId);
383 int passengersSize = passengers.size();
384 writer.print(" NumberPassengers: " + passengersSize);
385 if (passengersSize > 0) {
386 writer.print(" [");
387 for (int j = 0; j < passengersSize; j++) {
388 writer.print(passengers.get(j).id);
389 if (j < passengersSize - 1) {
390 writer.print(" ");
felipeal2d0483c2019-11-02 14:07:22 -0700391 }
felipeal2d0483c2019-11-02 14:07:22 -0700392 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700393 writer.print("]");
felipeal2d0483c2019-11-02 14:07:22 -0700394 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700395 writer.println();
396 }
397 writer.printf("EnablePassengerSupport: %s\n", mEnablePassengerSupport);
398 writer.printf("User HAL timeout: %dms\n", mHalTimeoutMs);
399 writer.printf("Initial user: %s\n", mInitialUser);
felipealbf327652020-06-03 11:33:29 -0700400
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700401 writer.println("Relevant overlayable properties");
402 Resources res = mContext.getResources();
403 writer.printf("%sowner_name=%s\n", indent,
404 res.getString(com.android.internal.R.string.owner_name));
405 writer.printf("%sdefault_guest_name=%s\n", indent,
406 res.getString(R.string.default_guest_name));
felipealf7368962020-04-16 12:55:19 -0700407 writer.printf("User switch in process=%d\n", mUserIdForUserSwitchInProcess);
Mayank Garg7a114c82020-04-08 21:25:06 -0700408 writer.printf("Request Id for the user switch in process=%d\n ",
409 mRequestIdForUserSwitchInProcess);
Mayank Garga480dd92020-05-14 03:14:57 -0700410 writer.printf("System UI package name=%s\n", getSystemUiPackageName());
felipeale8c5dce2020-04-15 11:27:06 -0700411
felipealbf327652020-06-03 11:33:29 -0700412 writer.println("Relevant Global settings");
413 dumpGlobalProperty(writer, indent, CarSettings.Global.LAST_ACTIVE_USER_ID);
414 dumpGlobalProperty(writer, indent, CarSettings.Global.LAST_ACTIVE_PERSISTENT_USER_ID);
415
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700416 mInitialUserSetter.dump(writer);
felipeale8c5dce2020-04-15 11:27:06 -0700417 }
418
felipealbf327652020-06-03 11:33:29 -0700419 private void dumpGlobalProperty(PrintWriter writer, String indent, String property) {
420 String value = Settings.Global.getString(mContext.getContentResolver(), property);
421 writer.printf("%s%s=%s\n", indent, property, value);
422 }
423
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700424 private void handleDumpListeners(@NonNull PrintWriter writer, String indent) {
425 CountDownLatch latch = new CountDownLatch(1);
426 mHandler.post(() -> {
felipealde1e16d2020-06-03 13:20:48 -0700427 handleDumpServiceLifecycleListeners(writer);
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700428 handleDumpAppLifecycleListeners(writer, indent);
429 latch.countDown();
430 });
431 int timeout = 5;
432 try {
433 if (!latch.await(timeout, TimeUnit.SECONDS)) {
434 writer.printf("Handler thread didn't respond in %ds when dumping listeners\n",
435 timeout);
436 }
437 } catch (InterruptedException e) {
438 Thread.currentThread().interrupt();
439 writer.println("Interrupted waiting for handler thread to dump app and user listeners");
440 }
441 }
442
felipealde1e16d2020-06-03 13:20:48 -0700443 private void handleDumpServiceLifecycleListeners(@NonNull PrintWriter writer) {
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700444 if (mUserLifecycleListeners.isEmpty()) {
felipealde1e16d2020-06-03 13:20:48 -0700445 writer.println("No lifecycle listeners for internal services");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700446 return;
447 }
felipealde1e16d2020-06-03 13:20:48 -0700448 int size = mUserLifecycleListeners.size();
449 writer.printf("%d lifecycle listener%s for services\n", size, size == 1 ? "" : "s");
450 String indent = " ";
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700451 for (UserLifecycleListener listener : mUserLifecycleListeners) {
felipealde1e16d2020-06-03 13:20:48 -0700452 writer.printf("%s%s\n", indent, FunctionalUtils.getLambdaName(listener));
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700453 }
454 }
455
456 private void handleDumpAppLifecycleListeners(@NonNull PrintWriter writer, String indent) {
felipealde1e16d2020-06-03 13:20:48 -0700457 int size = mAppLifecycleListeners.size();
458 if (size == 0) {
459 writer.println("No lifecycle listeners for apps");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700460 return;
461 }
felipealde1e16d2020-06-03 13:20:48 -0700462 writer.printf("%d lifecycle listener%s for apps \n", size, size == 1 ? "" : "s");
463 for (int i = 0; i < size; i++) {
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700464 int uid = mAppLifecycleListeners.keyAt(i);
465 IResultReceiver listener = mAppLifecycleListeners.valueAt(i);
Felipe Lemeea4b5322020-10-26 15:33:36 -0700466 writer.printf("%suid: %d listener: %s\n", indent, uid,
467 FunctionalUtils.getLambdaName(listener));
Keun-young Parkd462a912019-02-11 08:53:42 -0800468 }
Eric Jeong1545f3b2019-09-16 13:56:52 -0700469 }
470
471 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700472 * @see ExperimentalCarUserManager.createDriver
Eric Jeong1545f3b2019-09-16 13:56:52 -0700473 */
474 @Override
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700475 public AndroidFuture<UserCreationResult> createDriver(@NonNull String name, boolean admin) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700476 checkManageUsersPermission("createDriver");
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +0000477 Objects.requireNonNull(name, "name cannot be null");
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700478
479 AndroidFuture<UserCreationResult> future = new AndroidFuture<UserCreationResult>() {
480 @Override
481 protected void onCompleted(UserCreationResult result, Throwable err) {
482 if (result == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800483 Slog.w(TAG, "createDriver(" + name + "," + admin + ") failed: " + err);
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700484 } else {
485 if (result.getStatus() == UserCreationResult.STATUS_SUCCESSFUL) {
486 assignDefaultIcon(result.getUser());
487 }
488 }
489 super.onCompleted(result, err);
490 };
491 };
492 int flags = 0;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700493 if (admin) {
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700494 if (!(mUserManager.isAdminUser() || mUserManager.isSystemUser())) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800495 Slog.e(TAG, "Only admin users and system user can create other admins.");
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700496 sendUserCreationResultFailure(future, UserCreationResult.STATUS_INVALID_REQUEST);
497 return future;
498 }
499 flags = UserInfo.FLAG_ADMIN;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700500 }
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700501 createUser(name, UserInfo.getDefaultUserType(flags), flags, mHalTimeoutMs, future);
502 return future;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700503 }
504
505 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700506 * @see ExperimentalCarUserManager.createPassenger
Eric Jeong1545f3b2019-09-16 13:56:52 -0700507 */
508 @Override
509 @Nullable
510 public UserInfo createPassenger(@NonNull String name, @UserIdInt int driverId) {
511 checkManageUsersPermission("createPassenger");
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +0000512 Objects.requireNonNull(name, "name cannot be null");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700513 UserInfo driver = mUserManager.getUserInfo(driverId);
514 if (driver == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800515 Slog.w(TAG, "the driver is invalid");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700516 return null;
517 }
518 if (driver.isGuest()) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800519 Slog.w(TAG, "a guest driver cannot create a passenger");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700520 return null;
521 }
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700522 // createPassenger doesn't use user HAL because user HAL doesn't support profile user yet.
Bookatz42fb1a62019-10-30 11:45:01 -0700523 UserInfo user = mUserManager.createProfileForUser(name,
524 UserManager.USER_TYPE_PROFILE_MANAGED, /* flags */ 0, driverId);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700525 if (user == null) {
526 // Couldn't create user, most likely because there are too many.
Eric Jeongf75d4132020-12-21 13:48:23 -0800527 Slog.w(TAG, "can't create a profile for user" + driverId);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700528 return null;
529 }
530 // Passenger user should be a non-admin user.
Mayank Garge90a4082020-09-30 12:57:34 -0700531 UserHelper.setDefaultNonAdminRestrictions(mContext, user, /* enable= */ true);
Anthony Hugh6fed1e92019-10-22 16:22:03 -0700532 assignDefaultIcon(user);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700533 return user;
534 }
535
536 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700537 * @see ExperimentalCarUserManager.switchDriver
Eric Jeong1545f3b2019-09-16 13:56:52 -0700538 */
539 @Override
Eric Jeong25666cf2020-05-14 15:16:27 -0700540 public void switchDriver(@UserIdInt int driverId, AndroidFuture<UserSwitchResult> receiver) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700541 checkManageUsersPermission("switchDriver");
Mayank Garg94f3eb92020-08-12 12:38:58 -0700542 if (UserHelperLite.isHeadlessSystemUser(driverId)) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700543 // System user doesn't associate with real person, can not be switched to.
Eric Jeongf75d4132020-12-21 13:48:23 -0800544 Slog.w(TAG, "switching to system user in headless system user mode is not allowed");
felipealdfdf8512020-06-01 09:35:45 -0700545 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_INVALID_REQUEST);
Eric Jeong25666cf2020-05-14 15:16:27 -0700546 return;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700547 }
548 int userSwitchable = mUserManager.getUserSwitchability();
549 if (userSwitchable != UserManager.SWITCHABILITY_STATUS_OK) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800550 Slog.w(TAG, "current process is not allowed to switch user");
felipealdfdf8512020-06-01 09:35:45 -0700551 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_INVALID_REQUEST);
Eric Jeong25666cf2020-05-14 15:16:27 -0700552 return;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700553 }
Eric Jeong25666cf2020-05-14 15:16:27 -0700554 switchUser(driverId, mHalTimeoutMs, receiver);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700555 }
556
557 /**
Eric Jeonge7916fc2019-12-20 14:03:34 -0800558 * Returns all drivers who can occupy the driving zone. Guest users are included in the list.
559 *
560 * @return the list of {@link UserInfo} who can be a driver on the device.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700561 */
562 @Override
563 @NonNull
564 public List<UserInfo> getAllDrivers() {
felipeal2d0483c2019-11-02 14:07:22 -0700565 checkManageUsersOrDumpPermission("getAllDrivers");
Mayank Garg94f3eb92020-08-12 12:38:58 -0700566 return getUsers((user) -> !UserHelperLite.isHeadlessSystemUser(user.id) && user.isEnabled()
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700567 && !user.isManagedProfile() && !user.isEphemeral());
Eric Jeong1545f3b2019-09-16 13:56:52 -0700568 }
569
570 /**
Eric Jeonge7916fc2019-12-20 14:03:34 -0800571 * Returns all passengers under the given driver.
572 *
573 * @param driverId User id of a driver.
574 * @return the list of {@link UserInfo} who is a passenger under the given driver.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700575 */
576 @Override
577 @NonNull
578 public List<UserInfo> getPassengers(@UserIdInt int driverId) {
felipeal2d0483c2019-11-02 14:07:22 -0700579 checkManageUsersOrDumpPermission("getPassengers");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700580 return getUsers((user) -> {
Mayank Garg94f3eb92020-08-12 12:38:58 -0700581 return !UserHelperLite.isHeadlessSystemUser(user.id) && user.isEnabled()
Eric Jeong40f8fa32020-05-12 12:23:33 -0700582 && user.isManagedProfile() && user.profileGroupId == driverId;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700583 });
584 }
585
586 /**
587 * @see CarUserManager.startPassenger
588 */
589 @Override
590 public boolean startPassenger(@UserIdInt int passengerId, int zoneId) {
591 checkManageUsersPermission("startPassenger");
Eric Jeongc91f9452019-08-30 15:04:21 -0700592 synchronized (mLockUser) {
593 try {
594 if (!mAm.startUserInBackgroundWithListener(passengerId, null)) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800595 Slog.w(TAG, "could not start passenger");
Eric Jeongc91f9452019-08-30 15:04:21 -0700596 return false;
597 }
598 } catch (RemoteException e) {
599 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -0800600 Slog.w(TAG, "error while starting passenger", e);
Eric Jeongc91f9452019-08-30 15:04:21 -0700601 return false;
602 }
603 if (!assignUserToOccupantZone(passengerId, zoneId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800604 Slog.w(TAG, "could not assign passenger to zone");
Eric Jeongc91f9452019-08-30 15:04:21 -0700605 return false;
606 }
607 mLastPassengerId = passengerId;
608 }
609 for (PassengerCallback callback : mPassengerCallbacks) {
610 callback.onPassengerStarted(passengerId, zoneId);
611 }
612 return true;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700613 }
614
615 /**
616 * @see CarUserManager.stopPassenger
617 */
618 @Override
619 public boolean stopPassenger(@UserIdInt int passengerId) {
620 checkManageUsersPermission("stopPassenger");
Eric Jeongc91f9452019-08-30 15:04:21 -0700621 return stopPassengerInternal(passengerId, true);
622 }
623
624 private boolean stopPassengerInternal(@UserIdInt int passengerId, boolean checkCurrentDriver) {
625 synchronized (mLockUser) {
626 UserInfo passenger = mUserManager.getUserInfo(passengerId);
627 if (passenger == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800628 Slog.w(TAG, "passenger " + passengerId + " doesn't exist");
Eric Jeongc91f9452019-08-30 15:04:21 -0700629 return false;
630 }
631 if (mLastPassengerId != passengerId) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800632 Slog.w(TAG, "passenger " + passengerId + " hasn't been started");
Eric Jeongc91f9452019-08-30 15:04:21 -0700633 return true;
634 }
635 if (checkCurrentDriver) {
636 int currentUser = ActivityManager.getCurrentUser();
637 if (passenger.profileGroupId != currentUser) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800638 Slog.w(TAG, "passenger " + passengerId
Eric Jeongc91f9452019-08-30 15:04:21 -0700639 + " is not a profile of the current user");
640 return false;
641 }
642 }
643 // Passenger is a profile, so cannot be stopped through activity manager.
644 // Instead, activities started by the passenger are stopped and the passenger is
645 // unassigned from the zone.
646 stopAllTasks(passengerId);
647 if (!unassignUserFromOccupantZone(passengerId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800648 Slog.w(TAG, "could not unassign user from occupant zone");
Eric Jeongc91f9452019-08-30 15:04:21 -0700649 return false;
650 }
651 mLastPassengerId = UserHandle.USER_NULL;
652 }
653 for (PassengerCallback callback : mPassengerCallbacks) {
654 callback.onPassengerStopped(passengerId);
655 }
656 return true;
657 }
658
659 private void stopAllTasks(@UserIdInt int userId) {
660 try {
Louis Chang3bf2f202020-08-18 13:04:28 +0800661 for (RootTaskInfo info : mAm.getAllRootTaskInfos()) {
662 for (int i = 0; i < info.childTaskIds.length; i++) {
663 if (info.childTaskUserIds[i] == userId) {
664 int taskId = info.childTaskIds[i];
Eric Jeongc91f9452019-08-30 15:04:21 -0700665 if (!mAm.removeTask(taskId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800666 Slog.w(TAG, "could not remove task " + taskId);
Eric Jeongc91f9452019-08-30 15:04:21 -0700667 }
668 }
669 }
670 }
671 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800672 Slog.e(TAG, "could not get stack info", e);
Eric Jeongc91f9452019-08-30 15:04:21 -0700673 }
Eric Jeong1545f3b2019-09-16 13:56:52 -0700674 }
675
Felipe Leme5528ff72020-02-10 19:05:14 -0800676 @Override
677 public void setLifecycleListenerForUid(IResultReceiver listener) {
678 int uid = Binder.getCallingUid();
felipeal312416a2020-04-14 12:28:24 -0700679 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SET_LIFECYCLE_LISTENER, uid);
Felipe Leme5528ff72020-02-10 19:05:14 -0800680 checkInteractAcrossUsersPermission("setLifecycleListenerForUid" + uid);
681
682 try {
683 listener.asBinder().linkToDeath(() -> onListenerDeath(uid), 0);
684 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800685 Slog.wtf(TAG, "Cannot listen to death of " + uid);
Felipe Leme5528ff72020-02-10 19:05:14 -0800686 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700687 mHandler.post(() -> mAppLifecycleListeners.append(uid, listener));
Felipe Leme5528ff72020-02-10 19:05:14 -0800688 }
689
690 private void onListenerDeath(int uid) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800691 Slog.i(TAG, "Removing listeners for uid " + uid + " on binder death");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700692 mHandler.post(() -> mAppLifecycleListeners.remove(uid));
Felipe Leme5528ff72020-02-10 19:05:14 -0800693 }
694
695 @Override
696 public void resetLifecycleListenerForUid() {
697 int uid = Binder.getCallingUid();
felipeal312416a2020-04-14 12:28:24 -0700698 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_RESET_LIFECYCLE_LISTENER, uid);
Felipe Leme5528ff72020-02-10 19:05:14 -0800699 checkInteractAcrossUsersPermission("resetLifecycleListenerForUid-" + uid);
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700700 mHandler.post(() -> mAppLifecycleListeners.remove(uid));
Felipe Leme5528ff72020-02-10 19:05:14 -0800701 }
702
Felipe Lemee3cab982020-03-12 11:39:29 -0700703 /**
felipeal61ce3732020-04-03 11:01:00 -0700704 * Gets the initial foreground user after the device boots or resumes from suspension.
705 *
706 * <p>When the OEM supports the User HAL, the initial user won't be available until the HAL
707 * returns the initial value to {@code CarService} - if HAL takes too long or times out, this
708 * method returns {@code null}.
709 *
710 * <p>If the HAL eventually times out, {@code CarService} will fallback to its default behavior
711 * (like switching to the last active user), and this method will return the result of such
712 * operation.
713 *
714 * <p>Notice that if {@code CarService} crashes, subsequent calls to this method will return
715 * {@code null}.
716 *
717 * @hide
718 */
719 @Nullable
720 public UserInfo getInitialUser() {
721 checkInteractAcrossUsersPermission("getInitialUser");
722 synchronized (mLockUser) {
723 return mInitialUser;
724 }
725 }
726
felipeal61ce3732020-04-03 11:01:00 -0700727 /**
728 * Sets the initial foreground user after the device boots or resumes from suspension.
729 */
730 public void setInitialUser(@Nullable UserInfo user) {
felipeal312416a2020-04-14 12:28:24 -0700731 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SET_INITIAL_USER,
732 user == null ? UserHandle.USER_NULL : user.id);
felipeal61ce3732020-04-03 11:01:00 -0700733 synchronized (mLockUser) {
734 mInitialUser = user;
735 }
736 if (user == null) {
737 // This mean InitialUserSetter failed and could not fallback, so the initial user was
738 // not switched (and most likely is SYSTEM_USER).
739 // TODO(b/153104378): should we set it to ActivityManager.getCurrentUser() instead?
Eric Jeongf75d4132020-12-21 13:48:23 -0800740 Slog.wtf(TAG, "Initial user set to null");
felipeal61ce3732020-04-03 11:01:00 -0700741 }
742 }
743
Mayank Garg7e1450b2020-08-07 18:15:15 -0700744 private void initResumeReplaceGuest() {
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700745 int currentUserId = ActivityManager.getCurrentUser();
746 UserInfo currentUser = mUserManager.getUserInfo(currentUserId);
747
748 if (!mInitialUserSetter.canReplaceGuestUser(currentUser)) return; // Not a guest
749
750 InitialUserInfo info =
751 new InitialUserSetter.Builder(InitialUserSetter.TYPE_REPLACE_GUEST).build();
752
753 mInitialUserSetter.set(info);
754 }
755
756 /**
Mayank Garg0baf88a2020-08-30 21:57:36 -0700757 * Calls to switch user at the power suspend.
Mayank Garg7e1450b2020-08-07 18:15:15 -0700758 *
759 * <p><b>Note:</b> Should be used only by {@link CarPowerManagementService}
760 *
Mayank Garg7e1450b2020-08-07 18:15:15 -0700761 */
Mayank Garg0baf88a2020-08-30 21:57:36 -0700762 public void onSuspend() {
Eric Jeongf75d4132020-12-21 13:48:23 -0800763 if (Log.isLoggable(TAG, Log.DEBUG)) {
764 Slog.d(TAG, "onSuspend called.");
Mayank Garg7e1450b2020-08-07 18:15:15 -0700765 }
766
Mayank Garg0baf88a2020-08-30 21:57:36 -0700767 if (mSwitchGuestUserBeforeSleep) {
768 initResumeReplaceGuest();
Mayank Garg7e1450b2020-08-07 18:15:15 -0700769 }
Mayank Garg1bb1c382020-09-03 17:11:11 -0700770
Mayank Garga3b72d02021-03-14 23:05:51 -0700771 preCreateUsersInternal();
Mayank Garg7e1450b2020-08-07 18:15:15 -0700772 }
773
774 /**
Mayank Garg0baf88a2020-08-30 21:57:36 -0700775 * Calls to switch user at the power resume.
776 *
777 * <p>
778 * <b>Note:</b> Should be used only by {@link CarPowerManagementService}
779 *
780 */
781 public void onResume() {
Eric Jeongf75d4132020-12-21 13:48:23 -0800782 if (Log.isLoggable(TAG, Log.DEBUG)) {
783 Slog.d(TAG, "onResume called.");
Mayank Garg0baf88a2020-08-30 21:57:36 -0700784 }
785
Mayank Garg02576972021-02-18 16:46:07 -0800786 mHandler.post(() -> initBootUser(InitialUserInfoRequestType.RESUME));
Mayank Garg0baf88a2020-08-30 21:57:36 -0700787 }
788
789 /**
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700790 * Calls to start user at the android startup.
Mayank Garg70732a82020-08-05 20:17:47 -0700791 */
792 public void initBootUser() {
Mayank Garg02576972021-02-18 16:46:07 -0800793 mHandler.post(() -> initBootUser(getInitialUserInfoRequestType()));
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700794 }
795
Mayank Garg7e1450b2020-08-07 18:15:15 -0700796 private void initBootUser(int requestType) {
797 boolean replaceGuest =
798 requestType == InitialUserInfoRequestType.RESUME && !mSwitchGuestUserBeforeSleep;
Mayank Garg70732a82020-08-05 20:17:47 -0700799 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_REQ, requestType,
800 mHalTimeoutMs);
801 checkManageUsersPermission("startInitialUser");
802
803 if (!isUserHalSupported()) {
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700804 fallbackToDefaultInitialUserBehavior(/* userLocales= */ null, replaceGuest);
Mayank Gargfd1e0692021-05-25 13:33:48 -0700805 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_REQ_COMPLETE,
806 requestType);
Mayank Garg70732a82020-08-05 20:17:47 -0700807 return;
808 }
809
810 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
811 mHal.getInitialUserInfo(requestType, mHalTimeoutMs, usersInfo, (status, resp) -> {
812 if (resp != null) {
813 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_RESP,
814 status, resp.action, resp.userToSwitchOrCreate.userId,
815 resp.userToSwitchOrCreate.flags, resp.userNameToCreate, resp.userLocales);
816
817 String userLocales = resp.userLocales;
818 InitialUserInfo info;
819 switch (resp.action) {
820 case InitialUserInfoResponseAction.SWITCH:
821 int userId = resp.userToSwitchOrCreate.userId;
822 if (userId <= 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800823 Slog.w(TAG, "invalid (or missing) user id sent by HAL: " + userId);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700824 fallbackToDefaultInitialUserBehavior(userLocales, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700825 break;
826 }
827 info = new InitialUserSetter.Builder(InitialUserSetter.TYPE_SWITCH)
828 .setUserLocales(userLocales)
829 .setSwitchUserId(userId)
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700830 .setReplaceGuest(replaceGuest)
Mayank Garg70732a82020-08-05 20:17:47 -0700831 .build();
832 mInitialUserSetter.set(info);
833 break;
834
835 case InitialUserInfoResponseAction.CREATE:
836 int halFlags = resp.userToSwitchOrCreate.flags;
837 String userName = resp.userNameToCreate;
838 info = new InitialUserSetter.Builder(InitialUserSetter.TYPE_CREATE)
839 .setUserLocales(userLocales)
840 .setNewUserName(userName)
841 .setNewUserFlags(halFlags)
842 .build();
843 mInitialUserSetter.set(info);
844 break;
845
846 case InitialUserInfoResponseAction.DEFAULT:
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700847 fallbackToDefaultInitialUserBehavior(userLocales, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700848 break;
849 default:
Eric Jeongf75d4132020-12-21 13:48:23 -0800850 Slog.w(TAG, "invalid response action on " + resp);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700851 fallbackToDefaultInitialUserBehavior(/* user locale */ null, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700852 break;
853
854 }
855 } else {
856 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_RESP, status);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700857 fallbackToDefaultInitialUserBehavior(/* user locale */ null, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700858 }
Mayank Gargfd1e0692021-05-25 13:33:48 -0700859 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_REQ_COMPLETE,
860 requestType);
Mayank Garg70732a82020-08-05 20:17:47 -0700861 });
862 }
863
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700864 private void fallbackToDefaultInitialUserBehavior(String userLocales, boolean replaceGuest) {
Mayank Garg70732a82020-08-05 20:17:47 -0700865 InitialUserInfo info = new InitialUserSetter.Builder(
866 InitialUserSetter.TYPE_DEFAULT_BEHAVIOR)
867 .setUserLocales(userLocales)
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700868 .setReplaceGuest(replaceGuest)
Mayank Garg70732a82020-08-05 20:17:47 -0700869 .build();
870 mInitialUserSetter.set(info);
871 }
872
873 @VisibleForTesting
874 int getInitialUserInfoRequestType() {
Mayank Garge90a4082020-09-30 12:57:34 -0700875 if (!mInitialUserSetter.hasInitialUser()) {
Mayank Garg70732a82020-08-05 20:17:47 -0700876 return InitialUserInfoRequestType.FIRST_BOOT;
877 }
878 if (mContext.getPackageManager().isDeviceUpgrading()) {
879 return InitialUserInfoRequestType.FIRST_BOOT_AFTER_OTA;
880 }
881 return InitialUserInfoRequestType.COLD_BOOT;
882 }
883
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800884 /**
885 * Sets the {@link ICarServiceHelper} so it can receive UX restriction updates.
886 */
887 public void setCarServiceHelper(ICarServiceHelper helper) {
888 boolean restricted;
889 synchronized (mLockUser) {
890 mICarServiceHelper = helper;
891 restricted = mUxRestricted;
892 }
893 updateSafetyMode(helper, restricted);
894 }
895
896 private void updateSafetyMode(@Nullable ICarServiceHelper helper, boolean restricted) {
897 if (helper == null) return;
898
899 boolean isSafe = !restricted;
900 try {
901 helper.setSafetyMode(isSafe);
902 } catch (Exception e) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800903 Slog.e(TAG, "Exception calling helper.setDpmSafetyMode(" + isSafe + ")", e);
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800904 }
905 }
906
907 private void setUxRestrictions(@Nullable CarUxRestrictions restrictions) {
Felipe Leme5d5ab142020-10-27 13:49:10 -0700908 boolean restricted = restrictions != null
909 && (restrictions.getActiveRestrictions() & UX_RESTRICTIONS_NO_SETUP)
910 == UX_RESTRICTIONS_NO_SETUP;
Eric Jeongf75d4132020-12-21 13:48:23 -0800911 if (Log.isLoggable(TAG, Log.DEBUG)) {
912 Slog.d(TAG, "setUxRestrictions(" + restrictions + "): restricted=" + restricted);
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800913 } else {
Eric Jeongf75d4132020-12-21 13:48:23 -0800914 Slog.i(TAG, "Setting UX restricted to " + restricted);
Felipe Leme5d5ab142020-10-27 13:49:10 -0700915 }
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800916
917 ICarServiceHelper helper = null;
918
919 synchronized (mLockUser) {
920 mUxRestricted = restricted;
921 if (mICarServiceHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800922 Slog.e(TAG, "onUxRestrictionsChanged(): no mICarServiceHelper");
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800923 }
924 helper = mICarServiceHelper;
925 }
926 updateSafetyMode(helper, restricted);
927 }
928
929 private boolean isUxRestricted() {
930 synchronized (mLockUser) {
931 return mUxRestricted;
932 }
Felipe Leme5d5ab142020-10-27 13:49:10 -0700933 }
934
Mayank Garg70732a82020-08-05 20:17:47 -0700935 /**
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700936 * Calls the {@link UserHalService} and {@link IActivityManager} for user switch.
937 *
938 * <p>
Mayank Gargb08f6772020-05-01 18:06:48 -0700939 * When everything works well, the workflow is:
940 * <ol>
941 * <li> {@link UserHalService} is called for HAL user switch with ANDROID_SWITCH request
942 * type, current user id, target user id, and a callback.
943 * <li> HAL called back with SUCCESS.
944 * <li> {@link IActivityManager} is called for Android user switch.
945 * <li> Receiver would receive {@code STATUS_SUCCESSFUL}.
946 * <li> Once user is unlocked, {@link UserHalService} is again called with ANDROID_POST_SWITCH
947 * request type, current user id, and target user id. In this case, the current and target
948 * user IDs would be same.
949 * <ol/>
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700950 *
951 * <p>
Mayank Gargb08f6772020-05-01 18:06:48 -0700952 * Corner cases:
953 * <ul>
954 * <li> If target user is already the current user, no user switch is performed and receiver
Mayank Gargef1b9332020-06-11 17:36:56 -0700955 * would receive {@code STATUS_OK_USER_ALREADY_IN_FOREGROUND} right away.
Mayank Gargb08f6772020-05-01 18:06:48 -0700956 * <li> If HAL user switch call fails, no Android user switch. Receiver would receive
957 * {@code STATUS_HAL_INTERNAL_FAILURE}.
958 * <li> If HAL user switch call is successful, but android user switch call fails,
959 * {@link UserHalService} is again called with request type POST_SWITCH, current user id, and
960 * target user id, but in this case the current and target user IDs would be different.
961 * <li> If another user switch request for the same target user is received while previous
962 * request is in process, receiver would receive
963 * {@code STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO} for the new request right away.
964 * <li> If a user switch request is received while another user switch request for different
965 * target user is in process, the previous request would be abandoned and new request will be
966 * processed. No POST_SWITCH would be sent for the previous request.
967 * <ul/>
Mayank Garg59f22192020-03-27 00:51:45 -0700968 *
Mayank Garge19c2922020-03-30 18:05:53 -0700969 * @param targetUserId - target user Id
Mayank Garg59f22192020-03-27 00:51:45 -0700970 * @param timeoutMs - timeout for HAL to wait
971 * @param receiver - receiver for the results
972 */
Mayank Garge19c2922020-03-30 18:05:53 -0700973 @Override
974 public void switchUser(@UserIdInt int targetUserId, int timeoutMs,
felipeale5bf0322020-04-16 15:10:57 -0700975 @NonNull AndroidFuture<UserSwitchResult> receiver) {
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700976 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_REQ, targetUserId, timeoutMs);
Felipe Leme17799202020-09-03 12:55:53 -0700977 checkManageOrCreateUsersPermission("switchUser");
Mayank Garge19c2922020-03-30 18:05:53 -0700978 Objects.requireNonNull(receiver);
979 UserInfo targetUser = mUserManager.getUserInfo(targetUserId);
felipealf7368962020-04-16 12:55:19 -0700980 Preconditions.checkArgument(targetUser != null, "Target user doesn't exist");
Mayank Garga479cb32021-04-05 22:23:04 -0700981 if (mUserManager.getUserSwitchability() != UserManager.SWITCHABILITY_STATUS_OK) {
982 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_NOT_SWITCHABLE);
983 return;
984 }
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -0700985 mHandler.post(() -> handleSwitchUser(targetUser, timeoutMs, receiver));
Mayank Garg02576972021-02-18 16:46:07 -0800986 }
Mayank Garg7a114c82020-04-08 21:25:06 -0700987
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -0700988 private void handleSwitchUser(@NonNull UserInfo targetUser, int timeoutMs,
Mayank Garg02576972021-02-18 16:46:07 -0800989 @NonNull AndroidFuture<UserSwitchResult> receiver) {
felipealf7368962020-04-16 12:55:19 -0700990 int currentUser = ActivityManager.getCurrentUser();
Mayank Garg02576972021-02-18 16:46:07 -0800991 int targetUserId = targetUser.id;
felipealf7368962020-04-16 12:55:19 -0700992 if (currentUser == targetUserId) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800993 if (Log.isLoggable(TAG, Log.DEBUG)) {
994 Slog.d(TAG, "Current user is same as requested target user: " + targetUserId);
Mayank Garg0e239142020-04-14 19:16:31 -0700995 }
Mayank Gargef1b9332020-06-11 17:36:56 -0700996 int resultStatus = UserSwitchResult.STATUS_OK_USER_ALREADY_IN_FOREGROUND;
felipealdfdf8512020-06-01 09:35:45 -0700997 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg0e239142020-04-14 19:16:31 -0700998 return;
999 }
1000
Felipe Leme5d5ab142020-10-27 13:49:10 -07001001 if (isUxRestricted()) {
1002 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_UX_RESTRICTION_FAILURE);
1003 return;
1004 }
1005
Mayank Garg9ed099e2020-06-04 16:05:20 -07001006 // If User Hal is not supported, just android user switch.
1007 if (!isUserHalSupported()) {
1008 try {
1009 if (mAm.switchUser(targetUserId)) {
1010 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_SUCCESSFUL);
1011 return;
1012 }
1013 } catch (RemoteException e) {
1014 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001015 Slog.w(TAG, "error while switching user " + targetUser.toFullString(), e);
Mayank Garg9ed099e2020-06-04 16:05:20 -07001016 }
1017 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_ANDROID_FAILURE);
1018 return;
1019 }
1020
Mayank Garg7a114c82020-04-08 21:25:06 -07001021 synchronized (mLockUser) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001022 if (Log.isLoggable(TAG, Log.DEBUG)) {
1023 Slog.d(TAG, "switchUser(" + targetUserId + "): currentuser=" + currentUser
felipealf7368962020-04-16 12:55:19 -07001024 + ", mUserIdForUserSwitchInProcess=" + mUserIdForUserSwitchInProcess);
1025 }
1026
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001027 // If there is another request for the same target user, return another request in
1028 // process, else {@link mUserIdForUserSwitchInProcess} is updated and {@link
1029 // mRequestIdForUserSwitchInProcess} is reset. It is possible that there may be another
1030 // user switch request in process for different target user, but that request is now
1031 // ignored.
felipealf7368962020-04-16 12:55:19 -07001032 if (mUserIdForUserSwitchInProcess == targetUserId) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001033 if (Log.isLoggable(TAG, Log.DEBUG)) {
1034 Slog.d(TAG,
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001035 "Another user switch request in process for the requested target user: "
1036 + targetUserId);
1037 }
1038
1039 int resultStatus = UserSwitchResult.STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO;
felipealdfdf8512020-06-01 09:35:45 -07001040 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg7a114c82020-04-08 21:25:06 -07001041 return;
Mayank Garg02576972021-02-18 16:46:07 -08001042 } else {
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001043 mUserIdForUserSwitchInProcess = targetUserId;
1044 mRequestIdForUserSwitchInProcess = 0;
1045 }
Mayank Garg7a114c82020-04-08 21:25:06 -07001046 }
1047
felipealdfdf8512020-06-01 09:35:45 -07001048 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
Mayank Gargeb37d092020-06-02 14:37:57 -07001049 SwitchUserRequest request = createUserSwitchRequest(targetUserId, usersInfo);
1050
Felipe Leme5d5ab142020-10-27 13:49:10 -07001051 mHal.switchUser(request, timeoutMs, (halCallbackStatus, resp) -> {
Eric Jeongf75d4132020-12-21 13:48:23 -08001052 if (Log.isLoggable(TAG, Log.DEBUG)) {
1053 Slog.d(TAG, "switch response: status="
Felipe Leme5d5ab142020-10-27 13:49:10 -07001054 + UserHalHelper.halCallbackStatusToString(halCallbackStatus)
1055 + ", resp=" + resp);
felipealf7368962020-04-16 12:55:19 -07001056 }
1057
felipeale5bf0322020-04-16 15:10:57 -07001058 int resultStatus = UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE;
felipealf7368962020-04-16 12:55:19 -07001059
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001060 synchronized (mLockUser) {
Felipe Leme5d5ab142020-10-27 13:49:10 -07001061 if (halCallbackStatus != HalCallback.STATUS_OK) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001062 Slog.w(TAG, "invalid callback status ("
Felipe Leme5d5ab142020-10-27 13:49:10 -07001063 + UserHalHelper.halCallbackStatusToString(halCallbackStatus)
1064 + ") for response " + resp);
felipealdfdf8512020-06-01 09:35:45 -07001065 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001066 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
1067 return;
1068 }
felipealf7368962020-04-16 12:55:19 -07001069
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001070 if (mUserIdForUserSwitchInProcess != targetUserId) {
1071 // Another user switch request received while HAL responded. No need to process
1072 // this request further
Eric Jeongf75d4132020-12-21 13:48:23 -08001073 if (Log.isLoggable(TAG, Log.DEBUG)) {
1074 Slog.d(TAG, "Another user switch received while HAL responsed. Request"
1075 + " abondoned for : " + targetUserId + ". Current user in process: "
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001076 + mUserIdForUserSwitchInProcess);
felipealf7368962020-04-16 12:55:19 -07001077 }
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001078 resultStatus =
1079 UserSwitchResult.STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST;
felipealdfdf8512020-06-01 09:35:45 -07001080 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001081 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
1082 return;
1083 }
1084
1085 switch (resp.status) {
1086 case SwitchUserStatus.SUCCESS:
1087 boolean switched;
1088 try {
1089 switched = mAm.switchUser(targetUserId);
1090 if (switched) {
Mayank Garg587f1942020-05-06 01:41:34 -07001091 sendUserSwitchUiCallback(targetUserId);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001092 resultStatus = UserSwitchResult.STATUS_SUCCESSFUL;
1093 mRequestIdForUserSwitchInProcess = resp.requestId;
1094 } else {
1095 resultStatus = UserSwitchResult.STATUS_ANDROID_FAILURE;
1096 postSwitchHalResponse(resp.requestId, targetUserId);
1097 }
1098 } catch (RemoteException e) {
1099 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001100 Slog.w(TAG,
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001101 "error while switching user " + targetUser.toFullString(), e);
1102 }
1103 break;
1104 case SwitchUserStatus.FAILURE:
1105 // HAL failed to switch user
1106 resultStatus = UserSwitchResult.STATUS_HAL_FAILURE;
1107 break;
felipealdfdf8512020-06-01 09:35:45 -07001108 default:
1109 // Shouldn't happen because UserHalService validates the status
Eric Jeongf75d4132020-12-21 13:48:23 -08001110 Slog.wtf(TAG, "Received invalid user switch status from HAL: " + resp);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001111 }
1112
1113 if (mRequestIdForUserSwitchInProcess == 0) {
1114 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
1115 }
Mayank Garg59f22192020-03-27 00:51:45 -07001116 }
Felipe Leme5d5ab142020-10-27 13:49:10 -07001117 sendUserSwitchResult(receiver, halCallbackStatus, resultStatus, resp.errorMessage);
Mayank Garg59f22192020-03-27 00:51:45 -07001118 });
1119 }
1120
Mayank Garga55c3092020-05-28 03:19:24 -07001121 @Override
Mayank Gargc9266482021-03-01 10:27:37 -08001122 public void removeUser(@UserIdInt int userId, AndroidFuture<UserRemovalResult> receiver) {
1123 removeUser(userId, /* hasCallerRestrictions= */ false, receiver);
Felipe Leme55236722020-10-16 16:54:32 -07001124 }
1125
1126 /**
1127 * Internal implementation of {@code removeUser()}, which is used by both
1128 * {@code ICarUserService} and {@code ICarDevicePolicyService}.
1129 *
1130 * @param userId user to be removed
1131 * @param hasCallerRestrictions when {@code true}, if the caller user is not an admin, it can
1132 * only remove itself.
Mayank Gargc9266482021-03-01 10:27:37 -08001133 * @param receiver to post results
Felipe Leme55236722020-10-16 16:54:32 -07001134 */
Mayank Gargc9266482021-03-01 10:27:37 -08001135 public void removeUser(@UserIdInt int userId, boolean hasCallerRestrictions,
1136 AndroidFuture<UserRemovalResult> receiver) {
Felipe Leme17799202020-09-03 12:55:53 -07001137 checkManageOrCreateUsersPermission("removeUser");
Felipe Leme55236722020-10-16 16:54:32 -07001138 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_REMOVE_USER_REQ, userId,
1139 hasCallerRestrictions ? 1 : 0);
Felipe Lemee5bb26b2020-10-26 15:49:17 -07001140
Felipe Lemee5bb26b2020-10-26 15:49:17 -07001141 if (hasCallerRestrictions) {
1142 // Restrictions: non-admin user can only remove itself, admins have no restrictions
1143 int callingUserId = Binder.getCallingUserHandle().getIdentifier();
1144 UserInfo callingUser = mUserManager.getUserInfo(callingUserId);
1145 if (!callingUser.isAdmin() && userId != callingUserId) {
1146 throw new SecurityException("Non-admin user " + callingUserId
1147 + " can only remove itself");
1148 }
1149 }
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001150 mHandler.post(() -> handleRemoveUser(userId, hasCallerRestrictions, receiver));
Mayank Gargc9266482021-03-01 10:27:37 -08001151 }
Felipe Lemee5bb26b2020-10-26 15:49:17 -07001152
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001153 private void handleRemoveUser(@UserIdInt int userId, boolean hasCallerRestrictions,
Mayank Gargc9266482021-03-01 10:27:37 -08001154 AndroidFuture<UserRemovalResult> receiver) {
1155 UserInfo userInfo = mUserManager.getUserInfo(userId);
1156 if (userInfo == null) {
1157 sendUserRemovalResult(userId, UserRemovalResult.STATUS_USER_DOES_NOT_EXIST, receiver);
1158 return;
1159 }
Mayank Garga55c3092020-05-28 03:19:24 -07001160 android.hardware.automotive.vehicle.V2_0.UserInfo halUser =
1161 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1162 halUser.userId = userInfo.id;
1163 halUser.flags = UserHalHelper.convertFlags(userInfo);
1164 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1165
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001166 // check if the user is last admin user.
1167 boolean isLastAdmin = false;
Mayank Garga55c3092020-05-28 03:19:24 -07001168 if (UserHalHelper.isAdmin(halUser.flags)) {
1169 int size = usersInfo.existingUsers.size();
1170 int totalAdminUsers = 0;
1171 for (int i = 0; i < size; i++) {
1172 if (UserHalHelper.isAdmin(usersInfo.existingUsers.get(i).flags)) {
1173 totalAdminUsers++;
1174 }
1175 }
1176 if (totalAdminUsers == 1) {
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001177 isLastAdmin = true;
Mayank Garga55c3092020-05-28 03:19:24 -07001178 }
1179 }
1180
1181 // First remove user from android and then remove from HAL because HAL remove user is one
1182 // way call.
Felipe Leme9a751912021-01-05 17:45:48 -08001183 // TODO(b/170887769): rename hasCallerRestrictions to fromCarDevicePolicyManager (or use an
1184 // int / enum to indicate if it's called from CarUserManager or CarDevicePolicyManager), as
1185 // it's counter-intuitive that it's "allowed even when disallowed" when it
1186 // "has caller restrictions"
1187 boolean evenWhenDisallowed = hasCallerRestrictions;
1188 int result = mUserManager.removeUserOrSetEphemeral(userId, evenWhenDisallowed);
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001189 if (result == UserManager.REMOVE_RESULT_ERROR) {
Mayank Gargc9266482021-03-01 10:27:37 -08001190 sendUserRemovalResult(userId, UserRemovalResult.STATUS_ANDROID_FAILURE, receiver);
1191 return;
Mayank Garga55c3092020-05-28 03:19:24 -07001192 }
1193
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001194 if (isLastAdmin) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001195 Slog.w(TAG,
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001196 "Last admin user successfully removed or set ephemeral. User Id: " + userId);
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001197 }
1198
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001199 switch (result) {
1200 case UserManager.REMOVE_RESULT_REMOVED:
1201 case UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED:
Mayank Gargc9266482021-03-01 10:27:37 -08001202 sendUserRemovalResult(userId,
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001203 isLastAdmin ? UserRemovalResult.STATUS_SUCCESSFUL_LAST_ADMIN_REMOVED
Mayank Gargc9266482021-03-01 10:27:37 -08001204 : UserRemovalResult.STATUS_SUCCESSFUL, receiver);
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001205 case UserManager.REMOVE_RESULT_SET_EPHEMERAL:
Mayank Gargc9266482021-03-01 10:27:37 -08001206 sendUserRemovalResult(userId,
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001207 isLastAdmin ? UserRemovalResult.STATUS_SUCCESSFUL_LAST_ADMIN_SET_EPHEMERAL
Mayank Gargc9266482021-03-01 10:27:37 -08001208 : UserRemovalResult.STATUS_SUCCESSFUL_SET_EPHEMERAL, receiver);
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001209 default:
Mayank Gargc9266482021-03-01 10:27:37 -08001210 sendUserRemovalResult(userId, UserRemovalResult.STATUS_ANDROID_FAILURE, receiver);
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001211 }
Mayank Garga55c3092020-05-28 03:19:24 -07001212 }
1213
Felipe Leme67d564c2020-11-13 15:35:34 -08001214 /**
1215 * Should be called by {@code ICarImpl} only.
1216 */
1217 public void onUserRemoved(@NonNull UserInfo user) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001218 if (Log.isLoggable(TAG, Log.DEBUG)) {
1219 Slog.d(TAG, "onUserRemoved: " + user.toFullString());
Felipe Leme67d564c2020-11-13 15:35:34 -08001220 }
1221 notifyHalUserRemoved(user);
1222 }
1223
1224 private void notifyHalUserRemoved(@NonNull UserInfo user) {
Felipe Leme6b34fc32020-10-26 15:49:17 -07001225 if (!isUserHalSupported()) return;
1226
Felipe Leme67d564c2020-11-13 15:35:34 -08001227 if (user == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001228 Slog.wtf(TAG, "notifyHalUserRemoved() called for null user");
Felipe Leme67d564c2020-11-13 15:35:34 -08001229 return;
1230 }
1231
1232 int userId = user.id;
1233
Felipe Leme6b34fc32020-10-26 15:49:17 -07001234 if (userId == UserHandle.USER_NULL) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001235 Slog.wtf(TAG, "notifyHalUserRemoved() called for UserHandle.USER_NULL");
Felipe Leme6b34fc32020-10-26 15:49:17 -07001236 return;
1237 }
1238
1239 synchronized (mLockUser) {
1240 if (mFailedToCreateUserIds.get(userId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001241 if (Log.isLoggable(TAG, Log.DEBUG)) {
1242 Slog.d(TAG, "notifyHalUserRemoved(): skipping " + userId);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001243 }
1244 mFailedToCreateUserIds.delete(userId);
1245 return;
1246 }
1247 }
1248
1249 android.hardware.automotive.vehicle.V2_0.UserInfo halUser =
1250 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1251 halUser.userId = userId;
Felipe Leme67d564c2020-11-13 15:35:34 -08001252 halUser.flags = UserHalHelper.convertFlags(user);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001253
1254 RemoveUserRequest request = new RemoveUserRequest();
1255 request.removedUserInfo = halUser;
1256 request.usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1257 mHal.removeUser(request);
1258 }
1259
Mayank Gargc9266482021-03-01 10:27:37 -08001260 private void sendUserRemovalResult(@UserIdInt int userId, @UserRemovalResult.Status int result,
1261 AndroidFuture<UserRemovalResult> receiver) {
Mayank Garga55c3092020-05-28 03:19:24 -07001262 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_REMOVE_USER_RESP, userId, result);
Mayank Gargc9266482021-03-01 10:27:37 -08001263 receiver.complete(new UserRemovalResult(result));
Mayank Garga55c3092020-05-28 03:19:24 -07001264 }
1265
Mayank Garg587f1942020-05-06 01:41:34 -07001266 private void sendUserSwitchUiCallback(@UserIdInt int targetUserId) {
1267 if (mUserSwitchUiReceiver == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001268 Slog.w(TAG, "No User switch UI receiver.");
Mayank Garg587f1942020-05-06 01:41:34 -07001269 return;
1270 }
1271
felipealdfdf8512020-06-01 09:35:45 -07001272 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_UI_REQ, targetUserId);
Mayank Garg587f1942020-05-06 01:41:34 -07001273 try {
Mayank Garg587f1942020-05-06 01:41:34 -07001274 mUserSwitchUiReceiver.send(targetUserId, null);
1275 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001276 Slog.e(TAG, "Error calling user switch UI receiver.", e);
Mayank Garg587f1942020-05-06 01:41:34 -07001277 }
1278 }
1279
Felipe Lemecceb2992020-11-18 18:22:44 -08001280 /**
1281 * Used to create the initial user, even when it's disallowed by {@code DevicePolicyManager}.
1282 */
1283 @Nullable
1284 UserInfo createUserEvenWhenDisallowed(@Nullable String name, @NonNull String userType,
1285 @UserInfoFlag int flags) {
1286 if (mICarServiceHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001287 Slog.wtf(TAG, "createUserEvenWhenDisallowed(): mICarServiceHelper not set yet",
Felipe Lemecceb2992020-11-18 18:22:44 -08001288 new Exception());
1289 return null;
1290 }
1291 try {
1292 return mICarServiceHelper.createUserEvenWhenDisallowed(name, userType, flags);
1293 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001294 Slog.e(TAG, "createUserEvenWhenDisallowed(" + UserHelperLite.safeName(name) + ", "
Felipe Lemecceb2992020-11-18 18:22:44 -08001295 + userType + ", " + UserInfo.flagsToString(flags) + ") failed", e);
1296 return null;
1297 }
1298 }
1299
felipeal5e3ede42020-04-23 18:04:07 -07001300 @Override
felipealdfdf8512020-06-01 09:35:45 -07001301 public void createUser(@Nullable String name, @NonNull String userType, @UserInfoFlag int flags,
1302 int timeoutMs, @NonNull AndroidFuture<UserCreationResult> receiver) {
Felipe Leme8c888ab2020-11-02 17:39:52 -08001303 createUser(name, userType, flags, timeoutMs, receiver, /* hasCallerRestrictions= */ false);
1304 }
1305
1306 /**
1307 * Internal implementation of {@code createUser()}, which is used by both
1308 * {@code ICarUserService} and {@code ICarDevicePolicyService}.
1309 *
1310 * @param hasCallerRestrictions when {@code true}, if the caller user is not an admin, it can
1311 * only create admin users
1312 */
1313 public void createUser(@Nullable String name, @NonNull String userType, @UserInfoFlag int flags,
1314 int timeoutMs, @NonNull AndroidFuture<UserCreationResult> receiver,
1315 boolean hasCallerRestrictions) {
felipealdfdf8512020-06-01 09:35:45 -07001316 Objects.requireNonNull(userType, "user type cannot be null");
1317 Objects.requireNonNull(receiver, "receiver cannot be null");
Felipe Leme17799202020-09-03 12:55:53 -07001318 checkManageOrCreateUsersPermission(flags);
Mayank Garg94f3eb92020-08-12 12:38:58 -07001319 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_REQ,
Felipe Leme8c888ab2020-11-02 17:39:52 -08001320 UserHelperLite.safeName(name), userType, flags, timeoutMs,
1321 hasCallerRestrictions ? 1 : 0);
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001322 mHandler.post(() -> handleCreateUser(name, userType, flags, timeoutMs, receiver,
Mayank Garg02576972021-02-18 16:46:07 -08001323 hasCallerRestrictions));
Felipe Leme8c888ab2020-11-02 17:39:52 -08001324
Mayank Garg02576972021-02-18 16:46:07 -08001325 }
1326
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001327 private void handleCreateUser(@Nullable String name, @NonNull String userType,
Mayank Garg02576972021-02-18 16:46:07 -08001328 @UserInfoFlag int flags, int timeoutMs,
1329 @NonNull AndroidFuture<UserCreationResult> receiver,
1330 boolean hasCallerRestrictions) {
Felipe Leme8c888ab2020-11-02 17:39:52 -08001331 if (hasCallerRestrictions) {
1332 // Restrictions:
1333 // - type/flag can only be normal user, admin, or guest
1334 // - non-admin user can only create non-admin users
1335
1336 boolean validCombination;
1337 switch (userType) {
1338 case UserManager.USER_TYPE_FULL_SECONDARY:
1339 validCombination = flags == 0
1340 || (flags & UserInfo.FLAG_ADMIN) == UserInfo.FLAG_ADMIN;
1341 break;
1342 case UserManager.USER_TYPE_FULL_GUEST:
1343 validCombination = flags == 0;
1344 break;
1345 default:
1346 validCombination = false;
1347 }
1348 if (!validCombination) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001349 if (Log.isLoggable(TAG, Log.DEBUG)) {
1350 Slog.d(TAG, "Invalid combination of user type(" + userType
Felipe Leme71d296f2020-11-04 12:11:42 -08001351 + ") and flags (" + UserInfo.flagsToString(flags)
1352 + ") for caller with restrictions");
1353 }
1354 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_INVALID_REQUEST);
1355 return;
1356
Felipe Leme8c888ab2020-11-02 17:39:52 -08001357 }
1358
1359 int callingUserId = Binder.getCallingUserHandle().getIdentifier();
1360 UserInfo callingUser = mUserManager.getUserInfo(callingUserId);
1361 if (!callingUser.isAdmin() && (flags & UserInfo.FLAG_ADMIN) == UserInfo.FLAG_ADMIN) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001362 if (Log.isLoggable(TAG, Log.DEBUG)) {
1363 Slog.d(TAG, "Non-admin user " + callingUserId
Felipe Leme71d296f2020-11-04 12:11:42 -08001364 + " can only create non-admin users");
1365 }
1366 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_INVALID_REQUEST);
1367 return;
Felipe Leme8c888ab2020-11-02 17:39:52 -08001368 }
Felipe Leme71d296f2020-11-04 12:11:42 -08001369
Felipe Leme8c888ab2020-11-02 17:39:52 -08001370 }
felipealdfdf8512020-06-01 09:35:45 -07001371
1372 UserInfo newUser;
1373 try {
1374 newUser = mUserManager.createUser(name, userType, flags);
1375 if (newUser == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001376 Slog.w(TAG, "um.createUser() returned null for user of type " + userType
felipealdfdf8512020-06-01 09:35:45 -07001377 + " and flags " + UserInfo.flagsToString(flags));
1378 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_ANDROID_FAILURE);
1379 return;
1380 }
Eric Jeongf75d4132020-12-21 13:48:23 -08001381 if (Log.isLoggable(TAG, Log.DEBUG)) {
1382 Slog.d(TAG, "Created user: " + newUser.toFullString());
felipealdfdf8512020-06-01 09:35:45 -07001383 }
1384 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_USER_CREATED, newUser.id,
Mayank Garg94f3eb92020-08-12 12:38:58 -07001385 UserHelperLite.safeName(newUser.name), newUser.userType, newUser.flags);
felipealdfdf8512020-06-01 09:35:45 -07001386 } catch (RuntimeException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001387 Slog.e(TAG, "Error creating user of type " + userType + " and flags"
felipealdfdf8512020-06-01 09:35:45 -07001388 + UserInfo.flagsToString(flags), e);
1389 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_ANDROID_FAILURE);
1390 return;
1391 }
1392
Mayank Garg9ed099e2020-06-04 16:05:20 -07001393 if (!isUserHalSupported()) {
1394 sendUserCreationResult(receiver, UserCreationResult.STATUS_SUCCESSFUL, newUser, null);
1395 return;
1396 }
1397
felipealdfdf8512020-06-01 09:35:45 -07001398 CreateUserRequest request = new CreateUserRequest();
1399 request.usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1400 if (!TextUtils.isEmpty(name)) {
1401 request.newUserName = name;
1402 }
1403 request.newUserInfo.userId = newUser.id;
1404 request.newUserInfo.flags = UserHalHelper.convertFlags(newUser);
Eric Jeongf75d4132020-12-21 13:48:23 -08001405 if (Log.isLoggable(TAG, Log.DEBUG)) {
1406 Slog.d(TAG, "Create user request: " + request);
felipealdfdf8512020-06-01 09:35:45 -07001407 }
1408
1409 try {
1410 mHal.createUser(request, timeoutMs, (status, resp) -> {
1411 int resultStatus = UserCreationResult.STATUS_HAL_INTERNAL_FAILURE;
Eric Jeongf75d4132020-12-21 13:48:23 -08001412 if (Log.isLoggable(TAG, Log.DEBUG)) {
1413 Slog.d(TAG, "createUserResponse: status="
felipealdfdf8512020-06-01 09:35:45 -07001414 + UserHalHelper.halCallbackStatusToString(status) + ", resp=" + resp);
1415 }
1416 UserInfo user = null; // user returned in the result
1417 if (status != HalCallback.STATUS_OK) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001418 Slog.w(TAG, "invalid callback status ("
felipealdfdf8512020-06-01 09:35:45 -07001419 + UserHalHelper.halCallbackStatusToString(status) + ") for response "
1420 + resp);
1421 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_RESP, status,
1422 resultStatus, resp.errorMessage);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001423 removeCreatedUser(newUser, "HAL call failed with "
felipealdfdf8512020-06-01 09:35:45 -07001424 + UserHalHelper.halCallbackStatusToString(status));
1425 sendUserCreationResult(receiver, resultStatus, user, /* errorMsg= */ null);
1426 return;
1427 }
1428
1429 switch (resp.status) {
1430 case CreateUserStatus.SUCCESS:
1431 resultStatus = UserCreationResult.STATUS_SUCCESSFUL;
1432 user = newUser;
1433 break;
1434 case CreateUserStatus.FAILURE:
1435 // HAL failed to switch user
1436 resultStatus = UserCreationResult.STATUS_HAL_FAILURE;
1437 break;
1438 default:
1439 // Shouldn't happen because UserHalService validates the status
Eric Jeongf75d4132020-12-21 13:48:23 -08001440 Slog.wtf(TAG, "Received invalid user switch status from HAL: " + resp);
felipealdfdf8512020-06-01 09:35:45 -07001441 }
1442 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_RESP, status,
1443 resultStatus, resp.errorMessage);
1444 if (user == null) {
Felipe Leme6b34fc32020-10-26 15:49:17 -07001445 removeCreatedUser(newUser, "HAL returned "
felipealdfdf8512020-06-01 09:35:45 -07001446 + UserCreationResult.statusToString(resultStatus));
1447 }
1448 sendUserCreationResult(receiver, resultStatus, user, resp.errorMessage);
1449 });
1450 } catch (Exception e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001451 Slog.w(TAG, "mHal.createUser(" + request + ") failed", e);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001452 removeCreatedUser(newUser, "mHal.createUser() failed");
felipealdfdf8512020-06-01 09:35:45 -07001453 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_HAL_INTERNAL_FAILURE);
1454 }
1455 }
1456
Felipe Leme6b34fc32020-10-26 15:49:17 -07001457 private void removeCreatedUser(@NonNull UserInfo user, @NonNull String reason) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001458 Slog.i(TAG, "removing " + user.toFullString() + "; reason: " + reason);
Felipe Leme67d564c2020-11-13 15:35:34 -08001459
Felipe Leme6b34fc32020-10-26 15:49:17 -07001460 int userId = user.id;
1461 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_USER_REMOVED, userId, reason);
1462
1463 synchronized (mLockUser) {
1464 mFailedToCreateUserIds.put(userId, true);
1465 }
1466
felipealdfdf8512020-06-01 09:35:45 -07001467 try {
Felipe Leme6b34fc32020-10-26 15:49:17 -07001468 if (!mUserManager.removeUser(userId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001469 Slog.w(TAG, "Failed to remove user " + user.toFullString());
felipealdfdf8512020-06-01 09:35:45 -07001470 }
1471 } catch (Exception e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001472 Slog.e(TAG, "Failed to remove user " + user.toFullString(), e);
felipealdfdf8512020-06-01 09:35:45 -07001473 }
1474 }
1475
1476 @Override
Mayank Garg3f566582020-10-02 22:10:16 -07001477 public UserIdentificationAssociationResponse getUserIdentificationAssociation(
1478 @UserIdentificationAssociationType int[] types) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001479 if (!isUserHalUserAssociationSupported()) {
1480 return UserIdentificationAssociationResponse.forFailure(VEHICLE_HAL_NOT_SUPPORTED);
1481 }
1482
felipeal5e3ede42020-04-23 18:04:07 -07001483 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type");
Felipe Leme17799202020-09-03 12:55:53 -07001484 checkManageOrCreateUsersPermission("getUserIdentificationAssociation");
felipeal5e3ede42020-04-23 18:04:07 -07001485
1486 int uid = getCallingUid();
1487 int userId = UserHandle.getUserId(uid);
1488 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_GET_USER_AUTH_REQ, uid, userId);
1489
1490 UserIdentificationGetRequest request = new UserIdentificationGetRequest();
1491 request.userInfo.userId = userId;
1492 request.userInfo.flags = getHalUserInfoFlags(userId);
1493
1494 request.numberAssociationTypes = types.length;
1495 for (int i = 0; i < types.length; i++) {
1496 request.associationTypes.add(types[i]);
1497 }
1498
1499 UserIdentificationResponse halResponse = mHal.getUserAssociation(request);
1500 if (halResponse == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001501 Slog.w(TAG, "getUserIdentificationAssociation(): HAL returned null for "
felipeal5e3ede42020-04-23 18:04:07 -07001502 + Arrays.toString(types));
felipeal159a2a42020-05-08 10:32:11 -07001503 return UserIdentificationAssociationResponse.forFailure();
felipeal5e3ede42020-04-23 18:04:07 -07001504 }
1505
1506 int[] values = new int[halResponse.associations.size()];
1507 for (int i = 0; i < values.length; i++) {
1508 values[i] = halResponse.associations.get(i).value;
1509 }
1510 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_GET_USER_AUTH_RESP, values.length);
1511
felipeal159a2a42020-05-08 10:32:11 -07001512 return UserIdentificationAssociationResponse.forSuccess(values, halResponse.errorMessage);
1513 }
1514
1515 @Override
Mayank Garg3f566582020-10-02 22:10:16 -07001516 public void setUserIdentificationAssociation(int timeoutMs,
1517 @UserIdentificationAssociationType int[] types,
1518 @UserIdentificationAssociationSetValue int[] values,
felipeal159a2a42020-05-08 10:32:11 -07001519 AndroidFuture<UserIdentificationAssociationResponse> result) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001520 if (!isUserHalUserAssociationSupported()) {
1521 result.complete(
1522 UserIdentificationAssociationResponse.forFailure(VEHICLE_HAL_NOT_SUPPORTED));
1523 return;
1524 }
1525
felipeal159a2a42020-05-08 10:32:11 -07001526 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type");
1527 Preconditions.checkArgument(!ArrayUtils.isEmpty(values), "must have at least one value");
1528 if (types.length != values.length) {
1529 throw new IllegalArgumentException("types (" + Arrays.toString(types) + ") and values ("
1530 + Arrays.toString(values) + ") should have the same length");
1531 }
Felipe Leme17799202020-09-03 12:55:53 -07001532 checkManageOrCreateUsersPermission("setUserIdentificationAssociation");
felipeal159a2a42020-05-08 10:32:11 -07001533
1534 int uid = getCallingUid();
1535 int userId = UserHandle.getUserId(uid);
1536 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_REQ, uid, userId, types.length);
1537
1538 UserIdentificationSetRequest request = new UserIdentificationSetRequest();
1539 request.userInfo.userId = userId;
1540 request.userInfo.flags = getHalUserInfoFlags(userId);
1541
1542 request.numberAssociations = types.length;
1543 for (int i = 0; i < types.length; i++) {
1544 UserIdentificationSetAssociation association = new UserIdentificationSetAssociation();
1545 association.type = types[i];
1546 association.value = values[i];
1547 request.associations.add(association);
1548 }
1549
1550 mHal.setUserAssociation(timeoutMs, request, (status, resp) -> {
1551 if (status != HalCallback.STATUS_OK) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001552 Slog.w(TAG, "setUserIdentificationAssociation(): invalid callback status ("
felipeal159a2a42020-05-08 10:32:11 -07001553 + UserHalHelper.halCallbackStatusToString(status) + ") for response "
1554 + resp);
1555 if (resp == null || TextUtils.isEmpty(resp.errorMessage)) {
1556 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, 0);
1557 result.complete(UserIdentificationAssociationResponse.forFailure());
1558 return;
1559 }
1560 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, 0,
1561 resp.errorMessage);
1562 result.complete(
1563 UserIdentificationAssociationResponse.forFailure(resp.errorMessage));
1564 return;
1565 }
1566 int respSize = resp.associations.size();
1567 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, respSize,
1568 resp.errorMessage);
1569
1570 int[] responseTypes = new int[respSize];
1571 for (int i = 0; i < respSize; i++) {
1572 responseTypes[i] = resp.associations.get(i).value;
1573 }
1574 UserIdentificationAssociationResponse response = UserIdentificationAssociationResponse
1575 .forSuccess(responseTypes, resp.errorMessage);
Eric Jeongf75d4132020-12-21 13:48:23 -08001576 if (Log.isLoggable(TAG, Log.DEBUG)) {
1577 Slog.d(TAG, "setUserIdentificationAssociation(): resp= " + resp
felipeal159a2a42020-05-08 10:32:11 -07001578 + ", converted=" + response);
1579 }
1580 result.complete(response);
1581 });
felipeal5e3ede42020-04-23 18:04:07 -07001582 }
1583
1584 /**
1585 * Gets the User HAL flags for the given user.
1586 *
1587 * @throws IllegalArgumentException if the user does not exist.
1588 */
1589 private int getHalUserInfoFlags(@UserIdInt int userId) {
1590 UserInfo user = mUserManager.getUserInfo(userId);
1591 Preconditions.checkArgument(user != null, "no user for id %d", userId);
1592 return UserHalHelper.convertFlags(user);
1593 }
1594
Mayank Garg0e239142020-04-14 19:16:31 -07001595 private void sendResult(@NonNull IResultReceiver receiver, int resultCode,
1596 @Nullable Bundle resultData) {
1597 try {
1598 receiver.send(resultCode, resultData);
1599 } catch (RemoteException e) {
1600 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001601 Slog.w(TAG, "error while sending results", e);
Mayank Garg0e239142020-04-14 19:16:31 -07001602 }
1603 }
1604
felipealdfdf8512020-06-01 09:35:45 -07001605 private void sendUserSwitchResult(@NonNull AndroidFuture<UserSwitchResult> receiver,
Felipe Leme5d5ab142020-10-27 13:49:10 -07001606 @UserSwitchResult.Status int userSwitchStatus) {
1607 sendUserSwitchResult(receiver, HalCallback.STATUS_INVALID, userSwitchStatus,
1608 /* errorMessage= */ null);
felipeale5bf0322020-04-16 15:10:57 -07001609 }
1610
felipealdfdf8512020-06-01 09:35:45 -07001611 private void sendUserSwitchResult(@NonNull AndroidFuture<UserSwitchResult> receiver,
Felipe Leme5d5ab142020-10-27 13:49:10 -07001612 @HalCallback.HalCallbackStatus int halCallbackStatus,
1613 @UserSwitchResult.Status int userSwitchStatus, @Nullable String errorMessage) {
1614 if (errorMessage != null) {
1615 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_RESP, halCallbackStatus,
1616 userSwitchStatus, errorMessage);
1617 } else {
1618 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_RESP, halCallbackStatus,
1619 userSwitchStatus);
1620 }
1621 receiver.complete(new UserSwitchResult(userSwitchStatus, errorMessage));
felipeale5bf0322020-04-16 15:10:57 -07001622 }
1623
felipealdfdf8512020-06-01 09:35:45 -07001624 private void sendUserCreationResultFailure(@NonNull AndroidFuture<UserCreationResult> receiver,
1625 @UserCreationResult.Status int status) {
1626 sendUserCreationResult(receiver, status, /* user= */ null, /* errorMessage= */ null);
1627 }
1628
1629 private void sendUserCreationResult(@NonNull AndroidFuture<UserCreationResult> receiver,
1630 @UserCreationResult.Status int status, @NonNull UserInfo user,
1631 @Nullable String errorMessage) {
1632 if (TextUtils.isEmpty(errorMessage)) {
1633 errorMessage = null;
1634 }
1635 receiver.complete(new UserCreationResult(status, user, errorMessage));
1636 }
1637
Mayank Garg6307fe42020-04-15 23:09:03 -07001638 /**
1639 * Calls activity manager for user switch.
1640 *
1641 * <p><b>NOTE</b> This method is meant to be called just by UserHalService.
1642 *
1643 * @param requestId for the user switch request
1644 * @param targetUserId of the target user
1645 *
1646 * @hide
1647 */
1648 public void switchAndroidUserFromHal(int requestId, @UserIdInt int targetUserId) {
1649 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_FROM_HAL_REQ, requestId,
1650 targetUserId);
Eric Jeongf75d4132020-12-21 13:48:23 -08001651 Slog.i(TAG, "User hal requested a user switch. Target user id " + targetUserId);
Mayank Garg6307fe42020-04-15 23:09:03 -07001652
1653 try {
1654 boolean result = mAm.switchUser(targetUserId);
1655 if (result) {
1656 updateUserSwitchInProcess(requestId, targetUserId);
1657 } else {
1658 postSwitchHalResponse(requestId, targetUserId);
1659 }
1660 } catch (RemoteException e) {
1661 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001662 Slog.w(TAG, "error while switching user " + targetUserId, e);
Mayank Garg6307fe42020-04-15 23:09:03 -07001663 }
1664 }
1665
1666 private void updateUserSwitchInProcess(int requestId, @UserIdInt int targetUserId) {
1667 synchronized (mLockUser) {
1668 if (mUserIdForUserSwitchInProcess != UserHandle.USER_NULL) {
1669 // Some other user switch is in process.
Eric Jeongf75d4132020-12-21 13:48:23 -08001670 if (Log.isLoggable(TAG, Log.DEBUG)) {
1671 Slog.d(TAG, "User switch for user: " + mUserIdForUserSwitchInProcess
Mayank Garg6307fe42020-04-15 23:09:03 -07001672 + " is in process. Abandoning it as a new user switch is requested"
1673 + " for the target user: " + targetUserId);
1674 }
1675 }
1676 mUserIdForUserSwitchInProcess = targetUserId;
1677 mRequestIdForUserSwitchInProcess = requestId;
1678 }
1679 }
Mayank Garg9ed099e2020-06-04 16:05:20 -07001680
Mayank Garg7a114c82020-04-08 21:25:06 -07001681 private void postSwitchHalResponse(int requestId, @UserIdInt int targetUserId) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001682 if (!isUserHalSupported()) return;
1683
felipealdfdf8512020-06-01 09:35:45 -07001684 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
Mayank Gargeb37d092020-06-02 14:37:57 -07001685 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_POST_SWITCH_USER_REQ, requestId,
1686 targetUserId, usersInfo.currentUser.userId);
1687 SwitchUserRequest request = createUserSwitchRequest(targetUserId, usersInfo);
1688 request.requestId = requestId;
1689 mHal.postSwitchResponse(request);
1690 }
1691
1692 private SwitchUserRequest createUserSwitchRequest(@UserIdInt int targetUserId,
1693 @NonNull UsersInfo usersInfo) {
1694 UserInfo targetUser = mUserManager.getUserInfo(targetUserId);
Mayank Garg7a114c82020-04-08 21:25:06 -07001695 android.hardware.automotive.vehicle.V2_0.UserInfo halTargetUser =
1696 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1697 halTargetUser.userId = targetUser.id;
1698 halTargetUser.flags = UserHalHelper.convertFlags(targetUser);
Mayank Gargeb37d092020-06-02 14:37:57 -07001699 SwitchUserRequest request = new SwitchUserRequest();
1700 request.targetUser = halTargetUser;
1701 request.usersInfo = usersInfo;
1702 return request;
Mayank Garg7a114c82020-04-08 21:25:06 -07001703 }
1704
Mayank Garg59f22192020-03-27 00:51:45 -07001705 /**
Felipe Lemee3cab982020-03-12 11:39:29 -07001706 * Checks if the User HAL is supported.
1707 */
1708 public boolean isUserHalSupported() {
1709 return mHal.isSupported();
1710 }
1711
Mayank Garg587f1942020-05-06 01:41:34 -07001712 /**
Mayank Garg9ed099e2020-06-04 16:05:20 -07001713 * Checks if the User HAL user association is supported.
1714 */
1715 @Override
1716 public boolean isUserHalUserAssociationSupported() {
1717 return mHal.isUserAssociationSupported();
1718 }
1719
1720 /**
Mayank Garg587f1942020-05-06 01:41:34 -07001721 * Sets a callback which is invoked before user switch.
1722 *
1723 * <p>
1724 * This method should only be called by the Car System UI. The purpose of this call is to notify
1725 * Car System UI to show the user switch UI before the user switch.
1726 */
1727 @Override
1728 public void setUserSwitchUiCallback(@NonNull IResultReceiver receiver) {
Yan Zhu67a383e2020-05-11 20:46:24 -07001729 checkManageUsersPermission("setUserSwitchUiCallback");
Mayank Garga480dd92020-05-14 03:14:57 -07001730
1731 // Confirm that caller is system UI.
1732 String systemUiPackageName = getSystemUiPackageName();
1733 if (systemUiPackageName == null) {
1734 throw new IllegalStateException("System UI package not found.");
1735 }
1736
1737 try {
1738 int systemUiUid = mContext
1739 .createContextAsUser(UserHandle.SYSTEM, /* flags= */ 0).getPackageManager()
1740 .getPackageUid(systemUiPackageName, PackageManager.MATCH_SYSTEM_ONLY);
1741 int callerUid = Binder.getCallingUid();
1742 if (systemUiUid != callerUid) {
1743 throw new SecurityException("Invalid caller. Only" + systemUiPackageName
1744 + " is allowed to make this call");
1745 }
1746 } catch (NameNotFoundException e) {
1747 throw new IllegalStateException("Package " + systemUiPackageName + " not found.");
1748 }
1749
Mayank Garg587f1942020-05-06 01:41:34 -07001750 mUserSwitchUiReceiver = receiver;
1751 }
1752
Mayank Garga480dd92020-05-14 03:14:57 -07001753 // TODO(157082995): This information can be taken from
1754 // PackageManageInternalImpl.getSystemUiServiceComponent
1755 @Nullable
1756 private String getSystemUiPackageName() {
1757 try {
1758 ComponentName componentName = ComponentName.unflattenFromString(mContext.getResources()
1759 .getString(com.android.internal.R.string.config_systemUIServiceComponent));
1760 return componentName.getPackageName();
1761 } catch (RuntimeException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001762 Slog.w(TAG, "error while getting system UI package name.", e);
Mayank Garga480dd92020-05-14 03:14:57 -07001763 return null;
1764 }
1765 }
1766
Keun young Park13a7a822019-04-04 15:53:08 -07001767 private void updateDefaultUserRestriction() {
1768 // We want to set restrictions on system and guest users only once. These are persisted
1769 // onto disk, so it's sufficient to do it once + we minimize the number of disk writes.
1770 if (Settings.Global.getInt(mContext.getContentResolver(),
Eric Jeong1545f3b2019-09-16 13:56:52 -07001771 CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, /* default= */ 0) != 0) {
1772 return;
Keun young Park13a7a822019-04-04 15:53:08 -07001773 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07001774 // Only apply the system user restrictions if the system user is headless.
1775 if (UserManager.isHeadlessSystemUserMode()) {
1776 setSystemUserRestrictions();
1777 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07001778 Settings.Global.putInt(mContext.getContentResolver(),
1779 CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, 1);
Keun young Park13a7a822019-04-04 15:53:08 -07001780 }
1781
Eric Jeong1545f3b2019-09-16 13:56:52 -07001782 private boolean isPersistentUser(@UserIdInt int userId) {
Anthony Hugh9932a252019-06-12 16:19:56 -07001783 return !mUserManager.getUserInfo(userId).isEphemeral();
1784 }
1785
Antonio Kantekc8114752020-03-05 21:37:39 -08001786 /**
Antonio Kantekc8114752020-03-05 21:37:39 -08001787 * Adds a new {@link UserLifecycleListener} to listen to user activity events.
1788 */
1789 public void addUserLifecycleListener(@NonNull UserLifecycleListener listener) {
1790 Objects.requireNonNull(listener, "listener cannot be null");
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001791 mHandler.post(() -> mUserLifecycleListeners.add(listener));
Antonio Kantekc8114752020-03-05 21:37:39 -08001792 }
1793
1794 /**
1795 * Removes previously added {@link UserLifecycleListener}.
1796 */
1797 public void removeUserLifecycleListener(@NonNull UserLifecycleListener listener) {
1798 Objects.requireNonNull(listener, "listener cannot be null");
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001799 mHandler.post(() -> mUserLifecycleListeners.remove(listener));
Antonio Kantekc8114752020-03-05 21:37:39 -08001800 }
1801
Eric Jeongc91f9452019-08-30 15:04:21 -07001802 /** Adds callback to listen to passenger activity events. */
1803 public void addPassengerCallback(@NonNull PassengerCallback callback) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00001804 Objects.requireNonNull(callback, "callback cannot be null");
Eric Jeongc91f9452019-08-30 15:04:21 -07001805 mPassengerCallbacks.add(callback);
1806 }
1807
1808 /** Removes previously added callback to listen passenger events. */
1809 public void removePassengerCallback(@NonNull PassengerCallback callback) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00001810 Objects.requireNonNull(callback, "callback cannot be null");
Eric Jeongc91f9452019-08-30 15:04:21 -07001811 mPassengerCallbacks.remove(callback);
1812 }
1813
1814 /** Sets the implementation of ZoneUserBindingHelper. */
1815 public void setZoneUserBindingHelper(@NonNull ZoneUserBindingHelper helper) {
1816 synchronized (mLockHelper) {
1817 mZoneUserBindingHelper = helper;
1818 }
1819 }
1820
felipeal98900c82020-04-09 09:05:02 -07001821 private void onUserUnlocked(@UserIdInt int userId) {
Keun-young Parkd462a912019-02-11 08:53:42 -08001822 ArrayList<Runnable> tasks = null;
Eric Jeongc91f9452019-08-30 15:04:21 -07001823 synchronized (mLockUser) {
Mayank Garg7a114c82020-04-08 21:25:06 -07001824 sendPostSwitchToHalLocked(userId);
Eric Jeong1545f3b2019-09-16 13:56:52 -07001825 if (userId == UserHandle.USER_SYSTEM) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001826 if (!mUser0Unlocked) { // user 0, unlocked, do this only once
1827 updateDefaultUserRestriction();
1828 tasks = new ArrayList<>(mUser0UnlockTasks);
1829 mUser0UnlockTasks.clear();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001830 mUser0Unlocked = true;
Keun young Parkf3523cd2019-04-08 10:09:17 -07001831 }
1832 } else { // none user0
Eric Jeong1545f3b2019-09-16 13:56:52 -07001833 Integer user = userId;
1834 if (isPersistentUser(userId)) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001835 // current foreground user should stay in top priority.
Anthony Hughfbb67762019-10-15 12:54:54 -07001836 if (userId == ActivityManager.getCurrentUser()) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001837 mBackgroundUsersToRestart.remove(user);
1838 mBackgroundUsersToRestart.add(0, user);
1839 }
1840 // -1 for user 0
1841 if (mBackgroundUsersToRestart.size() > (mMaxRunningUsers - 1)) {
Eric Jeong1545f3b2019-09-16 13:56:52 -07001842 int userToDrop = mBackgroundUsersToRestart.get(
Keun young Parkf3523cd2019-04-08 10:09:17 -07001843 mBackgroundUsersToRestart.size() - 1);
Eric Jeongf75d4132020-12-21 13:48:23 -08001844 Slog.i(TAG, "New user unlocked:" + userId
Keun young Parkf3523cd2019-04-08 10:09:17 -07001845 + ", dropping least recently user from restart list:" + userToDrop);
1846 // Drop the least recently used user.
1847 mBackgroundUsersToRestart.remove(mBackgroundUsersToRestart.size() - 1);
1848 }
1849 }
Keun-young Parkd462a912019-02-11 08:53:42 -08001850 }
1851 }
1852 if (tasks != null && tasks.size() > 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001853 Slog.d(TAG, "User0 unlocked, run queued tasks:" + tasks.size());
Keun-young Parkd462a912019-02-11 08:53:42 -08001854 for (Runnable r : tasks) {
1855 r.run();
1856 }
1857 }
1858 }
1859
1860 /**
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001861 * Starts the specified user in the background.
1862 *
1863 * @param userId user to start in background
1864 * @param receiver to post results
1865 */
1866 public void startUserInBackground(@UserIdInt int userId,
1867 @NonNull AndroidFuture<UserStartResult> receiver) {
bkchoi5ab7aa32021-04-27 11:50:53 -07001868 checkManageOrCreateUsersPermission("startUserInBackground");
1869 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_START_USER_IN_BACKGROUND_REQ, userId);
1870
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001871 mHandler.post(() -> handleStartUserInBackground(userId, receiver));
1872 }
1873
1874 private void handleStartUserInBackground(@UserIdInt int userId,
1875 @NonNull AndroidFuture<UserStartResult> receiver) {
1876 // If the requested user is the current user, do nothing and return success.
1877 if (ActivityManager.getCurrentUser() == userId) {
bkchoi5ab7aa32021-04-27 11:50:53 -07001878 sendUserStartResult(
1879 userId, UserStartResult.STATUS_SUCCESSFUL_USER_IS_CURRENT_USER, receiver);
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001880 return;
1881 }
1882 // If requested user does not exist, return error.
1883 if (mUserManager.getUserInfo(userId) == null) {
1884 Slogf.w(TAG, "User %d does not exist", userId);
bkchoi5ab7aa32021-04-27 11:50:53 -07001885 sendUserStartResult(userId, UserStartResult.STATUS_USER_DOES_NOT_EXIST, receiver);
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001886 return;
1887 }
1888
1889 try {
1890 if (!mAm.startUserInBackground(userId)) {
1891 Slogf.w(TAG, "Failed to start user %d in background", userId);
bkchoi5ab7aa32021-04-27 11:50:53 -07001892 sendUserStartResult(userId, UserStartResult.STATUS_ANDROID_FAILURE, receiver);
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001893 return;
1894 }
1895 } catch (RemoteException e) {
1896 Slogf.w(TAG, e, "Failed to start user %d in background", userId);
1897 }
1898
1899 // TODO(b/181331178): We are not updating mBackgroundUsersToRestart or
1900 // mBackgroundUsersRestartedHere, which were only used for the garage mode. Consider
1901 // renaming them to make it more clear.
bkchoi5ab7aa32021-04-27 11:50:53 -07001902 sendUserStartResult(userId, UserStartResult.STATUS_SUCCESSFUL, receiver);
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001903 }
1904
bkchoi5ab7aa32021-04-27 11:50:53 -07001905 private void sendUserStartResult(@UserIdInt int userId, @UserStartResult.Status int result,
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001906 @NonNull AndroidFuture<UserStartResult> receiver) {
bkchoi5ab7aa32021-04-27 11:50:53 -07001907 EventLog.writeEvent(
1908 EventLogTags.CAR_USER_SVC_START_USER_IN_BACKGROUND_RESP, userId, result);
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001909 receiver.complete(new UserStartResult(result));
1910 }
1911
1912 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -07001913 * Starts all background users that were active in system.
1914 *
Keun young Parkfb656372019-03-12 18:37:55 -07001915 * @return list of background users started successfully.
1916 */
Eric Jeong1545f3b2019-09-16 13:56:52 -07001917 @NonNull
Mayank Garg784a0862021-05-26 00:20:50 -07001918 public ArrayList<Integer> startAllBackgroundUsersInGarageMode() {
1919 synchronized (mLockUser) {
1920 if (!mStartBackgroundUsersOnGarageMode) {
1921 Slogf.i(TAG, "Background users are not started as mStartBackgroundUsersOnGarageMode"
1922 + " is false.");
1923 return new ArrayList<>();
1924 }
1925 }
1926
Keun young Parkfb656372019-03-12 18:37:55 -07001927 ArrayList<Integer> users;
Eric Jeongc91f9452019-08-30 15:04:21 -07001928 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001929 users = new ArrayList<>(mBackgroundUsersToRestart);
1930 mBackgroundUsersRestartedHere.clear();
1931 mBackgroundUsersRestartedHere.addAll(mBackgroundUsersToRestart);
Keun young Parkfb656372019-03-12 18:37:55 -07001932 }
1933 ArrayList<Integer> startedUsers = new ArrayList<>();
1934 for (Integer user : users) {
Anthony Hughfbb67762019-10-15 12:54:54 -07001935 if (user == ActivityManager.getCurrentUser()) {
Keun young Parkfb656372019-03-12 18:37:55 -07001936 continue;
1937 }
1938 try {
1939 if (mAm.startUserInBackground(user)) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001940 if (mUserManager.isUserUnlockingOrUnlocked(user)) {
1941 // already unlocked / unlocking. No need to unlock.
Keun young Parkfb656372019-03-12 18:37:55 -07001942 startedUsers.add(user);
Keun young Parkf3523cd2019-04-08 10:09:17 -07001943 } else if (mAm.unlockUser(user, null, null, null)) {
1944 startedUsers.add(user);
1945 } else { // started but cannot unlock
Eric Jeongf75d4132020-12-21 13:48:23 -08001946 Slog.w(TAG, "Background user started but cannot be unlocked:" + user);
Keun young Parkf3523cd2019-04-08 10:09:17 -07001947 if (mUserManager.isUserRunning(user)) {
1948 // add to started list so that it can be stopped later.
1949 startedUsers.add(user);
1950 }
Keun young Parkfb656372019-03-12 18:37:55 -07001951 }
1952 }
1953 } catch (RemoteException e) {
1954 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001955 Slog.w(TAG, "error while starting user in background", e);
Keun young Parkfb656372019-03-12 18:37:55 -07001956 }
1957 }
Keun young Parkf3523cd2019-04-08 10:09:17 -07001958 // Keep only users that were re-started in mBackgroundUsersRestartedHere
Eric Jeongc91f9452019-08-30 15:04:21 -07001959 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001960 ArrayList<Integer> usersToRemove = new ArrayList<>();
1961 for (Integer user : mBackgroundUsersToRestart) {
1962 if (!startedUsers.contains(user)) {
1963 usersToRemove.add(user);
1964 }
1965 }
1966 mBackgroundUsersRestartedHere.removeAll(usersToRemove);
1967 }
Keun young Parkfb656372019-03-12 18:37:55 -07001968 return startedUsers;
1969 }
1970
1971 /**
bkchoid77d0bc2021-04-22 13:43:03 -07001972 * Stops the specified background user.
1973 *
1974 * @param userId user to stop
1975 * @param receiver to post results
1976 */
1977 public void stopUser(@UserIdInt int userId, @NonNull AndroidFuture<UserStopResult> receiver) {
bkchoia8c7fb92021-04-28 10:58:57 -07001978 checkManageOrCreateUsersPermission("stopUser");
1979 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_STOP_USER_REQ, userId);
1980
bkchoid77d0bc2021-04-22 13:43:03 -07001981 mHandler.post(() -> handleStopUser(userId, receiver));
1982 }
1983
1984 private void handleStopUser(
1985 @UserIdInt int userId, @NonNull AndroidFuture<UserStopResult> receiver) {
1986 @UserStopResult.Status int userStopStatus = stopBackgroundUserInternal(userId);
bkchoia8c7fb92021-04-28 10:58:57 -07001987 sendUserStopResult(userId, userStopStatus, receiver);
bkchoid77d0bc2021-04-22 13:43:03 -07001988 }
1989
bkchoia8c7fb92021-04-28 10:58:57 -07001990 private void sendUserStopResult(@UserIdInt int userId, @UserStopResult.Status int result,
bkchoid77d0bc2021-04-22 13:43:03 -07001991 @NonNull AndroidFuture<UserStopResult> receiver) {
bkchoia8c7fb92021-04-28 10:58:57 -07001992 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_STOP_USER_RESP, userId, result);
bkchoid77d0bc2021-04-22 13:43:03 -07001993 receiver.complete(new UserStopResult(result));
1994 }
1995
1996 private @UserStopResult.Status int stopBackgroundUserInternal(@UserIdInt int userId) {
1997 try {
1998 int r = mAm.stopUserWithDelayedLocking(userId, true, null);
1999 switch(r) {
2000 case ActivityManager.USER_OP_SUCCESS:
2001 return UserStopResult.STATUS_SUCCESSFUL;
2002 case ActivityManager.USER_OP_ERROR_IS_SYSTEM:
2003 Slogf.w(TAG, "Cannot stop the system user: %d", userId);
2004 return UserStopResult.STATUS_FAILURE_SYSTEM_USER;
2005 case ActivityManager.USER_OP_IS_CURRENT:
2006 Slogf.w(TAG, "Cannot stop the current user: %d", userId);
2007 return UserStopResult.STATUS_FAILURE_CURRENT_USER;
2008 case ActivityManager.USER_OP_UNKNOWN_USER:
2009 Slogf.w(TAG, "Cannot stop the user that does not exist: %d", userId);
2010 return UserStopResult.STATUS_USER_DOES_NOT_EXIST;
2011 default:
2012 Slogf.w(TAG, "stopUser failed, user: %d, err: %d", userId, r);
2013 }
2014 } catch (RemoteException e) {
2015 // ignore the exception
2016 Slogf.w(TAG, e, "error while stopping user: %d", userId);
2017 }
2018 return UserStopResult.STATUS_ANDROID_FAILURE;
2019 }
2020
2021 /**
Mayank Garg784a0862021-05-26 00:20:50 -07002022 * Sets boolean to control background user operations during garage mode.
2023 */
2024 public void setStartBackgroundUsersOnGarageMode(boolean enable) {
2025 synchronized (mLockUser) {
2026 mStartBackgroundUsersOnGarageMode = enable;
2027 }
2028 }
2029
2030 /**
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07002031 * Stops a background user.
Eric Jeong1545f3b2019-09-16 13:56:52 -07002032 *
2033 * @return whether stopping succeeds.
Keun young Parkfb656372019-03-12 18:37:55 -07002034 */
Mayank Garg784a0862021-05-26 00:20:50 -07002035 public boolean stopBackgroundUserInGagageMode(@UserIdInt int userId) {
2036 synchronized (mLockUser) {
2037 if (!mStartBackgroundUsersOnGarageMode) {
2038 Slogf.i(TAG, "Background users are not stopped as mStartBackgroundUsersOnGarageMode"
2039 + " is false.");
2040 return false;
2041 }
2042 }
2043
bkchoid77d0bc2021-04-22 13:43:03 -07002044 @UserStopResult.Status int userStopStatus = stopBackgroundUserInternal(userId);
2045 if (UserStopResult.isSuccess(userStopStatus)) {
2046 // Remove the stopped user from the mBackgroundUserRestartedHere list.
2047 synchronized (mLockUser) {
2048 mBackgroundUsersRestartedHere.remove(Integer.valueOf(userId));
Keun young Parkfb656372019-03-12 18:37:55 -07002049 }
bkchoid77d0bc2021-04-22 13:43:03 -07002050 return true;
Keun young Parkfb656372019-03-12 18:37:55 -07002051 }
bkchoid77d0bc2021-04-22 13:43:03 -07002052 return false;
Keun young Parkfb656372019-03-12 18:37:55 -07002053 }
2054
2055 /**
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002056 * Notifies all registered {@link UserLifecycleListener} with the event passed as argument.
Pavel Maltsev17e81832019-04-04 14:38:41 -07002057 */
Mayank Gargccad8062020-08-30 15:05:10 -07002058 public void onUserLifecycleEvent(@UserLifecycleEventType int eventType,
felipeale8c5dce2020-04-15 11:27:06 -07002059 @UserIdInt int fromUserId, @UserIdInt int toUserId) {
2060 int userId = toUserId;
felipeal98900c82020-04-09 09:05:02 -07002061
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002062 // Handle special cases first...
felipeal98900c82020-04-09 09:05:02 -07002063 if (eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING) {
Mayank Garge5de0f92020-04-23 21:38:38 -07002064 onUserSwitching(fromUserId, toUserId);
felipeal98900c82020-04-09 09:05:02 -07002065 } else if (eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_UNLOCKED) {
2066 onUserUnlocked(userId);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002067 }
2068
felipeale8c5dce2020-04-15 11:27:06 -07002069 // ...then notify listeners.
Yan Zhue7921522020-04-16 15:59:25 -07002070 UserLifecycleEvent event = new UserLifecycleEvent(eventType, fromUserId, userId);
felipeale8c5dce2020-04-15 11:27:06 -07002071
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002072 mHandler.post(() -> {
2073 handleNotifyServiceUserLifecycleListeners(event);
2074 handleNotifyAppUserLifecycleListeners(event);
2075 });
felipeale8c5dce2020-04-15 11:27:06 -07002076 }
2077
Mayank Garg7a114c82020-04-08 21:25:06 -07002078 private void sendPostSwitchToHalLocked(@UserIdInt int userId) {
felipealf7368962020-04-16 12:55:19 -07002079 if (mUserIdForUserSwitchInProcess == UserHandle.USER_NULL
Mayank Garg1f20dcd2020-04-22 17:46:01 -07002080 || mUserIdForUserSwitchInProcess != userId
2081 || mRequestIdForUserSwitchInProcess == 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002082 if (Log.isLoggable(TAG, Log.DEBUG)) {
2083 Slog.d(TAG, "No user switch request Id. No android post switch sent.");
Mayank Garg7a114c82020-04-08 21:25:06 -07002084 }
2085 return;
2086 }
felipealf7368962020-04-16 12:55:19 -07002087 postSwitchHalResponse(mRequestIdForUserSwitchInProcess, mUserIdForUserSwitchInProcess);
2088 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
Mayank Garg1f20dcd2020-04-22 17:46:01 -07002089 mRequestIdForUserSwitchInProcess = 0;
Mayank Garg7a114c82020-04-08 21:25:06 -07002090 }
2091
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002092 private void handleNotifyAppUserLifecycleListeners(UserLifecycleEvent event) {
2093 int listenersSize = mAppLifecycleListeners.size();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002094 if (listenersSize == 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002095 if (Log.isLoggable(TAG, Log.DEBUG)) {
2096 Slog.d(TAG, "No app listener to be notified of " + event);
felipeal2a84d512020-04-06 18:52:15 -07002097 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002098 return;
2099 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002100 // Must use a different TimingsTraceLog because it's another thread
Eric Jeongf75d4132020-12-21 13:48:23 -08002101 if (Log.isLoggable(TAG, Log.DEBUG)) {
2102 Slog.d(TAG, "Notifying " + listenersSize + " app listeners of " + event);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002103 }
felipeal2a84d512020-04-06 18:52:15 -07002104 int userId = event.getUserId();
Eric Jeongf75d4132020-12-21 13:48:23 -08002105 TimingsTraceLog t = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
felipealde1e16d2020-06-03 13:20:48 -07002106 int eventType = event.getEventType();
2107 t.traceBegin("notify-app-listeners-user-" + userId + "-event-" + eventType);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002108 for (int i = 0; i < listenersSize; i++) {
2109 int uid = mAppLifecycleListeners.keyAt(i);
felipealde1e16d2020-06-03 13:20:48 -07002110
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002111 IResultReceiver listener = mAppLifecycleListeners.valueAt(i);
2112 Bundle data = new Bundle();
felipealde1e16d2020-06-03 13:20:48 -07002113 data.putInt(CarUserManager.BUNDLE_PARAM_ACTION, eventType);
Yan Zhue7921522020-04-16 15:59:25 -07002114
felipealde1e16d2020-06-03 13:20:48 -07002115 int fromUserId = event.getPreviousUserId();
2116 if (fromUserId != UserHandle.USER_NULL) {
2117 data.putInt(CarUserManager.BUNDLE_PARAM_PREVIOUS_USER_ID, fromUserId);
Yan Zhue7921522020-04-16 15:59:25 -07002118 }
2119
Eric Jeongf75d4132020-12-21 13:48:23 -08002120 if (Log.isLoggable(TAG, Log.DEBUG)) {
2121 Slog.d(TAG, "Notifying listener for uid " + uid);
felipeal2a84d512020-04-06 18:52:15 -07002122 }
felipealde1e16d2020-06-03 13:20:48 -07002123 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_NOTIFY_APP_LIFECYCLE_LISTENER,
2124 uid, eventType, fromUserId, userId);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002125 try {
felipealde1e16d2020-06-03 13:20:48 -07002126 t.traceBegin("notify-app-listener-uid-" + uid);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002127 listener.send(userId, data);
2128 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002129 Slog.e(TAG, "Error calling lifecycle listener", e);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002130 } finally {
2131 t.traceEnd();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002132 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002133 }
2134 t.traceEnd(); // notify-app-listeners-user-USERID-event-EVENT_TYPE
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002135 }
2136
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002137 private void handleNotifyServiceUserLifecycleListeners(UserLifecycleEvent event) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002138 TimingsTraceLog t = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002139 if (mUserLifecycleListeners.isEmpty()) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002140 Slog.w(TAG, "Not notifying internal UserLifecycleListeners");
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002141 return;
Eric Jeongf75d4132020-12-21 13:48:23 -08002142 } else if (Log.isLoggable(TAG, Log.DEBUG)) {
2143 Slog.d(TAG, "Notifying " + mUserLifecycleListeners.size()
2144 + " service listeners of " + event);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002145 }
felipeal2a84d512020-04-06 18:52:15 -07002146
felipealde1e16d2020-06-03 13:20:48 -07002147 int userId = event.getUserId();
2148 int eventType = event.getEventType();
2149 t.traceBegin("notify-listeners-user-" + userId + "-event-" + eventType);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002150 for (UserLifecycleListener listener : mUserLifecycleListeners) {
felipeal2a84d512020-04-06 18:52:15 -07002151 String listenerName = FunctionalUtils.getLambdaName(listener);
felipealde1e16d2020-06-03 13:20:48 -07002152 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_NOTIFY_INTERNAL_LIFECYCLE_LISTENER,
2153 listenerName, eventType, event.getPreviousUserId(), userId);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002154 try {
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002155 t.traceBegin("notify-listener-" + listenerName);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002156 listener.onEvent(event);
2157 } catch (RuntimeException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002158 Slog.e(TAG,
felipeal2a84d512020-04-06 18:52:15 -07002159 "Exception raised when invoking onEvent for " + listenerName, e);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002160 } finally {
2161 t.traceEnd();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002162 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002163 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002164 t.traceEnd(); // notify-listeners-user-USERID-event-EVENT_TYPE
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002165 }
2166
Mayank Garge5de0f92020-04-23 21:38:38 -07002167 private void onUserSwitching(@UserIdInt int fromUserId, @UserIdInt int toUserId) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002168 Slog.i(TAG, "onUserSwitching() callback for user " + toUserId);
2169 TimingsTraceLog t = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
Mayank Garge5de0f92020-04-23 21:38:38 -07002170 t.traceBegin("onUserSwitching-" + toUserId);
Felipe Leme5528ff72020-02-10 19:05:14 -08002171
Mayank Garge5de0f92020-04-23 21:38:38 -07002172 // Switch HAL users if user switch is not requested by CarUserService
2173 notifyHalLegacySwitch(fromUserId, toUserId);
2174
Mayank Garge90a4082020-09-30 12:57:34 -07002175 mInitialUserSetter.setLastActiveUser(toUserId);
felipealbf327652020-06-03 11:33:29 -07002176
Eric Jeongc91f9452019-08-30 15:04:21 -07002177 if (mLastPassengerId != UserHandle.USER_NULL) {
2178 stopPassengerInternal(mLastPassengerId, false);
2179 }
2180 if (mEnablePassengerSupport && isPassengerDisplayAvailable()) {
2181 setupPassengerUser();
Mayank Garge5de0f92020-04-23 21:38:38 -07002182 startFirstPassenger(toUserId);
Eric Jeongc91f9452019-08-30 15:04:21 -07002183 }
felipeal98900c82020-04-09 09:05:02 -07002184 t.traceEnd();
Pavel Maltsev17e81832019-04-04 14:38:41 -07002185 }
2186
Mayank Garge5de0f92020-04-23 21:38:38 -07002187 private void notifyHalLegacySwitch(@UserIdInt int fromUserId, @UserIdInt int toUserId) {
2188 synchronized (mLockUser) {
felipeal7d12ee22020-06-05 09:30:19 -07002189 if (mUserIdForUserSwitchInProcess != UserHandle.USER_NULL) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002190 if (Log.isLoggable(TAG, Log.DEBUG)) {
2191 Slog.d(TAG, "notifyHalLegacySwitch(" + fromUserId + ", " + toUserId
felipeal7d12ee22020-06-05 09:30:19 -07002192 + "): not needed, normal switch for " + mUserIdForUserSwitchInProcess);
2193 }
2194 return;
2195 }
Mayank Garge5de0f92020-04-23 21:38:38 -07002196 }
2197
Mayank Garg9ed099e2020-06-04 16:05:20 -07002198 if (!isUserHalSupported()) return;
2199
Mayank Garge5de0f92020-04-23 21:38:38 -07002200 // switch HAL user
felipeal7d12ee22020-06-05 09:30:19 -07002201 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager, fromUserId);
Mayank Gargeb37d092020-06-02 14:37:57 -07002202 SwitchUserRequest request = createUserSwitchRequest(toUserId, usersInfo);
2203 mHal.legacyUserSwitch(request);
Mayank Garge5de0f92020-04-23 21:38:38 -07002204 }
2205
Pavel Maltsev17e81832019-04-04 14:38:41 -07002206 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -07002207 * 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 -08002208 * run inside this call.
Eric Jeong1545f3b2019-09-16 13:56:52 -07002209 *
Keun-young Parkd462a912019-02-11 08:53:42 -08002210 * @param r Runnable to run.
2211 */
Eric Jeong1545f3b2019-09-16 13:56:52 -07002212 public void runOnUser0Unlock(@NonNull Runnable r) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00002213 Objects.requireNonNull(r, "runnable cannot be null");
Keun-young Parkd462a912019-02-11 08:53:42 -08002214 boolean runNow = false;
Eric Jeongc91f9452019-08-30 15:04:21 -07002215 synchronized (mLockUser) {
Keun-young Parkd462a912019-02-11 08:53:42 -08002216 if (mUser0Unlocked) {
2217 runNow = true;
2218 } else {
2219 mUser0UnlockTasks.add(r);
2220 }
2221 }
2222 if (runNow) {
2223 r.run();
2224 }
2225 }
2226
Keun young Parkf3523cd2019-04-08 10:09:17 -07002227 @VisibleForTesting
Eric Jeong1545f3b2019-09-16 13:56:52 -07002228 @NonNull
2229 ArrayList<Integer> getBackgroundUsersToRestart() {
2230 ArrayList<Integer> backgroundUsersToRestart = null;
Eric Jeongc91f9452019-08-30 15:04:21 -07002231 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07002232 backgroundUsersToRestart = new ArrayList<>(mBackgroundUsersToRestart);
2233 }
2234 return backgroundUsersToRestart;
2235 }
2236
Ying Zheng1ab32b62018-06-26 12:47:26 -07002237 private void setSystemUserRestrictions() {
Ying Zheng1ab32b62018-06-26 12:47:26 -07002238 // Disable Location service for system user.
2239 LocationManager locationManager =
2240 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
Anthony Hugh04ee04f2019-12-17 16:11:33 -08002241 locationManager.setLocationEnabledForUser(
2242 /* enabled= */ false, UserHandle.of(UserHandle.USER_SYSTEM));
Ying Zheng1ab32b62018-06-26 12:47:26 -07002243 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07002244
2245 /**
Anthony Hugh6fed1e92019-10-22 16:22:03 -07002246 * Assigns a default icon to a user according to the user's id.
2247 *
2248 * @param userInfo User whose avatar is set to default icon.
Anthony Hugh6fed1e92019-10-22 16:22:03 -07002249 */
Eric Jeongb2dc6ff2020-06-05 17:00:26 -07002250 private void assignDefaultIcon(UserInfo userInfo) {
Anthony Hugh6fed1e92019-10-22 16:22:03 -07002251 int idForIcon = userInfo.isGuest() ? UserHandle.USER_NULL : userInfo.id;
2252 Bitmap bitmap = UserIcons.convertToBitmap(
2253 UserIcons.getDefaultUserIcon(mContext.getResources(), idForIcon, false));
2254 mUserManager.setUserIcon(userInfo.id, bitmap);
Anthony Hugh6fed1e92019-10-22 16:22:03 -07002255 }
2256
Eric Jeong1545f3b2019-09-16 13:56:52 -07002257 private interface UserFilter {
2258 boolean isEligibleUser(UserInfo user);
2259 }
2260
2261 /** Returns all users who are matched by the given filter. */
2262 private List<UserInfo> getUsers(UserFilter filter) {
Colin Cross0df71ea2020-08-27 04:12:26 +00002263 List<UserInfo> users = mUserManager.getAliveUsers();
Eric Jeong1545f3b2019-09-16 13:56:52 -07002264
2265 for (Iterator<UserInfo> iterator = users.iterator(); iterator.hasNext(); ) {
2266 UserInfo user = iterator.next();
2267 if (!filter.isEligibleUser(user)) {
2268 iterator.remove();
2269 }
2270 }
2271 return users;
2272 }
2273
felipeal2d0483c2019-11-02 14:07:22 -07002274 private static void checkManageUsersOrDumpPermission(String message) {
Felipe Leme55236722020-10-16 16:54:32 -07002275 checkHasAtLeastOnePermissionGranted(message,
felipeal2d0483c2019-11-02 14:07:22 -07002276 android.Manifest.permission.MANAGE_USERS,
2277 android.Manifest.permission.DUMP);
2278 }
2279
Felipe Leme5528ff72020-02-10 19:05:14 -08002280 private void checkInteractAcrossUsersPermission(String message) {
Felipe Leme55236722020-10-16 16:54:32 -07002281 checkHasAtLeastOnePermissionGranted(message,
2282 android.Manifest.permission.INTERACT_ACROSS_USERS,
Felipe Leme5528ff72020-02-10 19:05:14 -08002283 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
2284 }
2285
Eric Jeongc91f9452019-08-30 15:04:21 -07002286 private int getNumberOfManagedProfiles(@UserIdInt int userId) {
Colin Cross0df71ea2020-08-27 04:12:26 +00002287 List<UserInfo> users = mUserManager.getAliveUsers();
Eric Jeongc91f9452019-08-30 15:04:21 -07002288 // Count all users that are managed profiles of the given user.
2289 int managedProfilesCount = 0;
2290 for (UserInfo user : users) {
2291 if (user.isManagedProfile() && user.profileGroupId == userId) {
2292 managedProfilesCount++;
2293 }
2294 }
2295 return managedProfilesCount;
2296 }
2297
2298 /**
2299 * Starts the first passenger of the given driver and assigns the passenger to the front
2300 * passenger zone.
2301 *
2302 * @param driverId User id of the driver.
2303 * @return whether it succeeds.
2304 */
2305 private boolean startFirstPassenger(@UserIdInt int driverId) {
2306 int zoneId = getAvailablePassengerZone();
2307 if (zoneId == OccupantZoneInfo.INVALID_ZONE_ID) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002308 Slog.w(TAG, "passenger occupant zone is not found");
Eric Jeongc91f9452019-08-30 15:04:21 -07002309 return false;
2310 }
2311 List<UserInfo> passengers = getPassengers(driverId);
2312 if (passengers.size() < 1) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002313 Slog.w(TAG, "passenger is not found");
Eric Jeongc91f9452019-08-30 15:04:21 -07002314 return false;
2315 }
2316 // Only one passenger is supported. If there are two or more passengers, the first passenger
2317 // is chosen.
2318 int passengerId = passengers.get(0).id;
2319 if (!startPassenger(passengerId, zoneId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002320 Slog.w(TAG, "cannot start passenger " + passengerId);
Eric Jeongc91f9452019-08-30 15:04:21 -07002321 return false;
2322 }
2323 return true;
2324 }
2325
2326 private int getAvailablePassengerZone() {
2327 int[] occupantTypes = new int[] {CarOccupantZoneManager.OCCUPANT_TYPE_FRONT_PASSENGER,
2328 CarOccupantZoneManager.OCCUPANT_TYPE_REAR_PASSENGER};
2329 for (int occupantType : occupantTypes) {
2330 int zoneId = getZoneId(occupantType);
2331 if (zoneId != OccupantZoneInfo.INVALID_ZONE_ID) {
2332 return zoneId;
2333 }
2334 }
2335 return OccupantZoneInfo.INVALID_ZONE_ID;
2336 }
2337
2338 /**
2339 * Creates a new passenger user when there is no passenger user.
2340 */
2341 private void setupPassengerUser() {
2342 int currentUser = ActivityManager.getCurrentUser();
2343 int profileCount = getNumberOfManagedProfiles(currentUser);
2344 if (profileCount > 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002345 Slog.w(TAG, "max profile of user" + currentUser
Eric Jeongc91f9452019-08-30 15:04:21 -07002346 + " is exceeded: current profile count is " + profileCount);
2347 return;
2348 }
2349 // TODO(b/140311342): Use resource string for the default passenger name.
2350 UserInfo passenger = createPassenger("Passenger", currentUser);
2351 if (passenger == null) {
2352 // Couldn't create user, most likely because there are too many.
Eric Jeongf75d4132020-12-21 13:48:23 -08002353 Slog.w(TAG, "cannot create a passenger user");
Eric Jeongc91f9452019-08-30 15:04:21 -07002354 return;
2355 }
2356 }
2357
2358 @NonNull
2359 private List<OccupantZoneInfo> getOccupantZones(@OccupantTypeEnum int occupantType) {
2360 ZoneUserBindingHelper helper = null;
2361 synchronized (mLockHelper) {
2362 if (mZoneUserBindingHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002363 Slog.w(TAG, "implementation is not delegated");
Eric Jeongc91f9452019-08-30 15:04:21 -07002364 return new ArrayList<OccupantZoneInfo>();
2365 }
2366 helper = mZoneUserBindingHelper;
2367 }
2368 return helper.getOccupantZones(occupantType);
2369 }
2370
2371 private boolean assignUserToOccupantZone(@UserIdInt int userId, int zoneId) {
2372 ZoneUserBindingHelper helper = null;
2373 synchronized (mLockHelper) {
2374 if (mZoneUserBindingHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002375 Slog.w(TAG, "implementation is not delegated");
Eric Jeongc91f9452019-08-30 15:04:21 -07002376 return false;
2377 }
2378 helper = mZoneUserBindingHelper;
2379 }
2380 return helper.assignUserToOccupantZone(userId, zoneId);
2381 }
2382
2383 private boolean unassignUserFromOccupantZone(@UserIdInt int userId) {
2384 ZoneUserBindingHelper helper = null;
2385 synchronized (mLockHelper) {
2386 if (mZoneUserBindingHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002387 Slog.w(TAG, "implementation is not delegated");
Eric Jeongc91f9452019-08-30 15:04:21 -07002388 return false;
2389 }
2390 helper = mZoneUserBindingHelper;
2391 }
2392 return helper.unassignUserFromOccupantZone(userId);
2393 }
2394
2395 private boolean isPassengerDisplayAvailable() {
2396 ZoneUserBindingHelper helper = null;
2397 synchronized (mLockHelper) {
2398 if (mZoneUserBindingHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002399 Slog.w(TAG, "implementation is not delegated");
Eric Jeongc91f9452019-08-30 15:04:21 -07002400 return false;
2401 }
2402 helper = mZoneUserBindingHelper;
2403 }
2404 return helper.isPassengerDisplayAvailable();
2405 }
2406
2407 /**
2408 * Gets the zone id of the given occupant type. If there are two or more zones, the first found
2409 * zone is returned.
2410 *
2411 * @param occupantType The type of an occupant.
2412 * @return The zone id of the given occupant type. {@link OccupantZoneInfo.INVALID_ZONE_ID},
2413 * if not found.
2414 */
2415 private int getZoneId(@OccupantTypeEnum int occupantType) {
2416 List<OccupantZoneInfo> zoneInfos = getOccupantZones(occupantType);
2417 return (zoneInfos.size() > 0) ? zoneInfos.get(0).zoneId : OccupantZoneInfo.INVALID_ZONE_ID;
2418 }
Mayank Garg9732d602020-08-09 21:02:40 -07002419
2420 /**
2421 * Manages the required number of pre-created users.
2422 */
Mayank Garga3b72d02021-03-14 23:05:51 -07002423 @Override
2424 public void updatePreCreatedUsers() {
2425 checkManageOrCreateUsersPermission("preCreateUsers");
2426 preCreateUsersInternal();
Mayank Garg02576972021-02-18 16:46:07 -08002427 }
2428
Mayank Garga3b72d02021-03-14 23:05:51 -07002429 private void preCreateUsersInternal() {
2430 mHandler.post(() -> mUserPreCreator.managePreCreatedUsers());
Mayank Garg9732d602020-08-09 21:02:40 -07002431 }
Felipe Leme17799202020-09-03 12:55:53 -07002432
2433 // TODO(b/167698977): members below were copied from UserManagerService; it would be better to
2434 // move them to some internal android.os class instead.
2435
2436 private static final int ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION =
2437 UserInfo.FLAG_MANAGED_PROFILE
2438 | UserInfo.FLAG_PROFILE
2439 | UserInfo.FLAG_EPHEMERAL
2440 | UserInfo.FLAG_RESTRICTED
2441 | UserInfo.FLAG_GUEST
2442 | UserInfo.FLAG_DEMO
2443 | UserInfo.FLAG_FULL;
2444
2445 private static void checkManageUsersPermission(String message) {
2446 if (!hasManageUsersPermission()) {
2447 throw new SecurityException("You need " + MANAGE_USERS + " permission to: " + message);
2448 }
2449 }
2450
2451 private static void checkManageOrCreateUsersPermission(String message) {
2452 if (!hasManageOrCreateUsersPermission()) {
2453 throw new SecurityException(
2454 "You either need " + MANAGE_USERS + " or " + CREATE_USERS + " permission to: "
2455 + message);
2456 }
2457 }
2458
2459 private static void checkManageOrCreateUsersPermission(int creationFlags) {
2460 if ((creationFlags & ~ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION) == 0) {
2461 if (!hasManageOrCreateUsersPermission()) {
2462 throw new SecurityException("You either need " + MANAGE_USERS + " or "
2463 + CREATE_USERS + "permission to create a user with flags "
2464 + creationFlags);
2465 }
2466 } else if (!hasManageUsersPermission()) {
2467 throw new SecurityException("You need " + MANAGE_USERS + " permission to create a user"
2468 + " with flags " + creationFlags);
2469 }
2470 }
2471
2472 private static boolean hasManageUsersPermission() {
2473 final int callingUid = Binder.getCallingUid();
2474 return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
2475 || callingUid == Process.ROOT_UID
2476 || hasPermissionGranted(MANAGE_USERS, callingUid);
2477 }
2478
2479 private static boolean hasManageUsersOrPermission(String alternativePermission) {
2480 final int callingUid = Binder.getCallingUid();
2481 return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
2482 || callingUid == Process.ROOT_UID
2483 || hasPermissionGranted(MANAGE_USERS, callingUid)
2484 || hasPermissionGranted(alternativePermission, callingUid);
2485 }
2486
2487 private static boolean hasManageOrCreateUsersPermission() {
2488 return hasManageUsersOrPermission(CREATE_USERS);
2489 }
2490
2491 private static boolean hasPermissionGranted(String permission, int uid) {
2492 return ActivityManager.checkComponentPermission(permission, uid, /* owningUid= */ -1,
2493 /* exported= */ true) == PackageManager.PERMISSION_GRANTED;
2494 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002495}