blob: 5439236059097f54152c5a4fbe21fec62a83cd41 [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 /**
239 * Callback to notify {@code CarServiceHelper} about driving safety changes (through
240 * {@link ICarServiceHelper#setSafetyMode(boolean).
241 *
242 * <p>NOTE: in theory, that logic should belong to {@code CarDevicePolicyService}, but it's
243 * simpler to do it here (and that service already depends on this one).
244 */
245 @GuardedBy("mLockUser")
246 private ICarServiceHelper mICarServiceHelper;
247
248 private final ICarUxRestrictionsChangeListener mCarUxRestrictionsChangeListener =
249 new ICarUxRestrictionsChangeListener.Stub() {
250 @Override
251 public void onUxRestrictionsChanged(CarUxRestrictions restrictions) {
252 setUxRestrictions(restrictions);
253 }
254 };
Felipe Leme5d5ab142020-10-27 13:49:10 -0700255
Eric Jeongc91f9452019-08-30 15:04:21 -0700256 /** Interface for callbaks related to passenger activities. */
257 public interface PassengerCallback {
258 /** Called when passenger is started at a certain zone. */
259 void onPassengerStarted(@UserIdInt int passengerId, int zoneId);
260 /** Called when passenger is stopped. */
261 void onPassengerStopped(@UserIdInt int passengerId);
262 }
263
264 /** Interface for delegating zone-related implementation to CarOccupantZoneService. */
265 public interface ZoneUserBindingHelper {
266 /** Gets occupant zones corresponding to the occupant type. */
267 @NonNull
268 List<OccupantZoneInfo> getOccupantZones(@OccupantTypeEnum int occupantType);
269 /** Assigns the user to the occupant zone. */
270 boolean assignUserToOccupantZone(@UserIdInt int userId, int zoneId);
271 /** Makes the occupant zone unoccupied. */
272 boolean unassignUserFromOccupantZone(@UserIdInt int userId);
273 /** Returns whether there is a passenger display. */
274 boolean isPassengerDisplayAvailable();
275 }
276
277 private final Object mLockHelper = new Object();
278 @GuardedBy("mLockHelper")
279 private ZoneUserBindingHelper mZoneUserBindingHelper;
280
Felipe Leme6b34fc32020-10-26 15:49:17 -0700281 /** Map used to avoid calling UserHAL when a user was removed because HAL creation failed. */
282 @GuardedBy("mLockUser")
283 private final SparseBooleanArray mFailedToCreateUserIds = new SparseBooleanArray(1);
284
Felipe Leme58412202020-01-09 13:45:33 -0800285 public CarUserService(@NonNull Context context, @NonNull UserHalService hal,
Mayank Garge90a4082020-09-30 12:57:34 -0700286 @NonNull UserManager userManager,
Felipe Leme5d5ab142020-10-27 13:49:10 -0700287 @NonNull IActivityManager am, int maxRunningUsers,
288 @NonNull CarUxRestrictionsManagerService uxRestrictionService) {
Mayank Garge90a4082020-09-30 12:57:34 -0700289 this(context, hal, userManager, am, maxRunningUsers,
Mayank Garg02576972021-02-18 16:46:07 -0800290 /* initialUserSetter= */ null, /* userPreCreator= */ null, uxRestrictionService,
291 null);
Mayank Garg71661ea2020-04-29 01:25:03 -0700292 }
293
294 @VisibleForTesting
295 CarUserService(@NonNull Context context, @NonNull UserHalService hal,
Mayank Garge90a4082020-09-30 12:57:34 -0700296 @NonNull UserManager userManager,
Mayank Gargccad8062020-08-30 15:05:10 -0700297 @NonNull IActivityManager am, int maxRunningUsers,
Mayank Garg1bb1c382020-09-03 17:11:11 -0700298 @Nullable InitialUserSetter initialUserSetter,
Felipe Leme5d5ab142020-10-27 13:49:10 -0700299 @Nullable UserPreCreator userPreCreator,
Mayank Garg02576972021-02-18 16:46:07 -0800300 @NonNull CarUxRestrictionsManagerService uxRestrictionService,
301 @Nullable Handler handler) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800302 if (Log.isLoggable(TAG, Log.DEBUG)) {
Felipe Leme8725a2f2020-12-09 16:04:51 -0800303 Slog.d(TAG, "constructed for user " + context.getUserId());
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700304 }
305 mContext = context;
Felipe Leme58412202020-01-09 13:45:33 -0800306 mHal = hal;
Keun young Parkf3523cd2019-04-08 10:09:17 -0700307 mAm = am;
308 mMaxRunningUsers = maxRunningUsers;
Anthony Hugh9932a252019-06-12 16:19:56 -0700309 mUserManager = userManager;
Eric Jeongc91f9452019-08-30 15:04:21 -0700310 mLastPassengerId = UserHandle.USER_NULL;
Mayank Garg02576972021-02-18 16:46:07 -0800311 mHandler = handler == null ? new Handler(mHandlerThread.getLooper()) : handler;
Mayank Garg1bb1c382020-09-03 17:11:11 -0700312 mInitialUserSetter =
Felipe Lemecceb2992020-11-18 18:22:44 -0800313 initialUserSetter == null ? new InitialUserSetter(context, this,
314 (u) -> setInitialUser(u)) : initialUserSetter;
Mayank Garg1bb1c382020-09-03 17:11:11 -0700315 mUserPreCreator =
316 userPreCreator == null ? new UserPreCreator(mUserManager) : userPreCreator;
Mayank Garg7e1450b2020-08-07 18:15:15 -0700317 Resources resources = context.getResources();
318 mEnablePassengerSupport = resources.getBoolean(R.bool.enablePassengerSupport);
319 mSwitchGuestUserBeforeSleep = resources.getBoolean(
320 R.bool.config_switchGuestUserBeforeGoingSleep);
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800321 mCarUxRestrictionService = uxRestrictionService;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700322 }
323
324 @Override
325 public void init() {
Eric Jeongf75d4132020-12-21 13:48:23 -0800326 if (Log.isLoggable(TAG, Log.DEBUG)) {
327 Slog.d(TAG, "init()");
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700328 }
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800329 mCarUxRestrictionService.registerUxRestrictionsChangeListener(
330 mCarUxRestrictionsChangeListener, Display.DEFAULT_DISPLAY);
331
332 setUxRestrictions(mCarUxRestrictionService.getCurrentUxRestrictions());
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700333 }
334
335 @Override
336 public void release() {
Eric Jeongf75d4132020-12-21 13:48:23 -0800337 if (Log.isLoggable(TAG, Log.DEBUG)) {
338 Slog.d(TAG, "release()");
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700339 }
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800340 mCarUxRestrictionService
341 .unregisterUxRestrictionsChangeListener(mCarUxRestrictionsChangeListener);
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700342 }
343
344 @Override
Felipe Leme176a5fd2021-01-20 15:48:33 -0800345 public void dump(@NonNull IndentingPrintWriter writer) {
Felipe Leme55236722020-10-16 16:54:32 -0700346 checkHasDumpPermissionGranted("dump()");
347
Eric Jeong1545f3b2019-09-16 13:56:52 -0700348 writer.println("*CarUserService*");
Felipe Leme5528ff72020-02-10 19:05:14 -0800349 String indent = " ";
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700350 handleDumpListeners(writer, indent);
Mayank Garg587f1942020-05-06 01:41:34 -0700351 writer.printf("User switch UI receiver %s\n", mUserSwitchUiReceiver);
Eric Jeongc91f9452019-08-30 15:04:21 -0700352 synchronized (mLockUser) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700353 writer.println("User0Unlocked: " + mUser0Unlocked);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700354 writer.println("BackgroundUsersToRestart: " + mBackgroundUsersToRestart);
355 writer.println("BackgroundUsersRestarted: " + mBackgroundUsersRestartedHere);
Felipe Leme6b34fc32020-10-26 15:49:17 -0700356 if (mFailedToCreateUserIds.size() > 0) {
357 writer.println("FailedToCreateUserIds: " + mFailedToCreateUserIds);
358 }
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800359 writer.printf("Is UX restricted: %b\n", mUxRestricted);
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700360 }
Mayank Garg02576972021-02-18 16:46:07 -0800361
362 writer.println("SwitchGuestUserBeforeSleep: " + mSwitchGuestUserBeforeSleep);
Mayank Garg02576972021-02-18 16:46:07 -0800363
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700364 writer.println("MaxRunningUsers: " + mMaxRunningUsers);
365 List<UserInfo> allDrivers = getAllDrivers();
366 int driversSize = allDrivers.size();
367 writer.println("NumberOfDrivers: " + driversSize);
368 for (int i = 0; i < driversSize; i++) {
369 int driverId = allDrivers.get(i).id;
370 writer.print(indent + "#" + i + ": id=" + driverId);
371 List<UserInfo> passengers = getPassengers(driverId);
372 int passengersSize = passengers.size();
373 writer.print(" NumberPassengers: " + passengersSize);
374 if (passengersSize > 0) {
375 writer.print(" [");
376 for (int j = 0; j < passengersSize; j++) {
377 writer.print(passengers.get(j).id);
378 if (j < passengersSize - 1) {
379 writer.print(" ");
felipeal2d0483c2019-11-02 14:07:22 -0700380 }
felipeal2d0483c2019-11-02 14:07:22 -0700381 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700382 writer.print("]");
felipeal2d0483c2019-11-02 14:07:22 -0700383 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700384 writer.println();
385 }
386 writer.printf("EnablePassengerSupport: %s\n", mEnablePassengerSupport);
387 writer.printf("User HAL timeout: %dms\n", mHalTimeoutMs);
388 writer.printf("Initial user: %s\n", mInitialUser);
felipealbf327652020-06-03 11:33:29 -0700389
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700390 writer.println("Relevant overlayable properties");
391 Resources res = mContext.getResources();
392 writer.printf("%sowner_name=%s\n", indent,
393 res.getString(com.android.internal.R.string.owner_name));
394 writer.printf("%sdefault_guest_name=%s\n", indent,
395 res.getString(R.string.default_guest_name));
felipealf7368962020-04-16 12:55:19 -0700396 writer.printf("User switch in process=%d\n", mUserIdForUserSwitchInProcess);
Mayank Garg7a114c82020-04-08 21:25:06 -0700397 writer.printf("Request Id for the user switch in process=%d\n ",
398 mRequestIdForUserSwitchInProcess);
Mayank Garga480dd92020-05-14 03:14:57 -0700399 writer.printf("System UI package name=%s\n", getSystemUiPackageName());
felipeale8c5dce2020-04-15 11:27:06 -0700400
felipealbf327652020-06-03 11:33:29 -0700401 writer.println("Relevant Global settings");
402 dumpGlobalProperty(writer, indent, CarSettings.Global.LAST_ACTIVE_USER_ID);
403 dumpGlobalProperty(writer, indent, CarSettings.Global.LAST_ACTIVE_PERSISTENT_USER_ID);
404
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700405 mInitialUserSetter.dump(writer);
felipeale8c5dce2020-04-15 11:27:06 -0700406 }
407
felipealbf327652020-06-03 11:33:29 -0700408 private void dumpGlobalProperty(PrintWriter writer, String indent, String property) {
409 String value = Settings.Global.getString(mContext.getContentResolver(), property);
410 writer.printf("%s%s=%s\n", indent, property, value);
411 }
412
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700413 private void handleDumpListeners(@NonNull PrintWriter writer, String indent) {
414 CountDownLatch latch = new CountDownLatch(1);
415 mHandler.post(() -> {
felipealde1e16d2020-06-03 13:20:48 -0700416 handleDumpServiceLifecycleListeners(writer);
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700417 handleDumpAppLifecycleListeners(writer, indent);
418 latch.countDown();
419 });
420 int timeout = 5;
421 try {
422 if (!latch.await(timeout, TimeUnit.SECONDS)) {
423 writer.printf("Handler thread didn't respond in %ds when dumping listeners\n",
424 timeout);
425 }
426 } catch (InterruptedException e) {
427 Thread.currentThread().interrupt();
428 writer.println("Interrupted waiting for handler thread to dump app and user listeners");
429 }
430 }
431
felipealde1e16d2020-06-03 13:20:48 -0700432 private void handleDumpServiceLifecycleListeners(@NonNull PrintWriter writer) {
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700433 if (mUserLifecycleListeners.isEmpty()) {
felipealde1e16d2020-06-03 13:20:48 -0700434 writer.println("No lifecycle listeners for internal services");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700435 return;
436 }
felipealde1e16d2020-06-03 13:20:48 -0700437 int size = mUserLifecycleListeners.size();
438 writer.printf("%d lifecycle listener%s for services\n", size, size == 1 ? "" : "s");
439 String indent = " ";
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700440 for (UserLifecycleListener listener : mUserLifecycleListeners) {
felipealde1e16d2020-06-03 13:20:48 -0700441 writer.printf("%s%s\n", indent, FunctionalUtils.getLambdaName(listener));
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700442 }
443 }
444
445 private void handleDumpAppLifecycleListeners(@NonNull PrintWriter writer, String indent) {
felipealde1e16d2020-06-03 13:20:48 -0700446 int size = mAppLifecycleListeners.size();
447 if (size == 0) {
448 writer.println("No lifecycle listeners for apps");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700449 return;
450 }
felipealde1e16d2020-06-03 13:20:48 -0700451 writer.printf("%d lifecycle listener%s for apps \n", size, size == 1 ? "" : "s");
452 for (int i = 0; i < size; i++) {
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700453 int uid = mAppLifecycleListeners.keyAt(i);
454 IResultReceiver listener = mAppLifecycleListeners.valueAt(i);
Felipe Lemeea4b5322020-10-26 15:33:36 -0700455 writer.printf("%suid: %d listener: %s\n", indent, uid,
456 FunctionalUtils.getLambdaName(listener));
Keun-young Parkd462a912019-02-11 08:53:42 -0800457 }
Eric Jeong1545f3b2019-09-16 13:56:52 -0700458 }
459
460 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700461 * @see ExperimentalCarUserManager.createDriver
Eric Jeong1545f3b2019-09-16 13:56:52 -0700462 */
463 @Override
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700464 public AndroidFuture<UserCreationResult> createDriver(@NonNull String name, boolean admin) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700465 checkManageUsersPermission("createDriver");
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +0000466 Objects.requireNonNull(name, "name cannot be null");
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700467
468 AndroidFuture<UserCreationResult> future = new AndroidFuture<UserCreationResult>() {
469 @Override
470 protected void onCompleted(UserCreationResult result, Throwable err) {
471 if (result == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800472 Slog.w(TAG, "createDriver(" + name + "," + admin + ") failed: " + err);
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700473 } else {
474 if (result.getStatus() == UserCreationResult.STATUS_SUCCESSFUL) {
475 assignDefaultIcon(result.getUser());
476 }
477 }
478 super.onCompleted(result, err);
479 };
480 };
481 int flags = 0;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700482 if (admin) {
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700483 if (!(mUserManager.isAdminUser() || mUserManager.isSystemUser())) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800484 Slog.e(TAG, "Only admin users and system user can create other admins.");
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700485 sendUserCreationResultFailure(future, UserCreationResult.STATUS_INVALID_REQUEST);
486 return future;
487 }
488 flags = UserInfo.FLAG_ADMIN;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700489 }
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700490 createUser(name, UserInfo.getDefaultUserType(flags), flags, mHalTimeoutMs, future);
491 return future;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700492 }
493
494 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700495 * @see ExperimentalCarUserManager.createPassenger
Eric Jeong1545f3b2019-09-16 13:56:52 -0700496 */
497 @Override
498 @Nullable
499 public UserInfo createPassenger(@NonNull String name, @UserIdInt int driverId) {
500 checkManageUsersPermission("createPassenger");
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +0000501 Objects.requireNonNull(name, "name cannot be null");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700502 UserInfo driver = mUserManager.getUserInfo(driverId);
503 if (driver == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800504 Slog.w(TAG, "the driver is invalid");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700505 return null;
506 }
507 if (driver.isGuest()) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800508 Slog.w(TAG, "a guest driver cannot create a passenger");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700509 return null;
510 }
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700511 // createPassenger doesn't use user HAL because user HAL doesn't support profile user yet.
Bookatz42fb1a62019-10-30 11:45:01 -0700512 UserInfo user = mUserManager.createProfileForUser(name,
513 UserManager.USER_TYPE_PROFILE_MANAGED, /* flags */ 0, driverId);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700514 if (user == null) {
515 // Couldn't create user, most likely because there are too many.
Eric Jeongf75d4132020-12-21 13:48:23 -0800516 Slog.w(TAG, "can't create a profile for user" + driverId);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700517 return null;
518 }
519 // Passenger user should be a non-admin user.
Mayank Garge90a4082020-09-30 12:57:34 -0700520 UserHelper.setDefaultNonAdminRestrictions(mContext, user, /* enable= */ true);
Anthony Hugh6fed1e92019-10-22 16:22:03 -0700521 assignDefaultIcon(user);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700522 return user;
523 }
524
525 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700526 * @see ExperimentalCarUserManager.switchDriver
Eric Jeong1545f3b2019-09-16 13:56:52 -0700527 */
528 @Override
Eric Jeong25666cf2020-05-14 15:16:27 -0700529 public void switchDriver(@UserIdInt int driverId, AndroidFuture<UserSwitchResult> receiver) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700530 checkManageUsersPermission("switchDriver");
Mayank Garg94f3eb92020-08-12 12:38:58 -0700531 if (UserHelperLite.isHeadlessSystemUser(driverId)) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700532 // System user doesn't associate with real person, can not be switched to.
Eric Jeongf75d4132020-12-21 13:48:23 -0800533 Slog.w(TAG, "switching to system user in headless system user mode is not allowed");
felipealdfdf8512020-06-01 09:35:45 -0700534 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_INVALID_REQUEST);
Eric Jeong25666cf2020-05-14 15:16:27 -0700535 return;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700536 }
537 int userSwitchable = mUserManager.getUserSwitchability();
538 if (userSwitchable != UserManager.SWITCHABILITY_STATUS_OK) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800539 Slog.w(TAG, "current process is not allowed to switch user");
felipealdfdf8512020-06-01 09:35:45 -0700540 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_INVALID_REQUEST);
Eric Jeong25666cf2020-05-14 15:16:27 -0700541 return;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700542 }
Eric Jeong25666cf2020-05-14 15:16:27 -0700543 switchUser(driverId, mHalTimeoutMs, receiver);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700544 }
545
546 /**
Eric Jeonge7916fc2019-12-20 14:03:34 -0800547 * Returns all drivers who can occupy the driving zone. Guest users are included in the list.
548 *
549 * @return the list of {@link UserInfo} who can be a driver on the device.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700550 */
551 @Override
552 @NonNull
553 public List<UserInfo> getAllDrivers() {
felipeal2d0483c2019-11-02 14:07:22 -0700554 checkManageUsersOrDumpPermission("getAllDrivers");
Mayank Garg94f3eb92020-08-12 12:38:58 -0700555 return getUsers((user) -> !UserHelperLite.isHeadlessSystemUser(user.id) && user.isEnabled()
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700556 && !user.isManagedProfile() && !user.isEphemeral());
Eric Jeong1545f3b2019-09-16 13:56:52 -0700557 }
558
559 /**
Eric Jeonge7916fc2019-12-20 14:03:34 -0800560 * Returns all passengers under the given driver.
561 *
562 * @param driverId User id of a driver.
563 * @return the list of {@link UserInfo} who is a passenger under the given driver.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700564 */
565 @Override
566 @NonNull
567 public List<UserInfo> getPassengers(@UserIdInt int driverId) {
felipeal2d0483c2019-11-02 14:07:22 -0700568 checkManageUsersOrDumpPermission("getPassengers");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700569 return getUsers((user) -> {
Mayank Garg94f3eb92020-08-12 12:38:58 -0700570 return !UserHelperLite.isHeadlessSystemUser(user.id) && user.isEnabled()
Eric Jeong40f8fa32020-05-12 12:23:33 -0700571 && user.isManagedProfile() && user.profileGroupId == driverId;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700572 });
573 }
574
575 /**
576 * @see CarUserManager.startPassenger
577 */
578 @Override
579 public boolean startPassenger(@UserIdInt int passengerId, int zoneId) {
580 checkManageUsersPermission("startPassenger");
Eric Jeongc91f9452019-08-30 15:04:21 -0700581 synchronized (mLockUser) {
582 try {
583 if (!mAm.startUserInBackgroundWithListener(passengerId, null)) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800584 Slog.w(TAG, "could not start passenger");
Eric Jeongc91f9452019-08-30 15:04:21 -0700585 return false;
586 }
587 } catch (RemoteException e) {
588 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -0800589 Slog.w(TAG, "error while starting passenger", e);
Eric Jeongc91f9452019-08-30 15:04:21 -0700590 return false;
591 }
592 if (!assignUserToOccupantZone(passengerId, zoneId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800593 Slog.w(TAG, "could not assign passenger to zone");
Eric Jeongc91f9452019-08-30 15:04:21 -0700594 return false;
595 }
596 mLastPassengerId = passengerId;
597 }
598 for (PassengerCallback callback : mPassengerCallbacks) {
599 callback.onPassengerStarted(passengerId, zoneId);
600 }
601 return true;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700602 }
603
604 /**
605 * @see CarUserManager.stopPassenger
606 */
607 @Override
608 public boolean stopPassenger(@UserIdInt int passengerId) {
609 checkManageUsersPermission("stopPassenger");
Eric Jeongc91f9452019-08-30 15:04:21 -0700610 return stopPassengerInternal(passengerId, true);
611 }
612
613 private boolean stopPassengerInternal(@UserIdInt int passengerId, boolean checkCurrentDriver) {
614 synchronized (mLockUser) {
615 UserInfo passenger = mUserManager.getUserInfo(passengerId);
616 if (passenger == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800617 Slog.w(TAG, "passenger " + passengerId + " doesn't exist");
Eric Jeongc91f9452019-08-30 15:04:21 -0700618 return false;
619 }
620 if (mLastPassengerId != passengerId) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800621 Slog.w(TAG, "passenger " + passengerId + " hasn't been started");
Eric Jeongc91f9452019-08-30 15:04:21 -0700622 return true;
623 }
624 if (checkCurrentDriver) {
625 int currentUser = ActivityManager.getCurrentUser();
626 if (passenger.profileGroupId != currentUser) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800627 Slog.w(TAG, "passenger " + passengerId
Eric Jeongc91f9452019-08-30 15:04:21 -0700628 + " is not a profile of the current user");
629 return false;
630 }
631 }
632 // Passenger is a profile, so cannot be stopped through activity manager.
633 // Instead, activities started by the passenger are stopped and the passenger is
634 // unassigned from the zone.
635 stopAllTasks(passengerId);
636 if (!unassignUserFromOccupantZone(passengerId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800637 Slog.w(TAG, "could not unassign user from occupant zone");
Eric Jeongc91f9452019-08-30 15:04:21 -0700638 return false;
639 }
640 mLastPassengerId = UserHandle.USER_NULL;
641 }
642 for (PassengerCallback callback : mPassengerCallbacks) {
643 callback.onPassengerStopped(passengerId);
644 }
645 return true;
646 }
647
648 private void stopAllTasks(@UserIdInt int userId) {
649 try {
Louis Chang3bf2f202020-08-18 13:04:28 +0800650 for (RootTaskInfo info : mAm.getAllRootTaskInfos()) {
651 for (int i = 0; i < info.childTaskIds.length; i++) {
652 if (info.childTaskUserIds[i] == userId) {
653 int taskId = info.childTaskIds[i];
Eric Jeongc91f9452019-08-30 15:04:21 -0700654 if (!mAm.removeTask(taskId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800655 Slog.w(TAG, "could not remove task " + taskId);
Eric Jeongc91f9452019-08-30 15:04:21 -0700656 }
657 }
658 }
659 }
660 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800661 Slog.e(TAG, "could not get stack info", e);
Eric Jeongc91f9452019-08-30 15:04:21 -0700662 }
Eric Jeong1545f3b2019-09-16 13:56:52 -0700663 }
664
Felipe Leme5528ff72020-02-10 19:05:14 -0800665 @Override
666 public void setLifecycleListenerForUid(IResultReceiver listener) {
667 int uid = Binder.getCallingUid();
felipeal312416a2020-04-14 12:28:24 -0700668 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SET_LIFECYCLE_LISTENER, uid);
Felipe Leme5528ff72020-02-10 19:05:14 -0800669 checkInteractAcrossUsersPermission("setLifecycleListenerForUid" + uid);
670
671 try {
672 listener.asBinder().linkToDeath(() -> onListenerDeath(uid), 0);
673 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800674 Slog.wtf(TAG, "Cannot listen to death of " + uid);
Felipe Leme5528ff72020-02-10 19:05:14 -0800675 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700676 mHandler.post(() -> mAppLifecycleListeners.append(uid, listener));
Felipe Leme5528ff72020-02-10 19:05:14 -0800677 }
678
679 private void onListenerDeath(int uid) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800680 Slog.i(TAG, "Removing listeners for uid " + uid + " on binder death");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700681 mHandler.post(() -> mAppLifecycleListeners.remove(uid));
Felipe Leme5528ff72020-02-10 19:05:14 -0800682 }
683
684 @Override
685 public void resetLifecycleListenerForUid() {
686 int uid = Binder.getCallingUid();
felipeal312416a2020-04-14 12:28:24 -0700687 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_RESET_LIFECYCLE_LISTENER, uid);
Felipe Leme5528ff72020-02-10 19:05:14 -0800688 checkInteractAcrossUsersPermission("resetLifecycleListenerForUid-" + uid);
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700689 mHandler.post(() -> mAppLifecycleListeners.remove(uid));
Felipe Leme5528ff72020-02-10 19:05:14 -0800690 }
691
Felipe Lemee3cab982020-03-12 11:39:29 -0700692 /**
felipeal61ce3732020-04-03 11:01:00 -0700693 * Gets the initial foreground user after the device boots or resumes from suspension.
694 *
695 * <p>When the OEM supports the User HAL, the initial user won't be available until the HAL
696 * returns the initial value to {@code CarService} - if HAL takes too long or times out, this
697 * method returns {@code null}.
698 *
699 * <p>If the HAL eventually times out, {@code CarService} will fallback to its default behavior
700 * (like switching to the last active user), and this method will return the result of such
701 * operation.
702 *
703 * <p>Notice that if {@code CarService} crashes, subsequent calls to this method will return
704 * {@code null}.
705 *
706 * @hide
707 */
708 @Nullable
709 public UserInfo getInitialUser() {
710 checkInteractAcrossUsersPermission("getInitialUser");
711 synchronized (mLockUser) {
712 return mInitialUser;
713 }
714 }
715
felipeal61ce3732020-04-03 11:01:00 -0700716 /**
717 * Sets the initial foreground user after the device boots or resumes from suspension.
718 */
719 public void setInitialUser(@Nullable UserInfo user) {
felipeal312416a2020-04-14 12:28:24 -0700720 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SET_INITIAL_USER,
721 user == null ? UserHandle.USER_NULL : user.id);
felipeal61ce3732020-04-03 11:01:00 -0700722 synchronized (mLockUser) {
723 mInitialUser = user;
724 }
725 if (user == null) {
726 // This mean InitialUserSetter failed and could not fallback, so the initial user was
727 // not switched (and most likely is SYSTEM_USER).
728 // TODO(b/153104378): should we set it to ActivityManager.getCurrentUser() instead?
Eric Jeongf75d4132020-12-21 13:48:23 -0800729 Slog.wtf(TAG, "Initial user set to null");
felipeal61ce3732020-04-03 11:01:00 -0700730 }
731 }
732
Mayank Garg7e1450b2020-08-07 18:15:15 -0700733 private void initResumeReplaceGuest() {
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700734 int currentUserId = ActivityManager.getCurrentUser();
735 UserInfo currentUser = mUserManager.getUserInfo(currentUserId);
736
737 if (!mInitialUserSetter.canReplaceGuestUser(currentUser)) return; // Not a guest
738
739 InitialUserInfo info =
740 new InitialUserSetter.Builder(InitialUserSetter.TYPE_REPLACE_GUEST).build();
741
742 mInitialUserSetter.set(info);
743 }
744
745 /**
Mayank Garg0baf88a2020-08-30 21:57:36 -0700746 * Calls to switch user at the power suspend.
Mayank Garg7e1450b2020-08-07 18:15:15 -0700747 *
748 * <p><b>Note:</b> Should be used only by {@link CarPowerManagementService}
749 *
Mayank Garg7e1450b2020-08-07 18:15:15 -0700750 */
Mayank Garg0baf88a2020-08-30 21:57:36 -0700751 public void onSuspend() {
Eric Jeongf75d4132020-12-21 13:48:23 -0800752 if (Log.isLoggable(TAG, Log.DEBUG)) {
753 Slog.d(TAG, "onSuspend called.");
Mayank Garg7e1450b2020-08-07 18:15:15 -0700754 }
755
Mayank Garg0baf88a2020-08-30 21:57:36 -0700756 if (mSwitchGuestUserBeforeSleep) {
757 initResumeReplaceGuest();
Mayank Garg7e1450b2020-08-07 18:15:15 -0700758 }
Mayank Garg1bb1c382020-09-03 17:11:11 -0700759
Mayank Garga3b72d02021-03-14 23:05:51 -0700760 preCreateUsersInternal();
Mayank Garg7e1450b2020-08-07 18:15:15 -0700761 }
762
763 /**
Mayank Garg0baf88a2020-08-30 21:57:36 -0700764 * Calls to switch user at the power resume.
765 *
766 * <p>
767 * <b>Note:</b> Should be used only by {@link CarPowerManagementService}
768 *
769 */
770 public void onResume() {
Eric Jeongf75d4132020-12-21 13:48:23 -0800771 if (Log.isLoggable(TAG, Log.DEBUG)) {
772 Slog.d(TAG, "onResume called.");
Mayank Garg0baf88a2020-08-30 21:57:36 -0700773 }
774
Mayank Garg02576972021-02-18 16:46:07 -0800775 mHandler.post(() -> initBootUser(InitialUserInfoRequestType.RESUME));
Mayank Garg0baf88a2020-08-30 21:57:36 -0700776 }
777
778 /**
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700779 * Calls to start user at the android startup.
Mayank Garg70732a82020-08-05 20:17:47 -0700780 */
781 public void initBootUser() {
Mayank Garg02576972021-02-18 16:46:07 -0800782 mHandler.post(() -> initBootUser(getInitialUserInfoRequestType()));
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700783 }
784
Mayank Garg7e1450b2020-08-07 18:15:15 -0700785 private void initBootUser(int requestType) {
786 boolean replaceGuest =
787 requestType == InitialUserInfoRequestType.RESUME && !mSwitchGuestUserBeforeSleep;
Mayank Garg70732a82020-08-05 20:17:47 -0700788 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_REQ, requestType,
789 mHalTimeoutMs);
790 checkManageUsersPermission("startInitialUser");
791
792 if (!isUserHalSupported()) {
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700793 fallbackToDefaultInitialUserBehavior(/* userLocales= */ null, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700794 return;
795 }
796
797 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
798 mHal.getInitialUserInfo(requestType, mHalTimeoutMs, usersInfo, (status, resp) -> {
799 if (resp != null) {
800 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_RESP,
801 status, resp.action, resp.userToSwitchOrCreate.userId,
802 resp.userToSwitchOrCreate.flags, resp.userNameToCreate, resp.userLocales);
803
804 String userLocales = resp.userLocales;
805 InitialUserInfo info;
806 switch (resp.action) {
807 case InitialUserInfoResponseAction.SWITCH:
808 int userId = resp.userToSwitchOrCreate.userId;
809 if (userId <= 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800810 Slog.w(TAG, "invalid (or missing) user id sent by HAL: " + userId);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700811 fallbackToDefaultInitialUserBehavior(userLocales, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700812 break;
813 }
814 info = new InitialUserSetter.Builder(InitialUserSetter.TYPE_SWITCH)
815 .setUserLocales(userLocales)
816 .setSwitchUserId(userId)
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700817 .setReplaceGuest(replaceGuest)
Mayank Garg70732a82020-08-05 20:17:47 -0700818 .build();
819 mInitialUserSetter.set(info);
820 break;
821
822 case InitialUserInfoResponseAction.CREATE:
823 int halFlags = resp.userToSwitchOrCreate.flags;
824 String userName = resp.userNameToCreate;
825 info = new InitialUserSetter.Builder(InitialUserSetter.TYPE_CREATE)
826 .setUserLocales(userLocales)
827 .setNewUserName(userName)
828 .setNewUserFlags(halFlags)
829 .build();
830 mInitialUserSetter.set(info);
831 break;
832
833 case InitialUserInfoResponseAction.DEFAULT:
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700834 fallbackToDefaultInitialUserBehavior(userLocales, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700835 break;
836 default:
Eric Jeongf75d4132020-12-21 13:48:23 -0800837 Slog.w(TAG, "invalid response action on " + resp);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700838 fallbackToDefaultInitialUserBehavior(/* user locale */ null, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700839 break;
840
841 }
842 } else {
843 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_RESP, status);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700844 fallbackToDefaultInitialUserBehavior(/* user locale */ null, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700845 }
846 });
847 }
848
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700849 private void fallbackToDefaultInitialUserBehavior(String userLocales, boolean replaceGuest) {
Mayank Garg70732a82020-08-05 20:17:47 -0700850 InitialUserInfo info = new InitialUserSetter.Builder(
851 InitialUserSetter.TYPE_DEFAULT_BEHAVIOR)
852 .setUserLocales(userLocales)
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700853 .setReplaceGuest(replaceGuest)
Mayank Garg70732a82020-08-05 20:17:47 -0700854 .build();
855 mInitialUserSetter.set(info);
856 }
857
858 @VisibleForTesting
859 int getInitialUserInfoRequestType() {
Mayank Garge90a4082020-09-30 12:57:34 -0700860 if (!mInitialUserSetter.hasInitialUser()) {
Mayank Garg70732a82020-08-05 20:17:47 -0700861 return InitialUserInfoRequestType.FIRST_BOOT;
862 }
863 if (mContext.getPackageManager().isDeviceUpgrading()) {
864 return InitialUserInfoRequestType.FIRST_BOOT_AFTER_OTA;
865 }
866 return InitialUserInfoRequestType.COLD_BOOT;
867 }
868
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800869 /**
870 * Sets the {@link ICarServiceHelper} so it can receive UX restriction updates.
871 */
872 public void setCarServiceHelper(ICarServiceHelper helper) {
873 boolean restricted;
874 synchronized (mLockUser) {
875 mICarServiceHelper = helper;
876 restricted = mUxRestricted;
877 }
878 updateSafetyMode(helper, restricted);
879 }
880
881 private void updateSafetyMode(@Nullable ICarServiceHelper helper, boolean restricted) {
882 if (helper == null) return;
883
884 boolean isSafe = !restricted;
885 try {
886 helper.setSafetyMode(isSafe);
887 } catch (Exception e) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800888 Slog.e(TAG, "Exception calling helper.setDpmSafetyMode(" + isSafe + ")", e);
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800889 }
890 }
891
892 private void setUxRestrictions(@Nullable CarUxRestrictions restrictions) {
Felipe Leme5d5ab142020-10-27 13:49:10 -0700893 boolean restricted = restrictions != null
894 && (restrictions.getActiveRestrictions() & UX_RESTRICTIONS_NO_SETUP)
895 == UX_RESTRICTIONS_NO_SETUP;
Eric Jeongf75d4132020-12-21 13:48:23 -0800896 if (Log.isLoggable(TAG, Log.DEBUG)) {
897 Slog.d(TAG, "setUxRestrictions(" + restrictions + "): restricted=" + restricted);
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800898 } else {
Eric Jeongf75d4132020-12-21 13:48:23 -0800899 Slog.i(TAG, "Setting UX restricted to " + restricted);
Felipe Leme5d5ab142020-10-27 13:49:10 -0700900 }
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800901
902 ICarServiceHelper helper = null;
903
904 synchronized (mLockUser) {
905 mUxRestricted = restricted;
906 if (mICarServiceHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800907 Slog.e(TAG, "onUxRestrictionsChanged(): no mICarServiceHelper");
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800908 }
909 helper = mICarServiceHelper;
910 }
911 updateSafetyMode(helper, restricted);
912 }
913
914 private boolean isUxRestricted() {
915 synchronized (mLockUser) {
916 return mUxRestricted;
917 }
Felipe Leme5d5ab142020-10-27 13:49:10 -0700918 }
919
Mayank Garg70732a82020-08-05 20:17:47 -0700920 /**
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700921 * Calls the {@link UserHalService} and {@link IActivityManager} for user switch.
922 *
923 * <p>
Mayank Gargb08f6772020-05-01 18:06:48 -0700924 * When everything works well, the workflow is:
925 * <ol>
926 * <li> {@link UserHalService} is called for HAL user switch with ANDROID_SWITCH request
927 * type, current user id, target user id, and a callback.
928 * <li> HAL called back with SUCCESS.
929 * <li> {@link IActivityManager} is called for Android user switch.
930 * <li> Receiver would receive {@code STATUS_SUCCESSFUL}.
931 * <li> Once user is unlocked, {@link UserHalService} is again called with ANDROID_POST_SWITCH
932 * request type, current user id, and target user id. In this case, the current and target
933 * user IDs would be same.
934 * <ol/>
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700935 *
936 * <p>
Mayank Gargb08f6772020-05-01 18:06:48 -0700937 * Corner cases:
938 * <ul>
939 * <li> If target user is already the current user, no user switch is performed and receiver
Mayank Gargef1b9332020-06-11 17:36:56 -0700940 * would receive {@code STATUS_OK_USER_ALREADY_IN_FOREGROUND} right away.
Mayank Gargb08f6772020-05-01 18:06:48 -0700941 * <li> If HAL user switch call fails, no Android user switch. Receiver would receive
942 * {@code STATUS_HAL_INTERNAL_FAILURE}.
943 * <li> If HAL user switch call is successful, but android user switch call fails,
944 * {@link UserHalService} is again called with request type POST_SWITCH, current user id, and
945 * target user id, but in this case the current and target user IDs would be different.
946 * <li> If another user switch request for the same target user is received while previous
947 * request is in process, receiver would receive
948 * {@code STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO} for the new request right away.
949 * <li> If a user switch request is received while another user switch request for different
950 * target user is in process, the previous request would be abandoned and new request will be
951 * processed. No POST_SWITCH would be sent for the previous request.
952 * <ul/>
Mayank Garg59f22192020-03-27 00:51:45 -0700953 *
Mayank Garge19c2922020-03-30 18:05:53 -0700954 * @param targetUserId - target user Id
Mayank Garg59f22192020-03-27 00:51:45 -0700955 * @param timeoutMs - timeout for HAL to wait
956 * @param receiver - receiver for the results
957 */
Mayank Garge19c2922020-03-30 18:05:53 -0700958 @Override
959 public void switchUser(@UserIdInt int targetUserId, int timeoutMs,
felipeale5bf0322020-04-16 15:10:57 -0700960 @NonNull AndroidFuture<UserSwitchResult> receiver) {
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700961 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_REQ, targetUserId, timeoutMs);
Felipe Leme17799202020-09-03 12:55:53 -0700962 checkManageOrCreateUsersPermission("switchUser");
Mayank Garge19c2922020-03-30 18:05:53 -0700963 Objects.requireNonNull(receiver);
964 UserInfo targetUser = mUserManager.getUserInfo(targetUserId);
felipealf7368962020-04-16 12:55:19 -0700965 Preconditions.checkArgument(targetUser != null, "Target user doesn't exist");
Mayank Garga479cb32021-04-05 22:23:04 -0700966 if (mUserManager.getUserSwitchability() != UserManager.SWITCHABILITY_STATUS_OK) {
967 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_NOT_SWITCHABLE);
968 return;
969 }
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -0700970 mHandler.post(() -> handleSwitchUser(targetUser, timeoutMs, receiver));
Mayank Garg02576972021-02-18 16:46:07 -0800971 }
Mayank Garg7a114c82020-04-08 21:25:06 -0700972
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -0700973 private void handleSwitchUser(@NonNull UserInfo targetUser, int timeoutMs,
Mayank Garg02576972021-02-18 16:46:07 -0800974 @NonNull AndroidFuture<UserSwitchResult> receiver) {
felipealf7368962020-04-16 12:55:19 -0700975 int currentUser = ActivityManager.getCurrentUser();
Mayank Garg02576972021-02-18 16:46:07 -0800976 int targetUserId = targetUser.id;
felipealf7368962020-04-16 12:55:19 -0700977 if (currentUser == targetUserId) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800978 if (Log.isLoggable(TAG, Log.DEBUG)) {
979 Slog.d(TAG, "Current user is same as requested target user: " + targetUserId);
Mayank Garg0e239142020-04-14 19:16:31 -0700980 }
Mayank Gargef1b9332020-06-11 17:36:56 -0700981 int resultStatus = UserSwitchResult.STATUS_OK_USER_ALREADY_IN_FOREGROUND;
felipealdfdf8512020-06-01 09:35:45 -0700982 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg0e239142020-04-14 19:16:31 -0700983 return;
984 }
985
Felipe Leme5d5ab142020-10-27 13:49:10 -0700986 if (isUxRestricted()) {
987 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_UX_RESTRICTION_FAILURE);
988 return;
989 }
990
Mayank Garg9ed099e2020-06-04 16:05:20 -0700991 // If User Hal is not supported, just android user switch.
992 if (!isUserHalSupported()) {
993 try {
994 if (mAm.switchUser(targetUserId)) {
995 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_SUCCESSFUL);
996 return;
997 }
998 } catch (RemoteException e) {
999 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001000 Slog.w(TAG, "error while switching user " + targetUser.toFullString(), e);
Mayank Garg9ed099e2020-06-04 16:05:20 -07001001 }
1002 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_ANDROID_FAILURE);
1003 return;
1004 }
1005
Mayank Garg7a114c82020-04-08 21:25:06 -07001006 synchronized (mLockUser) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001007 if (Log.isLoggable(TAG, Log.DEBUG)) {
1008 Slog.d(TAG, "switchUser(" + targetUserId + "): currentuser=" + currentUser
felipealf7368962020-04-16 12:55:19 -07001009 + ", mUserIdForUserSwitchInProcess=" + mUserIdForUserSwitchInProcess);
1010 }
1011
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001012 // If there is another request for the same target user, return another request in
1013 // process, else {@link mUserIdForUserSwitchInProcess} is updated and {@link
1014 // mRequestIdForUserSwitchInProcess} is reset. It is possible that there may be another
1015 // user switch request in process for different target user, but that request is now
1016 // ignored.
felipealf7368962020-04-16 12:55:19 -07001017 if (mUserIdForUserSwitchInProcess == targetUserId) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001018 if (Log.isLoggable(TAG, Log.DEBUG)) {
1019 Slog.d(TAG,
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001020 "Another user switch request in process for the requested target user: "
1021 + targetUserId);
1022 }
1023
1024 int resultStatus = UserSwitchResult.STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO;
felipealdfdf8512020-06-01 09:35:45 -07001025 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg7a114c82020-04-08 21:25:06 -07001026 return;
Mayank Garg02576972021-02-18 16:46:07 -08001027 } else {
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001028 mUserIdForUserSwitchInProcess = targetUserId;
1029 mRequestIdForUserSwitchInProcess = 0;
1030 }
Mayank Garg7a114c82020-04-08 21:25:06 -07001031 }
1032
felipealdfdf8512020-06-01 09:35:45 -07001033 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
Mayank Gargeb37d092020-06-02 14:37:57 -07001034 SwitchUserRequest request = createUserSwitchRequest(targetUserId, usersInfo);
1035
Felipe Leme5d5ab142020-10-27 13:49:10 -07001036 mHal.switchUser(request, timeoutMs, (halCallbackStatus, resp) -> {
Eric Jeongf75d4132020-12-21 13:48:23 -08001037 if (Log.isLoggable(TAG, Log.DEBUG)) {
1038 Slog.d(TAG, "switch response: status="
Felipe Leme5d5ab142020-10-27 13:49:10 -07001039 + UserHalHelper.halCallbackStatusToString(halCallbackStatus)
1040 + ", resp=" + resp);
felipealf7368962020-04-16 12:55:19 -07001041 }
1042
felipeale5bf0322020-04-16 15:10:57 -07001043 int resultStatus = UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE;
felipealf7368962020-04-16 12:55:19 -07001044
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001045 synchronized (mLockUser) {
Felipe Leme5d5ab142020-10-27 13:49:10 -07001046 if (halCallbackStatus != HalCallback.STATUS_OK) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001047 Slog.w(TAG, "invalid callback status ("
Felipe Leme5d5ab142020-10-27 13:49:10 -07001048 + UserHalHelper.halCallbackStatusToString(halCallbackStatus)
1049 + ") for response " + resp);
felipealdfdf8512020-06-01 09:35:45 -07001050 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001051 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
1052 return;
1053 }
felipealf7368962020-04-16 12:55:19 -07001054
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001055 if (mUserIdForUserSwitchInProcess != targetUserId) {
1056 // Another user switch request received while HAL responded. No need to process
1057 // this request further
Eric Jeongf75d4132020-12-21 13:48:23 -08001058 if (Log.isLoggable(TAG, Log.DEBUG)) {
1059 Slog.d(TAG, "Another user switch received while HAL responsed. Request"
1060 + " abondoned for : " + targetUserId + ". Current user in process: "
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001061 + mUserIdForUserSwitchInProcess);
felipealf7368962020-04-16 12:55:19 -07001062 }
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001063 resultStatus =
1064 UserSwitchResult.STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST;
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 }
1069
1070 switch (resp.status) {
1071 case SwitchUserStatus.SUCCESS:
1072 boolean switched;
1073 try {
1074 switched = mAm.switchUser(targetUserId);
1075 if (switched) {
Mayank Garg587f1942020-05-06 01:41:34 -07001076 sendUserSwitchUiCallback(targetUserId);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001077 resultStatus = UserSwitchResult.STATUS_SUCCESSFUL;
1078 mRequestIdForUserSwitchInProcess = resp.requestId;
1079 } else {
1080 resultStatus = UserSwitchResult.STATUS_ANDROID_FAILURE;
1081 postSwitchHalResponse(resp.requestId, targetUserId);
1082 }
1083 } catch (RemoteException e) {
1084 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001085 Slog.w(TAG,
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001086 "error while switching user " + targetUser.toFullString(), e);
1087 }
1088 break;
1089 case SwitchUserStatus.FAILURE:
1090 // HAL failed to switch user
1091 resultStatus = UserSwitchResult.STATUS_HAL_FAILURE;
1092 break;
felipealdfdf8512020-06-01 09:35:45 -07001093 default:
1094 // Shouldn't happen because UserHalService validates the status
Eric Jeongf75d4132020-12-21 13:48:23 -08001095 Slog.wtf(TAG, "Received invalid user switch status from HAL: " + resp);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001096 }
1097
1098 if (mRequestIdForUserSwitchInProcess == 0) {
1099 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
1100 }
Mayank Garg59f22192020-03-27 00:51:45 -07001101 }
Felipe Leme5d5ab142020-10-27 13:49:10 -07001102 sendUserSwitchResult(receiver, halCallbackStatus, resultStatus, resp.errorMessage);
Mayank Garg59f22192020-03-27 00:51:45 -07001103 });
1104 }
1105
Mayank Garga55c3092020-05-28 03:19:24 -07001106 @Override
Mayank Gargc9266482021-03-01 10:27:37 -08001107 public void removeUser(@UserIdInt int userId, AndroidFuture<UserRemovalResult> receiver) {
1108 removeUser(userId, /* hasCallerRestrictions= */ false, receiver);
Felipe Leme55236722020-10-16 16:54:32 -07001109 }
1110
1111 /**
1112 * Internal implementation of {@code removeUser()}, which is used by both
1113 * {@code ICarUserService} and {@code ICarDevicePolicyService}.
1114 *
1115 * @param userId user to be removed
1116 * @param hasCallerRestrictions when {@code true}, if the caller user is not an admin, it can
1117 * only remove itself.
Mayank Gargc9266482021-03-01 10:27:37 -08001118 * @param receiver to post results
Felipe Leme55236722020-10-16 16:54:32 -07001119 */
Mayank Gargc9266482021-03-01 10:27:37 -08001120 public void removeUser(@UserIdInt int userId, boolean hasCallerRestrictions,
1121 AndroidFuture<UserRemovalResult> receiver) {
Felipe Leme17799202020-09-03 12:55:53 -07001122 checkManageOrCreateUsersPermission("removeUser");
Felipe Leme55236722020-10-16 16:54:32 -07001123 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_REMOVE_USER_REQ, userId,
1124 hasCallerRestrictions ? 1 : 0);
Felipe Lemee5bb26b2020-10-26 15:49:17 -07001125
Felipe Lemee5bb26b2020-10-26 15:49:17 -07001126 if (hasCallerRestrictions) {
1127 // Restrictions: non-admin user can only remove itself, admins have no restrictions
1128 int callingUserId = Binder.getCallingUserHandle().getIdentifier();
1129 UserInfo callingUser = mUserManager.getUserInfo(callingUserId);
1130 if (!callingUser.isAdmin() && userId != callingUserId) {
1131 throw new SecurityException("Non-admin user " + callingUserId
1132 + " can only remove itself");
1133 }
1134 }
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001135 mHandler.post(() -> handleRemoveUser(userId, hasCallerRestrictions, receiver));
Mayank Gargc9266482021-03-01 10:27:37 -08001136 }
Felipe Lemee5bb26b2020-10-26 15:49:17 -07001137
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001138 private void handleRemoveUser(@UserIdInt int userId, boolean hasCallerRestrictions,
Mayank Gargc9266482021-03-01 10:27:37 -08001139 AndroidFuture<UserRemovalResult> receiver) {
1140 UserInfo userInfo = mUserManager.getUserInfo(userId);
1141 if (userInfo == null) {
1142 sendUserRemovalResult(userId, UserRemovalResult.STATUS_USER_DOES_NOT_EXIST, receiver);
1143 return;
1144 }
Mayank Garga55c3092020-05-28 03:19:24 -07001145 android.hardware.automotive.vehicle.V2_0.UserInfo halUser =
1146 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1147 halUser.userId = userInfo.id;
1148 halUser.flags = UserHalHelper.convertFlags(userInfo);
1149 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1150
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001151 // check if the user is last admin user.
1152 boolean isLastAdmin = false;
Mayank Garga55c3092020-05-28 03:19:24 -07001153 if (UserHalHelper.isAdmin(halUser.flags)) {
1154 int size = usersInfo.existingUsers.size();
1155 int totalAdminUsers = 0;
1156 for (int i = 0; i < size; i++) {
1157 if (UserHalHelper.isAdmin(usersInfo.existingUsers.get(i).flags)) {
1158 totalAdminUsers++;
1159 }
1160 }
1161 if (totalAdminUsers == 1) {
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001162 isLastAdmin = true;
Mayank Garga55c3092020-05-28 03:19:24 -07001163 }
1164 }
1165
1166 // First remove user from android and then remove from HAL because HAL remove user is one
1167 // way call.
Felipe Leme9a751912021-01-05 17:45:48 -08001168 // TODO(b/170887769): rename hasCallerRestrictions to fromCarDevicePolicyManager (or use an
1169 // int / enum to indicate if it's called from CarUserManager or CarDevicePolicyManager), as
1170 // it's counter-intuitive that it's "allowed even when disallowed" when it
1171 // "has caller restrictions"
1172 boolean evenWhenDisallowed = hasCallerRestrictions;
1173 int result = mUserManager.removeUserOrSetEphemeral(userId, evenWhenDisallowed);
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001174 if (result == UserManager.REMOVE_RESULT_ERROR) {
Mayank Gargc9266482021-03-01 10:27:37 -08001175 sendUserRemovalResult(userId, UserRemovalResult.STATUS_ANDROID_FAILURE, receiver);
1176 return;
Mayank Garga55c3092020-05-28 03:19:24 -07001177 }
1178
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001179 if (isLastAdmin) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001180 Slog.w(TAG,
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001181 "Last admin user successfully removed or set ephemeral. User Id: " + userId);
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001182 }
1183
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001184 switch (result) {
1185 case UserManager.REMOVE_RESULT_REMOVED:
1186 case UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED:
Mayank Gargc9266482021-03-01 10:27:37 -08001187 sendUserRemovalResult(userId,
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001188 isLastAdmin ? UserRemovalResult.STATUS_SUCCESSFUL_LAST_ADMIN_REMOVED
Mayank Gargc9266482021-03-01 10:27:37 -08001189 : UserRemovalResult.STATUS_SUCCESSFUL, receiver);
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001190 case UserManager.REMOVE_RESULT_SET_EPHEMERAL:
Mayank Gargc9266482021-03-01 10:27:37 -08001191 sendUserRemovalResult(userId,
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001192 isLastAdmin ? UserRemovalResult.STATUS_SUCCESSFUL_LAST_ADMIN_SET_EPHEMERAL
Mayank Gargc9266482021-03-01 10:27:37 -08001193 : UserRemovalResult.STATUS_SUCCESSFUL_SET_EPHEMERAL, receiver);
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001194 default:
Mayank Gargc9266482021-03-01 10:27:37 -08001195 sendUserRemovalResult(userId, UserRemovalResult.STATUS_ANDROID_FAILURE, receiver);
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001196 }
Mayank Garga55c3092020-05-28 03:19:24 -07001197 }
1198
Felipe Leme67d564c2020-11-13 15:35:34 -08001199 /**
1200 * Should be called by {@code ICarImpl} only.
1201 */
1202 public void onUserRemoved(@NonNull UserInfo user) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001203 if (Log.isLoggable(TAG, Log.DEBUG)) {
1204 Slog.d(TAG, "onUserRemoved: " + user.toFullString());
Felipe Leme67d564c2020-11-13 15:35:34 -08001205 }
1206 notifyHalUserRemoved(user);
1207 }
1208
1209 private void notifyHalUserRemoved(@NonNull UserInfo user) {
Felipe Leme6b34fc32020-10-26 15:49:17 -07001210 if (!isUserHalSupported()) return;
1211
Felipe Leme67d564c2020-11-13 15:35:34 -08001212 if (user == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001213 Slog.wtf(TAG, "notifyHalUserRemoved() called for null user");
Felipe Leme67d564c2020-11-13 15:35:34 -08001214 return;
1215 }
1216
1217 int userId = user.id;
1218
Felipe Leme6b34fc32020-10-26 15:49:17 -07001219 if (userId == UserHandle.USER_NULL) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001220 Slog.wtf(TAG, "notifyHalUserRemoved() called for UserHandle.USER_NULL");
Felipe Leme6b34fc32020-10-26 15:49:17 -07001221 return;
1222 }
1223
1224 synchronized (mLockUser) {
1225 if (mFailedToCreateUserIds.get(userId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001226 if (Log.isLoggable(TAG, Log.DEBUG)) {
1227 Slog.d(TAG, "notifyHalUserRemoved(): skipping " + userId);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001228 }
1229 mFailedToCreateUserIds.delete(userId);
1230 return;
1231 }
1232 }
1233
1234 android.hardware.automotive.vehicle.V2_0.UserInfo halUser =
1235 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1236 halUser.userId = userId;
Felipe Leme67d564c2020-11-13 15:35:34 -08001237 halUser.flags = UserHalHelper.convertFlags(user);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001238
1239 RemoveUserRequest request = new RemoveUserRequest();
1240 request.removedUserInfo = halUser;
1241 request.usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1242 mHal.removeUser(request);
1243 }
1244
Mayank Gargc9266482021-03-01 10:27:37 -08001245 private void sendUserRemovalResult(@UserIdInt int userId, @UserRemovalResult.Status int result,
1246 AndroidFuture<UserRemovalResult> receiver) {
Mayank Garga55c3092020-05-28 03:19:24 -07001247 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_REMOVE_USER_RESP, userId, result);
Mayank Gargc9266482021-03-01 10:27:37 -08001248 receiver.complete(new UserRemovalResult(result));
Mayank Garga55c3092020-05-28 03:19:24 -07001249 }
1250
Mayank Garg587f1942020-05-06 01:41:34 -07001251 private void sendUserSwitchUiCallback(@UserIdInt int targetUserId) {
1252 if (mUserSwitchUiReceiver == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001253 Slog.w(TAG, "No User switch UI receiver.");
Mayank Garg587f1942020-05-06 01:41:34 -07001254 return;
1255 }
1256
felipealdfdf8512020-06-01 09:35:45 -07001257 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_UI_REQ, targetUserId);
Mayank Garg587f1942020-05-06 01:41:34 -07001258 try {
Mayank Garg587f1942020-05-06 01:41:34 -07001259 mUserSwitchUiReceiver.send(targetUserId, null);
1260 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001261 Slog.e(TAG, "Error calling user switch UI receiver.", e);
Mayank Garg587f1942020-05-06 01:41:34 -07001262 }
1263 }
1264
Felipe Lemecceb2992020-11-18 18:22:44 -08001265 /**
1266 * Used to create the initial user, even when it's disallowed by {@code DevicePolicyManager}.
1267 */
1268 @Nullable
1269 UserInfo createUserEvenWhenDisallowed(@Nullable String name, @NonNull String userType,
1270 @UserInfoFlag int flags) {
1271 if (mICarServiceHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001272 Slog.wtf(TAG, "createUserEvenWhenDisallowed(): mICarServiceHelper not set yet",
Felipe Lemecceb2992020-11-18 18:22:44 -08001273 new Exception());
1274 return null;
1275 }
1276 try {
1277 return mICarServiceHelper.createUserEvenWhenDisallowed(name, userType, flags);
1278 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001279 Slog.e(TAG, "createUserEvenWhenDisallowed(" + UserHelperLite.safeName(name) + ", "
Felipe Lemecceb2992020-11-18 18:22:44 -08001280 + userType + ", " + UserInfo.flagsToString(flags) + ") failed", e);
1281 return null;
1282 }
1283 }
1284
felipeal5e3ede42020-04-23 18:04:07 -07001285 @Override
felipealdfdf8512020-06-01 09:35:45 -07001286 public void createUser(@Nullable String name, @NonNull String userType, @UserInfoFlag int flags,
1287 int timeoutMs, @NonNull AndroidFuture<UserCreationResult> receiver) {
Felipe Leme8c888ab2020-11-02 17:39:52 -08001288 createUser(name, userType, flags, timeoutMs, receiver, /* hasCallerRestrictions= */ false);
1289 }
1290
1291 /**
1292 * Internal implementation of {@code createUser()}, which is used by both
1293 * {@code ICarUserService} and {@code ICarDevicePolicyService}.
1294 *
1295 * @param hasCallerRestrictions when {@code true}, if the caller user is not an admin, it can
1296 * only create admin users
1297 */
1298 public void createUser(@Nullable String name, @NonNull String userType, @UserInfoFlag int flags,
1299 int timeoutMs, @NonNull AndroidFuture<UserCreationResult> receiver,
1300 boolean hasCallerRestrictions) {
felipealdfdf8512020-06-01 09:35:45 -07001301 Objects.requireNonNull(userType, "user type cannot be null");
1302 Objects.requireNonNull(receiver, "receiver cannot be null");
Felipe Leme17799202020-09-03 12:55:53 -07001303 checkManageOrCreateUsersPermission(flags);
Mayank Garg94f3eb92020-08-12 12:38:58 -07001304 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_REQ,
Felipe Leme8c888ab2020-11-02 17:39:52 -08001305 UserHelperLite.safeName(name), userType, flags, timeoutMs,
1306 hasCallerRestrictions ? 1 : 0);
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001307 mHandler.post(() -> handleCreateUser(name, userType, flags, timeoutMs, receiver,
Mayank Garg02576972021-02-18 16:46:07 -08001308 hasCallerRestrictions));
Felipe Leme8c888ab2020-11-02 17:39:52 -08001309
Mayank Garg02576972021-02-18 16:46:07 -08001310 }
1311
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001312 private void handleCreateUser(@Nullable String name, @NonNull String userType,
Mayank Garg02576972021-02-18 16:46:07 -08001313 @UserInfoFlag int flags, int timeoutMs,
1314 @NonNull AndroidFuture<UserCreationResult> receiver,
1315 boolean hasCallerRestrictions) {
Felipe Leme8c888ab2020-11-02 17:39:52 -08001316 if (hasCallerRestrictions) {
1317 // Restrictions:
1318 // - type/flag can only be normal user, admin, or guest
1319 // - non-admin user can only create non-admin users
1320
1321 boolean validCombination;
1322 switch (userType) {
1323 case UserManager.USER_TYPE_FULL_SECONDARY:
1324 validCombination = flags == 0
1325 || (flags & UserInfo.FLAG_ADMIN) == UserInfo.FLAG_ADMIN;
1326 break;
1327 case UserManager.USER_TYPE_FULL_GUEST:
1328 validCombination = flags == 0;
1329 break;
1330 default:
1331 validCombination = false;
1332 }
1333 if (!validCombination) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001334 if (Log.isLoggable(TAG, Log.DEBUG)) {
1335 Slog.d(TAG, "Invalid combination of user type(" + userType
Felipe Leme71d296f2020-11-04 12:11:42 -08001336 + ") and flags (" + UserInfo.flagsToString(flags)
1337 + ") for caller with restrictions");
1338 }
1339 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_INVALID_REQUEST);
1340 return;
1341
Felipe Leme8c888ab2020-11-02 17:39:52 -08001342 }
1343
1344 int callingUserId = Binder.getCallingUserHandle().getIdentifier();
1345 UserInfo callingUser = mUserManager.getUserInfo(callingUserId);
1346 if (!callingUser.isAdmin() && (flags & UserInfo.FLAG_ADMIN) == UserInfo.FLAG_ADMIN) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001347 if (Log.isLoggable(TAG, Log.DEBUG)) {
1348 Slog.d(TAG, "Non-admin user " + callingUserId
Felipe Leme71d296f2020-11-04 12:11:42 -08001349 + " can only create non-admin users");
1350 }
1351 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_INVALID_REQUEST);
1352 return;
Felipe Leme8c888ab2020-11-02 17:39:52 -08001353 }
Felipe Leme71d296f2020-11-04 12:11:42 -08001354
Felipe Leme8c888ab2020-11-02 17:39:52 -08001355 }
felipealdfdf8512020-06-01 09:35:45 -07001356
1357 UserInfo newUser;
1358 try {
1359 newUser = mUserManager.createUser(name, userType, flags);
1360 if (newUser == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001361 Slog.w(TAG, "um.createUser() returned null for user of type " + userType
felipealdfdf8512020-06-01 09:35:45 -07001362 + " and flags " + UserInfo.flagsToString(flags));
1363 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_ANDROID_FAILURE);
1364 return;
1365 }
Eric Jeongf75d4132020-12-21 13:48:23 -08001366 if (Log.isLoggable(TAG, Log.DEBUG)) {
1367 Slog.d(TAG, "Created user: " + newUser.toFullString());
felipealdfdf8512020-06-01 09:35:45 -07001368 }
1369 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_USER_CREATED, newUser.id,
Mayank Garg94f3eb92020-08-12 12:38:58 -07001370 UserHelperLite.safeName(newUser.name), newUser.userType, newUser.flags);
felipealdfdf8512020-06-01 09:35:45 -07001371 } catch (RuntimeException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001372 Slog.e(TAG, "Error creating user of type " + userType + " and flags"
felipealdfdf8512020-06-01 09:35:45 -07001373 + UserInfo.flagsToString(flags), e);
1374 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_ANDROID_FAILURE);
1375 return;
1376 }
1377
Mayank Garg9ed099e2020-06-04 16:05:20 -07001378 if (!isUserHalSupported()) {
1379 sendUserCreationResult(receiver, UserCreationResult.STATUS_SUCCESSFUL, newUser, null);
1380 return;
1381 }
1382
felipealdfdf8512020-06-01 09:35:45 -07001383 CreateUserRequest request = new CreateUserRequest();
1384 request.usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1385 if (!TextUtils.isEmpty(name)) {
1386 request.newUserName = name;
1387 }
1388 request.newUserInfo.userId = newUser.id;
1389 request.newUserInfo.flags = UserHalHelper.convertFlags(newUser);
Eric Jeongf75d4132020-12-21 13:48:23 -08001390 if (Log.isLoggable(TAG, Log.DEBUG)) {
1391 Slog.d(TAG, "Create user request: " + request);
felipealdfdf8512020-06-01 09:35:45 -07001392 }
1393
1394 try {
1395 mHal.createUser(request, timeoutMs, (status, resp) -> {
1396 int resultStatus = UserCreationResult.STATUS_HAL_INTERNAL_FAILURE;
Eric Jeongf75d4132020-12-21 13:48:23 -08001397 if (Log.isLoggable(TAG, Log.DEBUG)) {
1398 Slog.d(TAG, "createUserResponse: status="
felipealdfdf8512020-06-01 09:35:45 -07001399 + UserHalHelper.halCallbackStatusToString(status) + ", resp=" + resp);
1400 }
1401 UserInfo user = null; // user returned in the result
1402 if (status != HalCallback.STATUS_OK) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001403 Slog.w(TAG, "invalid callback status ("
felipealdfdf8512020-06-01 09:35:45 -07001404 + UserHalHelper.halCallbackStatusToString(status) + ") for response "
1405 + resp);
1406 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_RESP, status,
1407 resultStatus, resp.errorMessage);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001408 removeCreatedUser(newUser, "HAL call failed with "
felipealdfdf8512020-06-01 09:35:45 -07001409 + UserHalHelper.halCallbackStatusToString(status));
1410 sendUserCreationResult(receiver, resultStatus, user, /* errorMsg= */ null);
1411 return;
1412 }
1413
1414 switch (resp.status) {
1415 case CreateUserStatus.SUCCESS:
1416 resultStatus = UserCreationResult.STATUS_SUCCESSFUL;
1417 user = newUser;
1418 break;
1419 case CreateUserStatus.FAILURE:
1420 // HAL failed to switch user
1421 resultStatus = UserCreationResult.STATUS_HAL_FAILURE;
1422 break;
1423 default:
1424 // Shouldn't happen because UserHalService validates the status
Eric Jeongf75d4132020-12-21 13:48:23 -08001425 Slog.wtf(TAG, "Received invalid user switch status from HAL: " + resp);
felipealdfdf8512020-06-01 09:35:45 -07001426 }
1427 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_RESP, status,
1428 resultStatus, resp.errorMessage);
1429 if (user == null) {
Felipe Leme6b34fc32020-10-26 15:49:17 -07001430 removeCreatedUser(newUser, "HAL returned "
felipealdfdf8512020-06-01 09:35:45 -07001431 + UserCreationResult.statusToString(resultStatus));
1432 }
1433 sendUserCreationResult(receiver, resultStatus, user, resp.errorMessage);
1434 });
1435 } catch (Exception e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001436 Slog.w(TAG, "mHal.createUser(" + request + ") failed", e);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001437 removeCreatedUser(newUser, "mHal.createUser() failed");
felipealdfdf8512020-06-01 09:35:45 -07001438 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_HAL_INTERNAL_FAILURE);
1439 }
1440 }
1441
Felipe Leme6b34fc32020-10-26 15:49:17 -07001442 private void removeCreatedUser(@NonNull UserInfo user, @NonNull String reason) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001443 Slog.i(TAG, "removing " + user.toFullString() + "; reason: " + reason);
Felipe Leme67d564c2020-11-13 15:35:34 -08001444
Felipe Leme6b34fc32020-10-26 15:49:17 -07001445 int userId = user.id;
1446 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_USER_REMOVED, userId, reason);
1447
1448 synchronized (mLockUser) {
1449 mFailedToCreateUserIds.put(userId, true);
1450 }
1451
felipealdfdf8512020-06-01 09:35:45 -07001452 try {
Felipe Leme6b34fc32020-10-26 15:49:17 -07001453 if (!mUserManager.removeUser(userId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001454 Slog.w(TAG, "Failed to remove user " + user.toFullString());
felipealdfdf8512020-06-01 09:35:45 -07001455 }
1456 } catch (Exception e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001457 Slog.e(TAG, "Failed to remove user " + user.toFullString(), e);
felipealdfdf8512020-06-01 09:35:45 -07001458 }
1459 }
1460
1461 @Override
Mayank Garg3f566582020-10-02 22:10:16 -07001462 public UserIdentificationAssociationResponse getUserIdentificationAssociation(
1463 @UserIdentificationAssociationType int[] types) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001464 if (!isUserHalUserAssociationSupported()) {
1465 return UserIdentificationAssociationResponse.forFailure(VEHICLE_HAL_NOT_SUPPORTED);
1466 }
1467
felipeal5e3ede42020-04-23 18:04:07 -07001468 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type");
Felipe Leme17799202020-09-03 12:55:53 -07001469 checkManageOrCreateUsersPermission("getUserIdentificationAssociation");
felipeal5e3ede42020-04-23 18:04:07 -07001470
1471 int uid = getCallingUid();
1472 int userId = UserHandle.getUserId(uid);
1473 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_GET_USER_AUTH_REQ, uid, userId);
1474
1475 UserIdentificationGetRequest request = new UserIdentificationGetRequest();
1476 request.userInfo.userId = userId;
1477 request.userInfo.flags = getHalUserInfoFlags(userId);
1478
1479 request.numberAssociationTypes = types.length;
1480 for (int i = 0; i < types.length; i++) {
1481 request.associationTypes.add(types[i]);
1482 }
1483
1484 UserIdentificationResponse halResponse = mHal.getUserAssociation(request);
1485 if (halResponse == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001486 Slog.w(TAG, "getUserIdentificationAssociation(): HAL returned null for "
felipeal5e3ede42020-04-23 18:04:07 -07001487 + Arrays.toString(types));
felipeal159a2a42020-05-08 10:32:11 -07001488 return UserIdentificationAssociationResponse.forFailure();
felipeal5e3ede42020-04-23 18:04:07 -07001489 }
1490
1491 int[] values = new int[halResponse.associations.size()];
1492 for (int i = 0; i < values.length; i++) {
1493 values[i] = halResponse.associations.get(i).value;
1494 }
1495 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_GET_USER_AUTH_RESP, values.length);
1496
felipeal159a2a42020-05-08 10:32:11 -07001497 return UserIdentificationAssociationResponse.forSuccess(values, halResponse.errorMessage);
1498 }
1499
1500 @Override
Mayank Garg3f566582020-10-02 22:10:16 -07001501 public void setUserIdentificationAssociation(int timeoutMs,
1502 @UserIdentificationAssociationType int[] types,
1503 @UserIdentificationAssociationSetValue int[] values,
felipeal159a2a42020-05-08 10:32:11 -07001504 AndroidFuture<UserIdentificationAssociationResponse> result) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001505 if (!isUserHalUserAssociationSupported()) {
1506 result.complete(
1507 UserIdentificationAssociationResponse.forFailure(VEHICLE_HAL_NOT_SUPPORTED));
1508 return;
1509 }
1510
felipeal159a2a42020-05-08 10:32:11 -07001511 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type");
1512 Preconditions.checkArgument(!ArrayUtils.isEmpty(values), "must have at least one value");
1513 if (types.length != values.length) {
1514 throw new IllegalArgumentException("types (" + Arrays.toString(types) + ") and values ("
1515 + Arrays.toString(values) + ") should have the same length");
1516 }
Felipe Leme17799202020-09-03 12:55:53 -07001517 checkManageOrCreateUsersPermission("setUserIdentificationAssociation");
felipeal159a2a42020-05-08 10:32:11 -07001518
1519 int uid = getCallingUid();
1520 int userId = UserHandle.getUserId(uid);
1521 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_REQ, uid, userId, types.length);
1522
1523 UserIdentificationSetRequest request = new UserIdentificationSetRequest();
1524 request.userInfo.userId = userId;
1525 request.userInfo.flags = getHalUserInfoFlags(userId);
1526
1527 request.numberAssociations = types.length;
1528 for (int i = 0; i < types.length; i++) {
1529 UserIdentificationSetAssociation association = new UserIdentificationSetAssociation();
1530 association.type = types[i];
1531 association.value = values[i];
1532 request.associations.add(association);
1533 }
1534
1535 mHal.setUserAssociation(timeoutMs, request, (status, resp) -> {
1536 if (status != HalCallback.STATUS_OK) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001537 Slog.w(TAG, "setUserIdentificationAssociation(): invalid callback status ("
felipeal159a2a42020-05-08 10:32:11 -07001538 + UserHalHelper.halCallbackStatusToString(status) + ") for response "
1539 + resp);
1540 if (resp == null || TextUtils.isEmpty(resp.errorMessage)) {
1541 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, 0);
1542 result.complete(UserIdentificationAssociationResponse.forFailure());
1543 return;
1544 }
1545 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, 0,
1546 resp.errorMessage);
1547 result.complete(
1548 UserIdentificationAssociationResponse.forFailure(resp.errorMessage));
1549 return;
1550 }
1551 int respSize = resp.associations.size();
1552 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, respSize,
1553 resp.errorMessage);
1554
1555 int[] responseTypes = new int[respSize];
1556 for (int i = 0; i < respSize; i++) {
1557 responseTypes[i] = resp.associations.get(i).value;
1558 }
1559 UserIdentificationAssociationResponse response = UserIdentificationAssociationResponse
1560 .forSuccess(responseTypes, resp.errorMessage);
Eric Jeongf75d4132020-12-21 13:48:23 -08001561 if (Log.isLoggable(TAG, Log.DEBUG)) {
1562 Slog.d(TAG, "setUserIdentificationAssociation(): resp= " + resp
felipeal159a2a42020-05-08 10:32:11 -07001563 + ", converted=" + response);
1564 }
1565 result.complete(response);
1566 });
felipeal5e3ede42020-04-23 18:04:07 -07001567 }
1568
1569 /**
1570 * Gets the User HAL flags for the given user.
1571 *
1572 * @throws IllegalArgumentException if the user does not exist.
1573 */
1574 private int getHalUserInfoFlags(@UserIdInt int userId) {
1575 UserInfo user = mUserManager.getUserInfo(userId);
1576 Preconditions.checkArgument(user != null, "no user for id %d", userId);
1577 return UserHalHelper.convertFlags(user);
1578 }
1579
Mayank Garg0e239142020-04-14 19:16:31 -07001580 private void sendResult(@NonNull IResultReceiver receiver, int resultCode,
1581 @Nullable Bundle resultData) {
1582 try {
1583 receiver.send(resultCode, resultData);
1584 } catch (RemoteException e) {
1585 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001586 Slog.w(TAG, "error while sending results", e);
Mayank Garg0e239142020-04-14 19:16:31 -07001587 }
1588 }
1589
felipealdfdf8512020-06-01 09:35:45 -07001590 private void sendUserSwitchResult(@NonNull AndroidFuture<UserSwitchResult> receiver,
Felipe Leme5d5ab142020-10-27 13:49:10 -07001591 @UserSwitchResult.Status int userSwitchStatus) {
1592 sendUserSwitchResult(receiver, HalCallback.STATUS_INVALID, userSwitchStatus,
1593 /* errorMessage= */ null);
felipeale5bf0322020-04-16 15:10:57 -07001594 }
1595
felipealdfdf8512020-06-01 09:35:45 -07001596 private void sendUserSwitchResult(@NonNull AndroidFuture<UserSwitchResult> receiver,
Felipe Leme5d5ab142020-10-27 13:49:10 -07001597 @HalCallback.HalCallbackStatus int halCallbackStatus,
1598 @UserSwitchResult.Status int userSwitchStatus, @Nullable String errorMessage) {
1599 if (errorMessage != null) {
1600 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_RESP, halCallbackStatus,
1601 userSwitchStatus, errorMessage);
1602 } else {
1603 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_RESP, halCallbackStatus,
1604 userSwitchStatus);
1605 }
1606 receiver.complete(new UserSwitchResult(userSwitchStatus, errorMessage));
felipeale5bf0322020-04-16 15:10:57 -07001607 }
1608
felipealdfdf8512020-06-01 09:35:45 -07001609 private void sendUserCreationResultFailure(@NonNull AndroidFuture<UserCreationResult> receiver,
1610 @UserCreationResult.Status int status) {
1611 sendUserCreationResult(receiver, status, /* user= */ null, /* errorMessage= */ null);
1612 }
1613
1614 private void sendUserCreationResult(@NonNull AndroidFuture<UserCreationResult> receiver,
1615 @UserCreationResult.Status int status, @NonNull UserInfo user,
1616 @Nullable String errorMessage) {
1617 if (TextUtils.isEmpty(errorMessage)) {
1618 errorMessage = null;
1619 }
1620 receiver.complete(new UserCreationResult(status, user, errorMessage));
1621 }
1622
Mayank Garg6307fe42020-04-15 23:09:03 -07001623 /**
1624 * Calls activity manager for user switch.
1625 *
1626 * <p><b>NOTE</b> This method is meant to be called just by UserHalService.
1627 *
1628 * @param requestId for the user switch request
1629 * @param targetUserId of the target user
1630 *
1631 * @hide
1632 */
1633 public void switchAndroidUserFromHal(int requestId, @UserIdInt int targetUserId) {
1634 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_FROM_HAL_REQ, requestId,
1635 targetUserId);
Eric Jeongf75d4132020-12-21 13:48:23 -08001636 Slog.i(TAG, "User hal requested a user switch. Target user id " + targetUserId);
Mayank Garg6307fe42020-04-15 23:09:03 -07001637
1638 try {
1639 boolean result = mAm.switchUser(targetUserId);
1640 if (result) {
1641 updateUserSwitchInProcess(requestId, targetUserId);
1642 } else {
1643 postSwitchHalResponse(requestId, targetUserId);
1644 }
1645 } catch (RemoteException e) {
1646 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001647 Slog.w(TAG, "error while switching user " + targetUserId, e);
Mayank Garg6307fe42020-04-15 23:09:03 -07001648 }
1649 }
1650
1651 private void updateUserSwitchInProcess(int requestId, @UserIdInt int targetUserId) {
1652 synchronized (mLockUser) {
1653 if (mUserIdForUserSwitchInProcess != UserHandle.USER_NULL) {
1654 // Some other user switch is in process.
Eric Jeongf75d4132020-12-21 13:48:23 -08001655 if (Log.isLoggable(TAG, Log.DEBUG)) {
1656 Slog.d(TAG, "User switch for user: " + mUserIdForUserSwitchInProcess
Mayank Garg6307fe42020-04-15 23:09:03 -07001657 + " is in process. Abandoning it as a new user switch is requested"
1658 + " for the target user: " + targetUserId);
1659 }
1660 }
1661 mUserIdForUserSwitchInProcess = targetUserId;
1662 mRequestIdForUserSwitchInProcess = requestId;
1663 }
1664 }
Mayank Garg9ed099e2020-06-04 16:05:20 -07001665
Mayank Garg7a114c82020-04-08 21:25:06 -07001666 private void postSwitchHalResponse(int requestId, @UserIdInt int targetUserId) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001667 if (!isUserHalSupported()) return;
1668
felipealdfdf8512020-06-01 09:35:45 -07001669 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
Mayank Gargeb37d092020-06-02 14:37:57 -07001670 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_POST_SWITCH_USER_REQ, requestId,
1671 targetUserId, usersInfo.currentUser.userId);
1672 SwitchUserRequest request = createUserSwitchRequest(targetUserId, usersInfo);
1673 request.requestId = requestId;
1674 mHal.postSwitchResponse(request);
1675 }
1676
1677 private SwitchUserRequest createUserSwitchRequest(@UserIdInt int targetUserId,
1678 @NonNull UsersInfo usersInfo) {
1679 UserInfo targetUser = mUserManager.getUserInfo(targetUserId);
Mayank Garg7a114c82020-04-08 21:25:06 -07001680 android.hardware.automotive.vehicle.V2_0.UserInfo halTargetUser =
1681 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1682 halTargetUser.userId = targetUser.id;
1683 halTargetUser.flags = UserHalHelper.convertFlags(targetUser);
Mayank Gargeb37d092020-06-02 14:37:57 -07001684 SwitchUserRequest request = new SwitchUserRequest();
1685 request.targetUser = halTargetUser;
1686 request.usersInfo = usersInfo;
1687 return request;
Mayank Garg7a114c82020-04-08 21:25:06 -07001688 }
1689
Mayank Garg59f22192020-03-27 00:51:45 -07001690 /**
Felipe Lemee3cab982020-03-12 11:39:29 -07001691 * Checks if the User HAL is supported.
1692 */
1693 public boolean isUserHalSupported() {
1694 return mHal.isSupported();
1695 }
1696
Mayank Garg587f1942020-05-06 01:41:34 -07001697 /**
Mayank Garg9ed099e2020-06-04 16:05:20 -07001698 * Checks if the User HAL user association is supported.
1699 */
1700 @Override
1701 public boolean isUserHalUserAssociationSupported() {
1702 return mHal.isUserAssociationSupported();
1703 }
1704
1705 /**
Mayank Garg587f1942020-05-06 01:41:34 -07001706 * Sets a callback which is invoked before user switch.
1707 *
1708 * <p>
1709 * This method should only be called by the Car System UI. The purpose of this call is to notify
1710 * Car System UI to show the user switch UI before the user switch.
1711 */
1712 @Override
1713 public void setUserSwitchUiCallback(@NonNull IResultReceiver receiver) {
Yan Zhu67a383e2020-05-11 20:46:24 -07001714 checkManageUsersPermission("setUserSwitchUiCallback");
Mayank Garga480dd92020-05-14 03:14:57 -07001715
1716 // Confirm that caller is system UI.
1717 String systemUiPackageName = getSystemUiPackageName();
1718 if (systemUiPackageName == null) {
1719 throw new IllegalStateException("System UI package not found.");
1720 }
1721
1722 try {
1723 int systemUiUid = mContext
1724 .createContextAsUser(UserHandle.SYSTEM, /* flags= */ 0).getPackageManager()
1725 .getPackageUid(systemUiPackageName, PackageManager.MATCH_SYSTEM_ONLY);
1726 int callerUid = Binder.getCallingUid();
1727 if (systemUiUid != callerUid) {
1728 throw new SecurityException("Invalid caller. Only" + systemUiPackageName
1729 + " is allowed to make this call");
1730 }
1731 } catch (NameNotFoundException e) {
1732 throw new IllegalStateException("Package " + systemUiPackageName + " not found.");
1733 }
1734
Mayank Garg587f1942020-05-06 01:41:34 -07001735 mUserSwitchUiReceiver = receiver;
1736 }
1737
Mayank Garga480dd92020-05-14 03:14:57 -07001738 // TODO(157082995): This information can be taken from
1739 // PackageManageInternalImpl.getSystemUiServiceComponent
1740 @Nullable
1741 private String getSystemUiPackageName() {
1742 try {
1743 ComponentName componentName = ComponentName.unflattenFromString(mContext.getResources()
1744 .getString(com.android.internal.R.string.config_systemUIServiceComponent));
1745 return componentName.getPackageName();
1746 } catch (RuntimeException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001747 Slog.w(TAG, "error while getting system UI package name.", e);
Mayank Garga480dd92020-05-14 03:14:57 -07001748 return null;
1749 }
1750 }
1751
Keun young Park13a7a822019-04-04 15:53:08 -07001752 private void updateDefaultUserRestriction() {
1753 // We want to set restrictions on system and guest users only once. These are persisted
1754 // onto disk, so it's sufficient to do it once + we minimize the number of disk writes.
1755 if (Settings.Global.getInt(mContext.getContentResolver(),
Eric Jeong1545f3b2019-09-16 13:56:52 -07001756 CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, /* default= */ 0) != 0) {
1757 return;
Keun young Park13a7a822019-04-04 15:53:08 -07001758 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07001759 // Only apply the system user restrictions if the system user is headless.
1760 if (UserManager.isHeadlessSystemUserMode()) {
1761 setSystemUserRestrictions();
1762 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07001763 Settings.Global.putInt(mContext.getContentResolver(),
1764 CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, 1);
Keun young Park13a7a822019-04-04 15:53:08 -07001765 }
1766
Eric Jeong1545f3b2019-09-16 13:56:52 -07001767 private boolean isPersistentUser(@UserIdInt int userId) {
Anthony Hugh9932a252019-06-12 16:19:56 -07001768 return !mUserManager.getUserInfo(userId).isEphemeral();
1769 }
1770
Antonio Kantekc8114752020-03-05 21:37:39 -08001771 /**
Antonio Kantekc8114752020-03-05 21:37:39 -08001772 * Adds a new {@link UserLifecycleListener} to listen to user activity events.
1773 */
1774 public void addUserLifecycleListener(@NonNull UserLifecycleListener listener) {
1775 Objects.requireNonNull(listener, "listener cannot be null");
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001776 mHandler.post(() -> mUserLifecycleListeners.add(listener));
Antonio Kantekc8114752020-03-05 21:37:39 -08001777 }
1778
1779 /**
1780 * Removes previously added {@link UserLifecycleListener}.
1781 */
1782 public void removeUserLifecycleListener(@NonNull UserLifecycleListener listener) {
1783 Objects.requireNonNull(listener, "listener cannot be null");
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001784 mHandler.post(() -> mUserLifecycleListeners.remove(listener));
Antonio Kantekc8114752020-03-05 21:37:39 -08001785 }
1786
Eric Jeongc91f9452019-08-30 15:04:21 -07001787 /** Adds callback to listen to passenger activity events. */
1788 public void addPassengerCallback(@NonNull PassengerCallback callback) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00001789 Objects.requireNonNull(callback, "callback cannot be null");
Eric Jeongc91f9452019-08-30 15:04:21 -07001790 mPassengerCallbacks.add(callback);
1791 }
1792
1793 /** Removes previously added callback to listen passenger events. */
1794 public void removePassengerCallback(@NonNull PassengerCallback callback) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00001795 Objects.requireNonNull(callback, "callback cannot be null");
Eric Jeongc91f9452019-08-30 15:04:21 -07001796 mPassengerCallbacks.remove(callback);
1797 }
1798
1799 /** Sets the implementation of ZoneUserBindingHelper. */
1800 public void setZoneUserBindingHelper(@NonNull ZoneUserBindingHelper helper) {
1801 synchronized (mLockHelper) {
1802 mZoneUserBindingHelper = helper;
1803 }
1804 }
1805
felipeal98900c82020-04-09 09:05:02 -07001806 private void onUserUnlocked(@UserIdInt int userId) {
Keun-young Parkd462a912019-02-11 08:53:42 -08001807 ArrayList<Runnable> tasks = null;
Eric Jeongc91f9452019-08-30 15:04:21 -07001808 synchronized (mLockUser) {
Mayank Garg7a114c82020-04-08 21:25:06 -07001809 sendPostSwitchToHalLocked(userId);
Eric Jeong1545f3b2019-09-16 13:56:52 -07001810 if (userId == UserHandle.USER_SYSTEM) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001811 if (!mUser0Unlocked) { // user 0, unlocked, do this only once
1812 updateDefaultUserRestriction();
1813 tasks = new ArrayList<>(mUser0UnlockTasks);
1814 mUser0UnlockTasks.clear();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001815 mUser0Unlocked = true;
Keun young Parkf3523cd2019-04-08 10:09:17 -07001816 }
1817 } else { // none user0
Eric Jeong1545f3b2019-09-16 13:56:52 -07001818 Integer user = userId;
1819 if (isPersistentUser(userId)) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001820 // current foreground user should stay in top priority.
Anthony Hughfbb67762019-10-15 12:54:54 -07001821 if (userId == ActivityManager.getCurrentUser()) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001822 mBackgroundUsersToRestart.remove(user);
1823 mBackgroundUsersToRestart.add(0, user);
1824 }
1825 // -1 for user 0
1826 if (mBackgroundUsersToRestart.size() > (mMaxRunningUsers - 1)) {
Eric Jeong1545f3b2019-09-16 13:56:52 -07001827 int userToDrop = mBackgroundUsersToRestart.get(
Keun young Parkf3523cd2019-04-08 10:09:17 -07001828 mBackgroundUsersToRestart.size() - 1);
Eric Jeongf75d4132020-12-21 13:48:23 -08001829 Slog.i(TAG, "New user unlocked:" + userId
Keun young Parkf3523cd2019-04-08 10:09:17 -07001830 + ", dropping least recently user from restart list:" + userToDrop);
1831 // Drop the least recently used user.
1832 mBackgroundUsersToRestart.remove(mBackgroundUsersToRestart.size() - 1);
1833 }
1834 }
Keun-young Parkd462a912019-02-11 08:53:42 -08001835 }
1836 }
1837 if (tasks != null && tasks.size() > 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001838 Slog.d(TAG, "User0 unlocked, run queued tasks:" + tasks.size());
Keun-young Parkd462a912019-02-11 08:53:42 -08001839 for (Runnable r : tasks) {
1840 r.run();
1841 }
1842 }
1843 }
1844
1845 /**
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001846 * Starts the specified user in the background.
1847 *
1848 * @param userId user to start in background
1849 * @param receiver to post results
1850 */
1851 public void startUserInBackground(@UserIdInt int userId,
1852 @NonNull AndroidFuture<UserStartResult> receiver) {
1853 mHandler.post(() -> handleStartUserInBackground(userId, receiver));
1854 }
1855
1856 private void handleStartUserInBackground(@UserIdInt int userId,
1857 @NonNull AndroidFuture<UserStartResult> receiver) {
1858 // If the requested user is the current user, do nothing and return success.
1859 if (ActivityManager.getCurrentUser() == userId) {
1860 sendUserStartResult(UserStartResult.STATUS_SUCCESSFUL_USER_IS_CURRENT_USER, receiver);
1861 return;
1862 }
1863 // If requested user does not exist, return error.
1864 if (mUserManager.getUserInfo(userId) == null) {
1865 Slogf.w(TAG, "User %d does not exist", userId);
1866 sendUserStartResult(UserStartResult.STATUS_USER_DOES_NOT_EXIST, receiver);
1867 return;
1868 }
1869
1870 try {
1871 if (!mAm.startUserInBackground(userId)) {
1872 Slogf.w(TAG, "Failed to start user %d in background", userId);
1873 sendUserStartResult(UserStartResult.STATUS_ANDROID_FAILURE, receiver);
1874 return;
1875 }
1876 } catch (RemoteException e) {
1877 Slogf.w(TAG, e, "Failed to start user %d in background", userId);
1878 }
1879
1880 // TODO(b/181331178): We are not updating mBackgroundUsersToRestart or
1881 // mBackgroundUsersRestartedHere, which were only used for the garage mode. Consider
1882 // renaming them to make it more clear.
1883 sendUserStartResult(UserStartResult.STATUS_SUCCESSFUL, receiver);
1884 }
1885
1886 private void sendUserStartResult(@UserStartResult.Status int result,
1887 @NonNull AndroidFuture<UserStartResult> receiver) {
1888 // TODO(b/181331178): Add event log calls.
1889 receiver.complete(new UserStartResult(result));
1890 }
1891
1892 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -07001893 * Starts all background users that were active in system.
1894 *
Keun young Parkfb656372019-03-12 18:37:55 -07001895 * @return list of background users started successfully.
1896 */
Eric Jeong1545f3b2019-09-16 13:56:52 -07001897 @NonNull
Keun young Parkfb656372019-03-12 18:37:55 -07001898 public ArrayList<Integer> startAllBackgroundUsers() {
1899 ArrayList<Integer> users;
Eric Jeongc91f9452019-08-30 15:04:21 -07001900 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001901 users = new ArrayList<>(mBackgroundUsersToRestart);
1902 mBackgroundUsersRestartedHere.clear();
1903 mBackgroundUsersRestartedHere.addAll(mBackgroundUsersToRestart);
Keun young Parkfb656372019-03-12 18:37:55 -07001904 }
1905 ArrayList<Integer> startedUsers = new ArrayList<>();
1906 for (Integer user : users) {
Anthony Hughfbb67762019-10-15 12:54:54 -07001907 if (user == ActivityManager.getCurrentUser()) {
Keun young Parkfb656372019-03-12 18:37:55 -07001908 continue;
1909 }
1910 try {
1911 if (mAm.startUserInBackground(user)) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001912 if (mUserManager.isUserUnlockingOrUnlocked(user)) {
1913 // already unlocked / unlocking. No need to unlock.
Keun young Parkfb656372019-03-12 18:37:55 -07001914 startedUsers.add(user);
Keun young Parkf3523cd2019-04-08 10:09:17 -07001915 } else if (mAm.unlockUser(user, null, null, null)) {
1916 startedUsers.add(user);
1917 } else { // started but cannot unlock
Eric Jeongf75d4132020-12-21 13:48:23 -08001918 Slog.w(TAG, "Background user started but cannot be unlocked:" + user);
Keun young Parkf3523cd2019-04-08 10:09:17 -07001919 if (mUserManager.isUserRunning(user)) {
1920 // add to started list so that it can be stopped later.
1921 startedUsers.add(user);
1922 }
Keun young Parkfb656372019-03-12 18:37:55 -07001923 }
1924 }
1925 } catch (RemoteException e) {
1926 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001927 Slog.w(TAG, "error while starting user in background", e);
Keun young Parkfb656372019-03-12 18:37:55 -07001928 }
1929 }
Keun young Parkf3523cd2019-04-08 10:09:17 -07001930 // Keep only users that were re-started in mBackgroundUsersRestartedHere
Eric Jeongc91f9452019-08-30 15:04:21 -07001931 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001932 ArrayList<Integer> usersToRemove = new ArrayList<>();
1933 for (Integer user : mBackgroundUsersToRestart) {
1934 if (!startedUsers.contains(user)) {
1935 usersToRemove.add(user);
1936 }
1937 }
1938 mBackgroundUsersRestartedHere.removeAll(usersToRemove);
1939 }
Keun young Parkfb656372019-03-12 18:37:55 -07001940 return startedUsers;
1941 }
1942
1943 /**
bkchoid77d0bc2021-04-22 13:43:03 -07001944 * Stops the specified background user.
1945 *
1946 * @param userId user to stop
1947 * @param receiver to post results
1948 */
1949 public void stopUser(@UserIdInt int userId, @NonNull AndroidFuture<UserStopResult> receiver) {
1950 mHandler.post(() -> handleStopUser(userId, receiver));
1951 }
1952
1953 private void handleStopUser(
1954 @UserIdInt int userId, @NonNull AndroidFuture<UserStopResult> receiver) {
1955 @UserStopResult.Status int userStopStatus = stopBackgroundUserInternal(userId);
1956 sendUserStopResult(userStopStatus, receiver);
1957 }
1958
1959 private void sendUserStopResult(@UserStopResult.Status int result,
1960 @NonNull AndroidFuture<UserStopResult> receiver) {
1961 // TODO(b/181331178): Add event log calls.
1962 receiver.complete(new UserStopResult(result));
1963 }
1964
1965 private @UserStopResult.Status int stopBackgroundUserInternal(@UserIdInt int userId) {
1966 try {
1967 int r = mAm.stopUserWithDelayedLocking(userId, true, null);
1968 switch(r) {
1969 case ActivityManager.USER_OP_SUCCESS:
1970 return UserStopResult.STATUS_SUCCESSFUL;
1971 case ActivityManager.USER_OP_ERROR_IS_SYSTEM:
1972 Slogf.w(TAG, "Cannot stop the system user: %d", userId);
1973 return UserStopResult.STATUS_FAILURE_SYSTEM_USER;
1974 case ActivityManager.USER_OP_IS_CURRENT:
1975 Slogf.w(TAG, "Cannot stop the current user: %d", userId);
1976 return UserStopResult.STATUS_FAILURE_CURRENT_USER;
1977 case ActivityManager.USER_OP_UNKNOWN_USER:
1978 Slogf.w(TAG, "Cannot stop the user that does not exist: %d", userId);
1979 return UserStopResult.STATUS_USER_DOES_NOT_EXIST;
1980 default:
1981 Slogf.w(TAG, "stopUser failed, user: %d, err: %d", userId, r);
1982 }
1983 } catch (RemoteException e) {
1984 // ignore the exception
1985 Slogf.w(TAG, e, "error while stopping user: %d", userId);
1986 }
1987 return UserStopResult.STATUS_ANDROID_FAILURE;
1988 }
1989
1990 /**
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001991 * Stops a background user.
Eric Jeong1545f3b2019-09-16 13:56:52 -07001992 *
1993 * @return whether stopping succeeds.
Keun young Parkfb656372019-03-12 18:37:55 -07001994 */
Eric Jeong1545f3b2019-09-16 13:56:52 -07001995 public boolean stopBackgroundUser(@UserIdInt int userId) {
bkchoid77d0bc2021-04-22 13:43:03 -07001996 @UserStopResult.Status int userStopStatus = stopBackgroundUserInternal(userId);
1997 if (UserStopResult.isSuccess(userStopStatus)) {
1998 // Remove the stopped user from the mBackgroundUserRestartedHere list.
1999 synchronized (mLockUser) {
2000 mBackgroundUsersRestartedHere.remove(Integer.valueOf(userId));
Keun young Parkfb656372019-03-12 18:37:55 -07002001 }
bkchoid77d0bc2021-04-22 13:43:03 -07002002 return true;
Keun young Parkfb656372019-03-12 18:37:55 -07002003 }
bkchoid77d0bc2021-04-22 13:43:03 -07002004 return false;
Keun young Parkfb656372019-03-12 18:37:55 -07002005 }
2006
2007 /**
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002008 * Notifies all registered {@link UserLifecycleListener} with the event passed as argument.
Pavel Maltsev17e81832019-04-04 14:38:41 -07002009 */
Mayank Gargccad8062020-08-30 15:05:10 -07002010 public void onUserLifecycleEvent(@UserLifecycleEventType int eventType,
felipeale8c5dce2020-04-15 11:27:06 -07002011 @UserIdInt int fromUserId, @UserIdInt int toUserId) {
2012 int userId = toUserId;
felipeal98900c82020-04-09 09:05:02 -07002013
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002014 // Handle special cases first...
felipeal98900c82020-04-09 09:05:02 -07002015 if (eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING) {
Mayank Garge5de0f92020-04-23 21:38:38 -07002016 onUserSwitching(fromUserId, toUserId);
felipeal98900c82020-04-09 09:05:02 -07002017 } else if (eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_UNLOCKED) {
2018 onUserUnlocked(userId);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002019 }
2020
felipeale8c5dce2020-04-15 11:27:06 -07002021 // ...then notify listeners.
Yan Zhue7921522020-04-16 15:59:25 -07002022 UserLifecycleEvent event = new UserLifecycleEvent(eventType, fromUserId, userId);
felipeale8c5dce2020-04-15 11:27:06 -07002023
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002024 mHandler.post(() -> {
2025 handleNotifyServiceUserLifecycleListeners(event);
2026 handleNotifyAppUserLifecycleListeners(event);
2027 });
felipeale8c5dce2020-04-15 11:27:06 -07002028 }
2029
Mayank Garg7a114c82020-04-08 21:25:06 -07002030 private void sendPostSwitchToHalLocked(@UserIdInt int userId) {
felipealf7368962020-04-16 12:55:19 -07002031 if (mUserIdForUserSwitchInProcess == UserHandle.USER_NULL
Mayank Garg1f20dcd2020-04-22 17:46:01 -07002032 || mUserIdForUserSwitchInProcess != userId
2033 || mRequestIdForUserSwitchInProcess == 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002034 if (Log.isLoggable(TAG, Log.DEBUG)) {
2035 Slog.d(TAG, "No user switch request Id. No android post switch sent.");
Mayank Garg7a114c82020-04-08 21:25:06 -07002036 }
2037 return;
2038 }
felipealf7368962020-04-16 12:55:19 -07002039 postSwitchHalResponse(mRequestIdForUserSwitchInProcess, mUserIdForUserSwitchInProcess);
2040 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
Mayank Garg1f20dcd2020-04-22 17:46:01 -07002041 mRequestIdForUserSwitchInProcess = 0;
Mayank Garg7a114c82020-04-08 21:25:06 -07002042 }
2043
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002044 private void handleNotifyAppUserLifecycleListeners(UserLifecycleEvent event) {
2045 int listenersSize = mAppLifecycleListeners.size();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002046 if (listenersSize == 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002047 if (Log.isLoggable(TAG, Log.DEBUG)) {
2048 Slog.d(TAG, "No app listener to be notified of " + event);
felipeal2a84d512020-04-06 18:52:15 -07002049 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002050 return;
2051 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002052 // Must use a different TimingsTraceLog because it's another thread
Eric Jeongf75d4132020-12-21 13:48:23 -08002053 if (Log.isLoggable(TAG, Log.DEBUG)) {
2054 Slog.d(TAG, "Notifying " + listenersSize + " app listeners of " + event);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002055 }
felipeal2a84d512020-04-06 18:52:15 -07002056 int userId = event.getUserId();
Eric Jeongf75d4132020-12-21 13:48:23 -08002057 TimingsTraceLog t = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
felipealde1e16d2020-06-03 13:20:48 -07002058 int eventType = event.getEventType();
2059 t.traceBegin("notify-app-listeners-user-" + userId + "-event-" + eventType);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002060 for (int i = 0; i < listenersSize; i++) {
2061 int uid = mAppLifecycleListeners.keyAt(i);
felipealde1e16d2020-06-03 13:20:48 -07002062
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002063 IResultReceiver listener = mAppLifecycleListeners.valueAt(i);
2064 Bundle data = new Bundle();
felipealde1e16d2020-06-03 13:20:48 -07002065 data.putInt(CarUserManager.BUNDLE_PARAM_ACTION, eventType);
Yan Zhue7921522020-04-16 15:59:25 -07002066
felipealde1e16d2020-06-03 13:20:48 -07002067 int fromUserId = event.getPreviousUserId();
2068 if (fromUserId != UserHandle.USER_NULL) {
2069 data.putInt(CarUserManager.BUNDLE_PARAM_PREVIOUS_USER_ID, fromUserId);
Yan Zhue7921522020-04-16 15:59:25 -07002070 }
2071
Eric Jeongf75d4132020-12-21 13:48:23 -08002072 if (Log.isLoggable(TAG, Log.DEBUG)) {
2073 Slog.d(TAG, "Notifying listener for uid " + uid);
felipeal2a84d512020-04-06 18:52:15 -07002074 }
felipealde1e16d2020-06-03 13:20:48 -07002075 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_NOTIFY_APP_LIFECYCLE_LISTENER,
2076 uid, eventType, fromUserId, userId);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002077 try {
felipealde1e16d2020-06-03 13:20:48 -07002078 t.traceBegin("notify-app-listener-uid-" + uid);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002079 listener.send(userId, data);
2080 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002081 Slog.e(TAG, "Error calling lifecycle listener", e);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002082 } finally {
2083 t.traceEnd();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002084 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002085 }
2086 t.traceEnd(); // notify-app-listeners-user-USERID-event-EVENT_TYPE
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002087 }
2088
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002089 private void handleNotifyServiceUserLifecycleListeners(UserLifecycleEvent event) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002090 TimingsTraceLog t = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002091 if (mUserLifecycleListeners.isEmpty()) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002092 Slog.w(TAG, "Not notifying internal UserLifecycleListeners");
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002093 return;
Eric Jeongf75d4132020-12-21 13:48:23 -08002094 } else if (Log.isLoggable(TAG, Log.DEBUG)) {
2095 Slog.d(TAG, "Notifying " + mUserLifecycleListeners.size()
2096 + " service listeners of " + event);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002097 }
felipeal2a84d512020-04-06 18:52:15 -07002098
felipealde1e16d2020-06-03 13:20:48 -07002099 int userId = event.getUserId();
2100 int eventType = event.getEventType();
2101 t.traceBegin("notify-listeners-user-" + userId + "-event-" + eventType);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002102 for (UserLifecycleListener listener : mUserLifecycleListeners) {
felipeal2a84d512020-04-06 18:52:15 -07002103 String listenerName = FunctionalUtils.getLambdaName(listener);
felipealde1e16d2020-06-03 13:20:48 -07002104 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_NOTIFY_INTERNAL_LIFECYCLE_LISTENER,
2105 listenerName, eventType, event.getPreviousUserId(), userId);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002106 try {
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002107 t.traceBegin("notify-listener-" + listenerName);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002108 listener.onEvent(event);
2109 } catch (RuntimeException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002110 Slog.e(TAG,
felipeal2a84d512020-04-06 18:52:15 -07002111 "Exception raised when invoking onEvent for " + listenerName, e);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002112 } finally {
2113 t.traceEnd();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002114 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002115 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002116 t.traceEnd(); // notify-listeners-user-USERID-event-EVENT_TYPE
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002117 }
2118
Mayank Garge5de0f92020-04-23 21:38:38 -07002119 private void onUserSwitching(@UserIdInt int fromUserId, @UserIdInt int toUserId) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002120 Slog.i(TAG, "onUserSwitching() callback for user " + toUserId);
2121 TimingsTraceLog t = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
Mayank Garge5de0f92020-04-23 21:38:38 -07002122 t.traceBegin("onUserSwitching-" + toUserId);
Felipe Leme5528ff72020-02-10 19:05:14 -08002123
Mayank Garge5de0f92020-04-23 21:38:38 -07002124 // Switch HAL users if user switch is not requested by CarUserService
2125 notifyHalLegacySwitch(fromUserId, toUserId);
2126
Mayank Garge90a4082020-09-30 12:57:34 -07002127 mInitialUserSetter.setLastActiveUser(toUserId);
felipealbf327652020-06-03 11:33:29 -07002128
Eric Jeongc91f9452019-08-30 15:04:21 -07002129 if (mLastPassengerId != UserHandle.USER_NULL) {
2130 stopPassengerInternal(mLastPassengerId, false);
2131 }
2132 if (mEnablePassengerSupport && isPassengerDisplayAvailable()) {
2133 setupPassengerUser();
Mayank Garge5de0f92020-04-23 21:38:38 -07002134 startFirstPassenger(toUserId);
Eric Jeongc91f9452019-08-30 15:04:21 -07002135 }
felipeal98900c82020-04-09 09:05:02 -07002136 t.traceEnd();
Pavel Maltsev17e81832019-04-04 14:38:41 -07002137 }
2138
Mayank Garge5de0f92020-04-23 21:38:38 -07002139 private void notifyHalLegacySwitch(@UserIdInt int fromUserId, @UserIdInt int toUserId) {
2140 synchronized (mLockUser) {
felipeal7d12ee22020-06-05 09:30:19 -07002141 if (mUserIdForUserSwitchInProcess != UserHandle.USER_NULL) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002142 if (Log.isLoggable(TAG, Log.DEBUG)) {
2143 Slog.d(TAG, "notifyHalLegacySwitch(" + fromUserId + ", " + toUserId
felipeal7d12ee22020-06-05 09:30:19 -07002144 + "): not needed, normal switch for " + mUserIdForUserSwitchInProcess);
2145 }
2146 return;
2147 }
Mayank Garge5de0f92020-04-23 21:38:38 -07002148 }
2149
Mayank Garg9ed099e2020-06-04 16:05:20 -07002150 if (!isUserHalSupported()) return;
2151
Mayank Garge5de0f92020-04-23 21:38:38 -07002152 // switch HAL user
felipeal7d12ee22020-06-05 09:30:19 -07002153 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager, fromUserId);
Mayank Gargeb37d092020-06-02 14:37:57 -07002154 SwitchUserRequest request = createUserSwitchRequest(toUserId, usersInfo);
2155 mHal.legacyUserSwitch(request);
Mayank Garge5de0f92020-04-23 21:38:38 -07002156 }
2157
Pavel Maltsev17e81832019-04-04 14:38:41 -07002158 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -07002159 * 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 -08002160 * run inside this call.
Eric Jeong1545f3b2019-09-16 13:56:52 -07002161 *
Keun-young Parkd462a912019-02-11 08:53:42 -08002162 * @param r Runnable to run.
2163 */
Eric Jeong1545f3b2019-09-16 13:56:52 -07002164 public void runOnUser0Unlock(@NonNull Runnable r) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00002165 Objects.requireNonNull(r, "runnable cannot be null");
Keun-young Parkd462a912019-02-11 08:53:42 -08002166 boolean runNow = false;
Eric Jeongc91f9452019-08-30 15:04:21 -07002167 synchronized (mLockUser) {
Keun-young Parkd462a912019-02-11 08:53:42 -08002168 if (mUser0Unlocked) {
2169 runNow = true;
2170 } else {
2171 mUser0UnlockTasks.add(r);
2172 }
2173 }
2174 if (runNow) {
2175 r.run();
2176 }
2177 }
2178
Keun young Parkf3523cd2019-04-08 10:09:17 -07002179 @VisibleForTesting
Eric Jeong1545f3b2019-09-16 13:56:52 -07002180 @NonNull
2181 ArrayList<Integer> getBackgroundUsersToRestart() {
2182 ArrayList<Integer> backgroundUsersToRestart = null;
Eric Jeongc91f9452019-08-30 15:04:21 -07002183 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07002184 backgroundUsersToRestart = new ArrayList<>(mBackgroundUsersToRestart);
2185 }
2186 return backgroundUsersToRestart;
2187 }
2188
Ying Zheng1ab32b62018-06-26 12:47:26 -07002189 private void setSystemUserRestrictions() {
Ying Zheng1ab32b62018-06-26 12:47:26 -07002190 // Disable Location service for system user.
2191 LocationManager locationManager =
2192 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
Anthony Hugh04ee04f2019-12-17 16:11:33 -08002193 locationManager.setLocationEnabledForUser(
2194 /* enabled= */ false, UserHandle.of(UserHandle.USER_SYSTEM));
Ying Zheng1ab32b62018-06-26 12:47:26 -07002195 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07002196
2197 /**
Anthony Hugh6fed1e92019-10-22 16:22:03 -07002198 * Assigns a default icon to a user according to the user's id.
2199 *
2200 * @param userInfo User whose avatar is set to default icon.
Anthony Hugh6fed1e92019-10-22 16:22:03 -07002201 */
Eric Jeongb2dc6ff2020-06-05 17:00:26 -07002202 private void assignDefaultIcon(UserInfo userInfo) {
Anthony Hugh6fed1e92019-10-22 16:22:03 -07002203 int idForIcon = userInfo.isGuest() ? UserHandle.USER_NULL : userInfo.id;
2204 Bitmap bitmap = UserIcons.convertToBitmap(
2205 UserIcons.getDefaultUserIcon(mContext.getResources(), idForIcon, false));
2206 mUserManager.setUserIcon(userInfo.id, bitmap);
Anthony Hugh6fed1e92019-10-22 16:22:03 -07002207 }
2208
Eric Jeong1545f3b2019-09-16 13:56:52 -07002209 private interface UserFilter {
2210 boolean isEligibleUser(UserInfo user);
2211 }
2212
2213 /** Returns all users who are matched by the given filter. */
2214 private List<UserInfo> getUsers(UserFilter filter) {
Colin Cross0df71ea2020-08-27 04:12:26 +00002215 List<UserInfo> users = mUserManager.getAliveUsers();
Eric Jeong1545f3b2019-09-16 13:56:52 -07002216
2217 for (Iterator<UserInfo> iterator = users.iterator(); iterator.hasNext(); ) {
2218 UserInfo user = iterator.next();
2219 if (!filter.isEligibleUser(user)) {
2220 iterator.remove();
2221 }
2222 }
2223 return users;
2224 }
2225
felipeal2d0483c2019-11-02 14:07:22 -07002226 private static void checkManageUsersOrDumpPermission(String message) {
Felipe Leme55236722020-10-16 16:54:32 -07002227 checkHasAtLeastOnePermissionGranted(message,
felipeal2d0483c2019-11-02 14:07:22 -07002228 android.Manifest.permission.MANAGE_USERS,
2229 android.Manifest.permission.DUMP);
2230 }
2231
Felipe Leme5528ff72020-02-10 19:05:14 -08002232 private void checkInteractAcrossUsersPermission(String message) {
Felipe Leme55236722020-10-16 16:54:32 -07002233 checkHasAtLeastOnePermissionGranted(message,
2234 android.Manifest.permission.INTERACT_ACROSS_USERS,
Felipe Leme5528ff72020-02-10 19:05:14 -08002235 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
2236 }
2237
Eric Jeongc91f9452019-08-30 15:04:21 -07002238 private int getNumberOfManagedProfiles(@UserIdInt int userId) {
Colin Cross0df71ea2020-08-27 04:12:26 +00002239 List<UserInfo> users = mUserManager.getAliveUsers();
Eric Jeongc91f9452019-08-30 15:04:21 -07002240 // Count all users that are managed profiles of the given user.
2241 int managedProfilesCount = 0;
2242 for (UserInfo user : users) {
2243 if (user.isManagedProfile() && user.profileGroupId == userId) {
2244 managedProfilesCount++;
2245 }
2246 }
2247 return managedProfilesCount;
2248 }
2249
2250 /**
2251 * Starts the first passenger of the given driver and assigns the passenger to the front
2252 * passenger zone.
2253 *
2254 * @param driverId User id of the driver.
2255 * @return whether it succeeds.
2256 */
2257 private boolean startFirstPassenger(@UserIdInt int driverId) {
2258 int zoneId = getAvailablePassengerZone();
2259 if (zoneId == OccupantZoneInfo.INVALID_ZONE_ID) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002260 Slog.w(TAG, "passenger occupant zone is not found");
Eric Jeongc91f9452019-08-30 15:04:21 -07002261 return false;
2262 }
2263 List<UserInfo> passengers = getPassengers(driverId);
2264 if (passengers.size() < 1) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002265 Slog.w(TAG, "passenger is not found");
Eric Jeongc91f9452019-08-30 15:04:21 -07002266 return false;
2267 }
2268 // Only one passenger is supported. If there are two or more passengers, the first passenger
2269 // is chosen.
2270 int passengerId = passengers.get(0).id;
2271 if (!startPassenger(passengerId, zoneId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002272 Slog.w(TAG, "cannot start passenger " + passengerId);
Eric Jeongc91f9452019-08-30 15:04:21 -07002273 return false;
2274 }
2275 return true;
2276 }
2277
2278 private int getAvailablePassengerZone() {
2279 int[] occupantTypes = new int[] {CarOccupantZoneManager.OCCUPANT_TYPE_FRONT_PASSENGER,
2280 CarOccupantZoneManager.OCCUPANT_TYPE_REAR_PASSENGER};
2281 for (int occupantType : occupantTypes) {
2282 int zoneId = getZoneId(occupantType);
2283 if (zoneId != OccupantZoneInfo.INVALID_ZONE_ID) {
2284 return zoneId;
2285 }
2286 }
2287 return OccupantZoneInfo.INVALID_ZONE_ID;
2288 }
2289
2290 /**
2291 * Creates a new passenger user when there is no passenger user.
2292 */
2293 private void setupPassengerUser() {
2294 int currentUser = ActivityManager.getCurrentUser();
2295 int profileCount = getNumberOfManagedProfiles(currentUser);
2296 if (profileCount > 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002297 Slog.w(TAG, "max profile of user" + currentUser
Eric Jeongc91f9452019-08-30 15:04:21 -07002298 + " is exceeded: current profile count is " + profileCount);
2299 return;
2300 }
2301 // TODO(b/140311342): Use resource string for the default passenger name.
2302 UserInfo passenger = createPassenger("Passenger", currentUser);
2303 if (passenger == null) {
2304 // Couldn't create user, most likely because there are too many.
Eric Jeongf75d4132020-12-21 13:48:23 -08002305 Slog.w(TAG, "cannot create a passenger user");
Eric Jeongc91f9452019-08-30 15:04:21 -07002306 return;
2307 }
2308 }
2309
2310 @NonNull
2311 private List<OccupantZoneInfo> getOccupantZones(@OccupantTypeEnum int occupantType) {
2312 ZoneUserBindingHelper helper = null;
2313 synchronized (mLockHelper) {
2314 if (mZoneUserBindingHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002315 Slog.w(TAG, "implementation is not delegated");
Eric Jeongc91f9452019-08-30 15:04:21 -07002316 return new ArrayList<OccupantZoneInfo>();
2317 }
2318 helper = mZoneUserBindingHelper;
2319 }
2320 return helper.getOccupantZones(occupantType);
2321 }
2322
2323 private boolean assignUserToOccupantZone(@UserIdInt int userId, int zoneId) {
2324 ZoneUserBindingHelper helper = null;
2325 synchronized (mLockHelper) {
2326 if (mZoneUserBindingHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002327 Slog.w(TAG, "implementation is not delegated");
Eric Jeongc91f9452019-08-30 15:04:21 -07002328 return false;
2329 }
2330 helper = mZoneUserBindingHelper;
2331 }
2332 return helper.assignUserToOccupantZone(userId, zoneId);
2333 }
2334
2335 private boolean unassignUserFromOccupantZone(@UserIdInt int userId) {
2336 ZoneUserBindingHelper helper = null;
2337 synchronized (mLockHelper) {
2338 if (mZoneUserBindingHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002339 Slog.w(TAG, "implementation is not delegated");
Eric Jeongc91f9452019-08-30 15:04:21 -07002340 return false;
2341 }
2342 helper = mZoneUserBindingHelper;
2343 }
2344 return helper.unassignUserFromOccupantZone(userId);
2345 }
2346
2347 private boolean isPassengerDisplayAvailable() {
2348 ZoneUserBindingHelper helper = null;
2349 synchronized (mLockHelper) {
2350 if (mZoneUserBindingHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002351 Slog.w(TAG, "implementation is not delegated");
Eric Jeongc91f9452019-08-30 15:04:21 -07002352 return false;
2353 }
2354 helper = mZoneUserBindingHelper;
2355 }
2356 return helper.isPassengerDisplayAvailable();
2357 }
2358
2359 /**
2360 * Gets the zone id of the given occupant type. If there are two or more zones, the first found
2361 * zone is returned.
2362 *
2363 * @param occupantType The type of an occupant.
2364 * @return The zone id of the given occupant type. {@link OccupantZoneInfo.INVALID_ZONE_ID},
2365 * if not found.
2366 */
2367 private int getZoneId(@OccupantTypeEnum int occupantType) {
2368 List<OccupantZoneInfo> zoneInfos = getOccupantZones(occupantType);
2369 return (zoneInfos.size() > 0) ? zoneInfos.get(0).zoneId : OccupantZoneInfo.INVALID_ZONE_ID;
2370 }
Mayank Garg9732d602020-08-09 21:02:40 -07002371
2372 /**
2373 * Manages the required number of pre-created users.
2374 */
Mayank Garga3b72d02021-03-14 23:05:51 -07002375 @Override
2376 public void updatePreCreatedUsers() {
2377 checkManageOrCreateUsersPermission("preCreateUsers");
2378 preCreateUsersInternal();
Mayank Garg02576972021-02-18 16:46:07 -08002379 }
2380
Mayank Garga3b72d02021-03-14 23:05:51 -07002381 private void preCreateUsersInternal() {
2382 mHandler.post(() -> mUserPreCreator.managePreCreatedUsers());
Mayank Garg9732d602020-08-09 21:02:40 -07002383 }
Felipe Leme17799202020-09-03 12:55:53 -07002384
2385 // TODO(b/167698977): members below were copied from UserManagerService; it would be better to
2386 // move them to some internal android.os class instead.
2387
2388 private static final int ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION =
2389 UserInfo.FLAG_MANAGED_PROFILE
2390 | UserInfo.FLAG_PROFILE
2391 | UserInfo.FLAG_EPHEMERAL
2392 | UserInfo.FLAG_RESTRICTED
2393 | UserInfo.FLAG_GUEST
2394 | UserInfo.FLAG_DEMO
2395 | UserInfo.FLAG_FULL;
2396
2397 private static void checkManageUsersPermission(String message) {
2398 if (!hasManageUsersPermission()) {
2399 throw new SecurityException("You need " + MANAGE_USERS + " permission to: " + message);
2400 }
2401 }
2402
2403 private static void checkManageOrCreateUsersPermission(String message) {
2404 if (!hasManageOrCreateUsersPermission()) {
2405 throw new SecurityException(
2406 "You either need " + MANAGE_USERS + " or " + CREATE_USERS + " permission to: "
2407 + message);
2408 }
2409 }
2410
2411 private static void checkManageOrCreateUsersPermission(int creationFlags) {
2412 if ((creationFlags & ~ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION) == 0) {
2413 if (!hasManageOrCreateUsersPermission()) {
2414 throw new SecurityException("You either need " + MANAGE_USERS + " or "
2415 + CREATE_USERS + "permission to create a user with flags "
2416 + creationFlags);
2417 }
2418 } else if (!hasManageUsersPermission()) {
2419 throw new SecurityException("You need " + MANAGE_USERS + " permission to create a user"
2420 + " with flags " + creationFlags);
2421 }
2422 }
2423
2424 private static boolean hasManageUsersPermission() {
2425 final int callingUid = Binder.getCallingUid();
2426 return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
2427 || callingUid == Process.ROOT_UID
2428 || hasPermissionGranted(MANAGE_USERS, callingUid);
2429 }
2430
2431 private static boolean hasManageUsersOrPermission(String alternativePermission) {
2432 final int callingUid = Binder.getCallingUid();
2433 return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
2434 || callingUid == Process.ROOT_UID
2435 || hasPermissionGranted(MANAGE_USERS, callingUid)
2436 || hasPermissionGranted(alternativePermission, callingUid);
2437 }
2438
2439 private static boolean hasManageOrCreateUsersPermission() {
2440 return hasManageUsersOrPermission(CREATE_USERS);
2441 }
2442
2443 private static boolean hasPermissionGranted(String permission, int uid) {
2444 return ActivityManager.checkComponentPermission(permission, uid, /* owningUid= */ -1,
2445 /* exported= */ true) == PackageManager.PERMISSION_GRANTED;
2446 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002447}