blob: b80be8166ee303ec370232930e4a9470f0cac105 [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;
felipeale5bf0322020-04-16 15:10:57 -070047import android.car.user.UserSwitchResult;
felipeal19e3d732020-03-18 12:07:32 -070048import android.car.userlib.HalCallback;
49import android.car.userlib.UserHalHelper;
Mayank Garge90a4082020-09-30 12:57:34 -070050import android.car.userlib.UserHelper;
Mayank Garga480dd92020-05-14 03:14:57 -070051import android.content.ComponentName;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070052import android.content.Context;
Mayank Garga480dd92020-05-14 03:14:57 -070053import android.content.pm.PackageManager;
54import android.content.pm.PackageManager.NameNotFoundException;
Eric Jeong1545f3b2019-09-16 13:56:52 -070055import android.content.pm.UserInfo;
felipealdfdf8512020-06-01 09:35:45 -070056import android.content.pm.UserInfo.UserInfoFlag;
Felipe Leme315a53b2020-03-12 10:51:04 -070057import android.content.res.Resources;
Anthony Hugh6fed1e92019-10-22 16:22:03 -070058import android.graphics.Bitmap;
felipealdfdf8512020-06-01 09:35:45 -070059import android.hardware.automotive.vehicle.V2_0.CreateUserRequest;
60import android.hardware.automotive.vehicle.V2_0.CreateUserStatus;
Mayank Garg70732a82020-08-05 20:17:47 -070061import android.hardware.automotive.vehicle.V2_0.InitialUserInfoRequestType;
Felipe Lemec6e3c2a2020-02-19 16:53:57 -080062import android.hardware.automotive.vehicle.V2_0.InitialUserInfoResponseAction;
Mayank Garga55c3092020-05-28 03:19:24 -070063import android.hardware.automotive.vehicle.V2_0.RemoveUserRequest;
Mayank Gargeb37d092020-06-02 14:37:57 -070064import android.hardware.automotive.vehicle.V2_0.SwitchUserRequest;
Mayank Garg59f22192020-03-27 00:51:45 -070065import android.hardware.automotive.vehicle.V2_0.SwitchUserStatus;
felipeal5e3ede42020-04-23 18:04:07 -070066import android.hardware.automotive.vehicle.V2_0.UserIdentificationGetRequest;
67import android.hardware.automotive.vehicle.V2_0.UserIdentificationResponse;
felipeal159a2a42020-05-08 10:32:11 -070068import android.hardware.automotive.vehicle.V2_0.UserIdentificationSetAssociation;
69import android.hardware.automotive.vehicle.V2_0.UserIdentificationSetRequest;
Felipe Lemec6e3c2a2020-02-19 16:53:57 -080070import android.hardware.automotive.vehicle.V2_0.UsersInfo;
Ying Zheng1ab32b62018-06-26 12:47:26 -070071import android.location.LocationManager;
Eric Jeong1545f3b2019-09-16 13:56:52 -070072import android.os.Binder;
Felipe Leme5528ff72020-02-10 19:05:14 -080073import android.os.Bundle;
Antonio Kantek7236a5b2020-04-06 19:53:55 -070074import android.os.Handler;
75import android.os.HandlerThread;
Felipe Leme17799202020-09-03 12:55:53 -070076import android.os.Process;
Keun young Parkfb656372019-03-12 18:37:55 -070077import android.os.RemoteException;
Mayank Garg31e73042020-01-23 00:10:38 -080078import android.os.Trace;
Ying Zhengcf20f442018-06-22 16:54:51 -070079import android.os.UserHandle;
Ying Zheng8f90edb2018-06-13 12:42:31 -070080import android.os.UserManager;
jovanak24470652018-09-11 17:51:57 -070081import android.provider.Settings;
Felipe Lemee3cab982020-03-12 11:39:29 -070082import android.sysprop.CarProperties;
felipeal159a2a42020-05-08 10:32:11 -070083import android.text.TextUtils;
felipeal312416a2020-04-14 12:28:24 -070084import android.util.EventLog;
Felipe Leme176a5fd2021-01-20 15:48:33 -080085import android.util.IndentingPrintWriter;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070086import android.util.Log;
Eric Jeongf75d4132020-12-21 13:48:23 -080087import android.util.Slog;
Felipe Leme5528ff72020-02-10 19:05:14 -080088import android.util.SparseArray;
Felipe Leme6b34fc32020-10-26 15:49:17 -070089import android.util.SparseBooleanArray;
Mayank Garg31e73042020-01-23 00:10:38 -080090import android.util.TimingsTraceLog;
Felipe Leme56ef9ad2020-11-05 18:39:03 -080091import android.view.Display;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070092
Mayank Garg72c71d22021-02-03 23:54:45 -080093import com.android.car.CarLog;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070094import com.android.car.CarServiceBase;
Keun young Parkb241d022020-04-20 20:31:34 -070095import com.android.car.CarServiceUtils;
Felipe Leme5d5ab142020-10-27 13:49:10 -070096import com.android.car.CarUxRestrictionsManagerService;
Eric Jeongc91f9452019-08-30 15:04:21 -070097import com.android.car.R;
Felipe Leme58412202020-01-09 13:45:33 -080098import com.android.car.hal.UserHalService;
Felipe Leme56ef9ad2020-11-05 18:39:03 -080099import com.android.car.internal.ICarServiceHelper;
Mayank Gargf59f95b2020-10-01 14:55:11 -0700100import com.android.car.internal.common.CommonConstants.UserLifecycleEventType;
Mayank Garg801ea6a2020-09-29 15:43:49 -0700101import com.android.car.internal.common.EventLogTags;
102import com.android.car.internal.common.UserHelperLite;
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700103import com.android.car.power.CarPowerManagementService;
Mayank Garg665c20b2020-08-07 16:19:28 -0700104import com.android.car.user.InitialUserSetter.InitialUserInfo;
Keun-young Parkd462a912019-02-11 08:53:42 -0800105import com.android.internal.annotations.GuardedBy;
Keun young Parkf3523cd2019-04-08 10:09:17 -0700106import com.android.internal.annotations.VisibleForTesting;
felipeale5bf0322020-04-16 15:10:57 -0700107import com.android.internal.infra.AndroidFuture;
Felipe Leme5528ff72020-02-10 19:05:14 -0800108import com.android.internal.os.IResultReceiver;
felipeal5e3ede42020-04-23 18:04:07 -0700109import com.android.internal.util.ArrayUtils;
felipeal2a84d512020-04-06 18:52:15 -0700110import com.android.internal.util.FunctionalUtils;
Mayank Garge19c2922020-03-30 18:05:53 -0700111import com.android.internal.util.Preconditions;
Anthony Hugh6fed1e92019-10-22 16:22:03 -0700112import com.android.internal.util.UserIcons;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700113
114import java.io.PrintWriter;
Keun-young Parkd462a912019-02-11 08:53:42 -0800115import java.util.ArrayList;
felipeal2d0483c2019-11-02 14:07:22 -0700116import java.util.Arrays;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700117import java.util.Iterator;
118import java.util.List;
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +0000119import java.util.Objects;
Pavel Maltsev17e81832019-04-04 14:38:41 -0700120import java.util.concurrent.CopyOnWriteArrayList;
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700121import java.util.concurrent.CountDownLatch;
122import java.util.concurrent.TimeUnit;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700123
124/**
125 * User service for cars. Manages users at boot time. Including:
126 *
127 * <ol>
Eric Jeong1545f3b2019-09-16 13:56:52 -0700128 * <li> Creates a user used as driver.
129 * <li> Creates a user used as passenger.
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700130 * <li> Creates a secondary admin user on first run.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700131 * <li> Switch drivers.
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700132 * <ol/>
133 */
Eric Jeong1545f3b2019-09-16 13:56:52 -0700134public final class CarUserService extends ICarUserService.Stub implements CarServiceBase {
Felipe Leme5528ff72020-02-10 19:05:14 -0800135
Mayank Garg72c71d22021-02-03 23:54:45 -0800136 private static final String TAG = CarLog.tagFor(CarUserService.class);
felipealf7368962020-04-16 12:55:19 -0700137
Felipe Lemeabbf2da2020-02-24 18:25:29 -0800138 /** {@code int} extra used to represent a user id in a {@link IResultReceiver} response. */
Mayank Garg8f932822020-09-17 16:09:12 -0700139 public static final String BUNDLE_USER_ID = "user.id";
Felipe Lemeabbf2da2020-02-24 18:25:29 -0800140 /** {@code int} extra used to represent user flags in a {@link IResultReceiver} response. */
Mayank Garg8f932822020-09-17 16:09:12 -0700141 public static final String BUNDLE_USER_FLAGS = "user.flags";
Felipe Lemeabbf2da2020-02-24 18:25:29 -0800142 /** {@code String} extra used to represent a user name in a {@link IResultReceiver} response. */
Mayank Garg8f932822020-09-17 16:09:12 -0700143 public static final String BUNDLE_USER_NAME = "user.name";
felipeala68ecef2020-05-19 12:46:08 -0700144 /**
145 * {@code int} extra used to represent the user locales in a {@link IResultReceiver} response.
146 */
Mayank Garg8f932822020-09-17 16:09:12 -0700147 public static final String BUNDLE_USER_LOCALES = "user.locales";
felipeala68ecef2020-05-19 12:46:08 -0700148 /**
149 * {@code int} extra used to represent the info action in a {@link IResultReceiver} response.
150 */
Mayank Garg8f932822020-09-17 16:09:12 -0700151 public static final String BUNDLE_INITIAL_INFO_ACTION = "initial_info.action";
Felipe Leme5528ff72020-02-10 19:05:14 -0800152
Mayank Garg9ed099e2020-06-04 16:05:20 -0700153 public static final String VEHICLE_HAL_NOT_SUPPORTED = "Vehicle Hal not supported.";
154
Mayank Garg02576972021-02-18 16:46:07 -0800155 public static final String HANDLER_THREAD_NAME = "UserService";
156
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700157 private final Context mContext;
Keun young Parkfb656372019-03-12 18:37:55 -0700158 private final IActivityManager mAm;
Anthony Hugh9932a252019-06-12 16:19:56 -0700159 private final UserManager mUserManager;
160 private final int mMaxRunningUsers;
Mayank Garg70732a82020-08-05 20:17:47 -0700161 private final InitialUserSetter mInitialUserSetter;
Eric Jeongc91f9452019-08-30 15:04:21 -0700162 private final boolean mEnablePassengerSupport;
Mayank Garg9732d602020-08-09 21:02:40 -0700163 private final UserPreCreator mUserPreCreator;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700164
Eric Jeongc91f9452019-08-30 15:04:21 -0700165 private final Object mLockUser = new Object();
166 @GuardedBy("mLockUser")
Keun-young Parkd462a912019-02-11 08:53:42 -0800167 private boolean mUser0Unlocked;
Eric Jeongc91f9452019-08-30 15:04:21 -0700168 @GuardedBy("mLockUser")
Keun-young Parkd462a912019-02-11 08:53:42 -0800169 private final ArrayList<Runnable> mUser0UnlockTasks = new ArrayList<>();
Eric Jeongc91f9452019-08-30 15:04:21 -0700170 // Only one passenger is supported.
171 @GuardedBy("mLockUser")
172 private @UserIdInt int mLastPassengerId;
Keun young Parkf3523cd2019-04-08 10:09:17 -0700173 /**
174 * Background users that will be restarted in garage mode. This list can include the
Mayank Garg31e73042020-01-23 00:10:38 -0800175 * current foreground user but the current foreground user should not be restarted.
Keun young Parkf3523cd2019-04-08 10:09:17 -0700176 */
Eric Jeongc91f9452019-08-30 15:04:21 -0700177 @GuardedBy("mLockUser")
Keun young Parkf3523cd2019-04-08 10:09:17 -0700178 private final ArrayList<Integer> mBackgroundUsersToRestart = new ArrayList<>();
179 /**
180 * Keep the list of background users started here. This is wholly for debugging purpose.
181 */
Eric Jeongc91f9452019-08-30 15:04:21 -0700182 @GuardedBy("mLockUser")
Keun young Parkf3523cd2019-04-08 10:09:17 -0700183 private final ArrayList<Integer> mBackgroundUsersRestartedHere = new ArrayList<>();
184
Felipe Leme58412202020-01-09 13:45:33 -0800185 private final UserHalService mHal;
186
Keun young Parkb241d022020-04-20 20:31:34 -0700187 private final HandlerThread mHandlerThread = CarServiceUtils.getHandlerThread(
Mayank Garg02576972021-02-18 16:46:07 -0800188 HANDLER_THREAD_NAME);
189 private final Handler mHandler;
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700190
Felipe Leme5528ff72020-02-10 19:05:14 -0800191 /**
Antonio Kantekc8114752020-03-05 21:37:39 -0800192 * List of listeners to be notified on new user activities events.
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700193 * This collection should be accessed and manipulated by mHandlerThread only.
Antonio Kantekc8114752020-03-05 21:37:39 -0800194 */
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700195 private final List<UserLifecycleListener> mUserLifecycleListeners = new ArrayList<>();
Antonio Kantekc8114752020-03-05 21:37:39 -0800196
197 /**
Felipe Leme5528ff72020-02-10 19:05:14 -0800198 * List of lifecycle listeners by uid.
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700199 * This collection should be accessed and manipulated by mHandlerThread only.
Felipe Leme5528ff72020-02-10 19:05:14 -0800200 */
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700201 private final SparseArray<IResultReceiver> mAppLifecycleListeners = new SparseArray<>();
Felipe Leme5528ff72020-02-10 19:05:14 -0800202
Mayank Garg7a114c82020-04-08 21:25:06 -0700203 /**
204 * User Id for the user switch in process, if any.
205 */
206 @GuardedBy("mLockUser")
felipealf7368962020-04-16 12:55:19 -0700207 private int mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
Mayank Garg7a114c82020-04-08 21:25:06 -0700208 /**
209 * Request Id for the user switch in process, if any.
210 */
211 @GuardedBy("mLockUser")
felipealf7368962020-04-16 12:55:19 -0700212 private int mRequestIdForUserSwitchInProcess;
Felipe Lemee3cab982020-03-12 11:39:29 -0700213 private final int mHalTimeoutMs = CarProperties.user_hal_timeout().orElse(5_000);
214
Eric Jeongc91f9452019-08-30 15:04:21 -0700215 private final CopyOnWriteArrayList<PassengerCallback> mPassengerCallbacks =
216 new CopyOnWriteArrayList<>();
217
Mayank Garg7e1450b2020-08-07 18:15:15 -0700218 // TODO(b/163566866): Use mSwitchGuestUserBeforeSleep for new create guest request
219 private final boolean mSwitchGuestUserBeforeSleep;
220
felipeal61ce3732020-04-03 11:01:00 -0700221 @Nullable
222 @GuardedBy("mLockUser")
223 private UserInfo mInitialUser;
224
Mayank Garg587f1942020-05-06 01:41:34 -0700225 private IResultReceiver mUserSwitchUiReceiver;
226
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800227 private final CarUxRestrictionsManagerService mCarUxRestrictionService;
228
229 /**
230 * Whether some operations - like user switch - are restricted by driving safety constraints.
231 */
232 @GuardedBy("mLockUser")
233 private boolean mUxRestricted;
234
235 /**
236 * Callback to notify {@code CarServiceHelper} about driving safety changes (through
237 * {@link ICarServiceHelper#setSafetyMode(boolean).
238 *
239 * <p>NOTE: in theory, that logic should belong to {@code CarDevicePolicyService}, but it's
240 * simpler to do it here (and that service already depends on this one).
241 */
242 @GuardedBy("mLockUser")
243 private ICarServiceHelper mICarServiceHelper;
244
245 private final ICarUxRestrictionsChangeListener mCarUxRestrictionsChangeListener =
246 new ICarUxRestrictionsChangeListener.Stub() {
247 @Override
248 public void onUxRestrictionsChanged(CarUxRestrictions restrictions) {
249 setUxRestrictions(restrictions);
250 }
251 };
Felipe Leme5d5ab142020-10-27 13:49:10 -0700252
Eric Jeongc91f9452019-08-30 15:04:21 -0700253 /** Interface for callbaks related to passenger activities. */
254 public interface PassengerCallback {
255 /** Called when passenger is started at a certain zone. */
256 void onPassengerStarted(@UserIdInt int passengerId, int zoneId);
257 /** Called when passenger is stopped. */
258 void onPassengerStopped(@UserIdInt int passengerId);
259 }
260
261 /** Interface for delegating zone-related implementation to CarOccupantZoneService. */
262 public interface ZoneUserBindingHelper {
263 /** Gets occupant zones corresponding to the occupant type. */
264 @NonNull
265 List<OccupantZoneInfo> getOccupantZones(@OccupantTypeEnum int occupantType);
266 /** Assigns the user to the occupant zone. */
267 boolean assignUserToOccupantZone(@UserIdInt int userId, int zoneId);
268 /** Makes the occupant zone unoccupied. */
269 boolean unassignUserFromOccupantZone(@UserIdInt int userId);
270 /** Returns whether there is a passenger display. */
271 boolean isPassengerDisplayAvailable();
272 }
273
274 private final Object mLockHelper = new Object();
275 @GuardedBy("mLockHelper")
276 private ZoneUserBindingHelper mZoneUserBindingHelper;
277
Felipe Leme6b34fc32020-10-26 15:49:17 -0700278 /** Map used to avoid calling UserHAL when a user was removed because HAL creation failed. */
279 @GuardedBy("mLockUser")
280 private final SparseBooleanArray mFailedToCreateUserIds = new SparseBooleanArray(1);
281
Felipe Leme58412202020-01-09 13:45:33 -0800282 public CarUserService(@NonNull Context context, @NonNull UserHalService hal,
Mayank Garge90a4082020-09-30 12:57:34 -0700283 @NonNull UserManager userManager,
Felipe Leme5d5ab142020-10-27 13:49:10 -0700284 @NonNull IActivityManager am, int maxRunningUsers,
285 @NonNull CarUxRestrictionsManagerService uxRestrictionService) {
Mayank Garge90a4082020-09-30 12:57:34 -0700286 this(context, hal, userManager, am, maxRunningUsers,
Mayank Garg02576972021-02-18 16:46:07 -0800287 /* initialUserSetter= */ null, /* userPreCreator= */ null, uxRestrictionService,
288 null);
Mayank Garg71661ea2020-04-29 01:25:03 -0700289 }
290
291 @VisibleForTesting
292 CarUserService(@NonNull Context context, @NonNull UserHalService hal,
Mayank Garge90a4082020-09-30 12:57:34 -0700293 @NonNull UserManager userManager,
Mayank Gargccad8062020-08-30 15:05:10 -0700294 @NonNull IActivityManager am, int maxRunningUsers,
Mayank Garg1bb1c382020-09-03 17:11:11 -0700295 @Nullable InitialUserSetter initialUserSetter,
Felipe Leme5d5ab142020-10-27 13:49:10 -0700296 @Nullable UserPreCreator userPreCreator,
Mayank Garg02576972021-02-18 16:46:07 -0800297 @NonNull CarUxRestrictionsManagerService uxRestrictionService,
298 @Nullable Handler handler) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800299 if (Log.isLoggable(TAG, Log.DEBUG)) {
Felipe Leme8725a2f2020-12-09 16:04:51 -0800300 Slog.d(TAG, "constructed for user " + context.getUserId());
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700301 }
302 mContext = context;
Felipe Leme58412202020-01-09 13:45:33 -0800303 mHal = hal;
Keun young Parkf3523cd2019-04-08 10:09:17 -0700304 mAm = am;
305 mMaxRunningUsers = maxRunningUsers;
Anthony Hugh9932a252019-06-12 16:19:56 -0700306 mUserManager = userManager;
Eric Jeongc91f9452019-08-30 15:04:21 -0700307 mLastPassengerId = UserHandle.USER_NULL;
Mayank Garg02576972021-02-18 16:46:07 -0800308 mHandler = handler == null ? new Handler(mHandlerThread.getLooper()) : handler;
Mayank Garg1bb1c382020-09-03 17:11:11 -0700309 mInitialUserSetter =
Felipe Lemecceb2992020-11-18 18:22:44 -0800310 initialUserSetter == null ? new InitialUserSetter(context, this,
311 (u) -> setInitialUser(u)) : initialUserSetter;
Mayank Garg1bb1c382020-09-03 17:11:11 -0700312 mUserPreCreator =
313 userPreCreator == null ? new UserPreCreator(mUserManager) : userPreCreator;
Mayank Garg7e1450b2020-08-07 18:15:15 -0700314 Resources resources = context.getResources();
315 mEnablePassengerSupport = resources.getBoolean(R.bool.enablePassengerSupport);
316 mSwitchGuestUserBeforeSleep = resources.getBoolean(
317 R.bool.config_switchGuestUserBeforeGoingSleep);
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800318 mCarUxRestrictionService = uxRestrictionService;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700319 }
320
321 @Override
322 public void init() {
Eric Jeongf75d4132020-12-21 13:48:23 -0800323 if (Log.isLoggable(TAG, Log.DEBUG)) {
324 Slog.d(TAG, "init()");
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700325 }
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800326 mCarUxRestrictionService.registerUxRestrictionsChangeListener(
327 mCarUxRestrictionsChangeListener, Display.DEFAULT_DISPLAY);
328
329 setUxRestrictions(mCarUxRestrictionService.getCurrentUxRestrictions());
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700330 }
331
332 @Override
333 public void release() {
Eric Jeongf75d4132020-12-21 13:48:23 -0800334 if (Log.isLoggable(TAG, Log.DEBUG)) {
335 Slog.d(TAG, "release()");
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700336 }
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800337 mCarUxRestrictionService
338 .unregisterUxRestrictionsChangeListener(mCarUxRestrictionsChangeListener);
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700339 }
340
341 @Override
Felipe Leme176a5fd2021-01-20 15:48:33 -0800342 public void dump(@NonNull IndentingPrintWriter writer) {
Felipe Leme55236722020-10-16 16:54:32 -0700343 checkHasDumpPermissionGranted("dump()");
344
Eric Jeong1545f3b2019-09-16 13:56:52 -0700345 writer.println("*CarUserService*");
Felipe Leme5528ff72020-02-10 19:05:14 -0800346 String indent = " ";
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700347 handleDumpListeners(writer, indent);
Mayank Garg587f1942020-05-06 01:41:34 -0700348 writer.printf("User switch UI receiver %s\n", mUserSwitchUiReceiver);
Eric Jeongc91f9452019-08-30 15:04:21 -0700349 synchronized (mLockUser) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700350 writer.println("User0Unlocked: " + mUser0Unlocked);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700351 writer.println("BackgroundUsersToRestart: " + mBackgroundUsersToRestart);
352 writer.println("BackgroundUsersRestarted: " + mBackgroundUsersRestartedHere);
Felipe Leme6b34fc32020-10-26 15:49:17 -0700353 if (mFailedToCreateUserIds.size() > 0) {
354 writer.println("FailedToCreateUserIds: " + mFailedToCreateUserIds);
355 }
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800356 writer.printf("Is UX restricted: %b\n", mUxRestricted);
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700357 }
Mayank Garg02576972021-02-18 16:46:07 -0800358
359 writer.println("SwitchGuestUserBeforeSleep: " + mSwitchGuestUserBeforeSleep);
Mayank Garg02576972021-02-18 16:46:07 -0800360
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700361 writer.println("MaxRunningUsers: " + mMaxRunningUsers);
362 List<UserInfo> allDrivers = getAllDrivers();
363 int driversSize = allDrivers.size();
364 writer.println("NumberOfDrivers: " + driversSize);
365 for (int i = 0; i < driversSize; i++) {
366 int driverId = allDrivers.get(i).id;
367 writer.print(indent + "#" + i + ": id=" + driverId);
368 List<UserInfo> passengers = getPassengers(driverId);
369 int passengersSize = passengers.size();
370 writer.print(" NumberPassengers: " + passengersSize);
371 if (passengersSize > 0) {
372 writer.print(" [");
373 for (int j = 0; j < passengersSize; j++) {
374 writer.print(passengers.get(j).id);
375 if (j < passengersSize - 1) {
376 writer.print(" ");
felipeal2d0483c2019-11-02 14:07:22 -0700377 }
felipeal2d0483c2019-11-02 14:07:22 -0700378 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700379 writer.print("]");
felipeal2d0483c2019-11-02 14:07:22 -0700380 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700381 writer.println();
382 }
383 writer.printf("EnablePassengerSupport: %s\n", mEnablePassengerSupport);
384 writer.printf("User HAL timeout: %dms\n", mHalTimeoutMs);
385 writer.printf("Initial user: %s\n", mInitialUser);
felipealbf327652020-06-03 11:33:29 -0700386
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700387 writer.println("Relevant overlayable properties");
388 Resources res = mContext.getResources();
389 writer.printf("%sowner_name=%s\n", indent,
390 res.getString(com.android.internal.R.string.owner_name));
391 writer.printf("%sdefault_guest_name=%s\n", indent,
392 res.getString(R.string.default_guest_name));
felipealf7368962020-04-16 12:55:19 -0700393 writer.printf("User switch in process=%d\n", mUserIdForUserSwitchInProcess);
Mayank Garg7a114c82020-04-08 21:25:06 -0700394 writer.printf("Request Id for the user switch in process=%d\n ",
395 mRequestIdForUserSwitchInProcess);
Mayank Garga480dd92020-05-14 03:14:57 -0700396 writer.printf("System UI package name=%s\n", getSystemUiPackageName());
felipeale8c5dce2020-04-15 11:27:06 -0700397
felipealbf327652020-06-03 11:33:29 -0700398 writer.println("Relevant Global settings");
399 dumpGlobalProperty(writer, indent, CarSettings.Global.LAST_ACTIVE_USER_ID);
400 dumpGlobalProperty(writer, indent, CarSettings.Global.LAST_ACTIVE_PERSISTENT_USER_ID);
401
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700402 mInitialUserSetter.dump(writer);
felipeale8c5dce2020-04-15 11:27:06 -0700403 }
404
felipealbf327652020-06-03 11:33:29 -0700405 private void dumpGlobalProperty(PrintWriter writer, String indent, String property) {
406 String value = Settings.Global.getString(mContext.getContentResolver(), property);
407 writer.printf("%s%s=%s\n", indent, property, value);
408 }
409
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700410 private void handleDumpListeners(@NonNull PrintWriter writer, String indent) {
411 CountDownLatch latch = new CountDownLatch(1);
412 mHandler.post(() -> {
felipealde1e16d2020-06-03 13:20:48 -0700413 handleDumpServiceLifecycleListeners(writer);
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700414 handleDumpAppLifecycleListeners(writer, indent);
415 latch.countDown();
416 });
417 int timeout = 5;
418 try {
419 if (!latch.await(timeout, TimeUnit.SECONDS)) {
420 writer.printf("Handler thread didn't respond in %ds when dumping listeners\n",
421 timeout);
422 }
423 } catch (InterruptedException e) {
424 Thread.currentThread().interrupt();
425 writer.println("Interrupted waiting for handler thread to dump app and user listeners");
426 }
427 }
428
felipealde1e16d2020-06-03 13:20:48 -0700429 private void handleDumpServiceLifecycleListeners(@NonNull PrintWriter writer) {
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700430 if (mUserLifecycleListeners.isEmpty()) {
felipealde1e16d2020-06-03 13:20:48 -0700431 writer.println("No lifecycle listeners for internal services");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700432 return;
433 }
felipealde1e16d2020-06-03 13:20:48 -0700434 int size = mUserLifecycleListeners.size();
435 writer.printf("%d lifecycle listener%s for services\n", size, size == 1 ? "" : "s");
436 String indent = " ";
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700437 for (UserLifecycleListener listener : mUserLifecycleListeners) {
felipealde1e16d2020-06-03 13:20:48 -0700438 writer.printf("%s%s\n", indent, FunctionalUtils.getLambdaName(listener));
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700439 }
440 }
441
442 private void handleDumpAppLifecycleListeners(@NonNull PrintWriter writer, String indent) {
felipealde1e16d2020-06-03 13:20:48 -0700443 int size = mAppLifecycleListeners.size();
444 if (size == 0) {
445 writer.println("No lifecycle listeners for apps");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700446 return;
447 }
felipealde1e16d2020-06-03 13:20:48 -0700448 writer.printf("%d lifecycle listener%s for apps \n", size, size == 1 ? "" : "s");
449 for (int i = 0; i < size; i++) {
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700450 int uid = mAppLifecycleListeners.keyAt(i);
451 IResultReceiver listener = mAppLifecycleListeners.valueAt(i);
Felipe Lemeea4b5322020-10-26 15:33:36 -0700452 writer.printf("%suid: %d listener: %s\n", indent, uid,
453 FunctionalUtils.getLambdaName(listener));
Keun-young Parkd462a912019-02-11 08:53:42 -0800454 }
Eric Jeong1545f3b2019-09-16 13:56:52 -0700455 }
456
457 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700458 * @see ExperimentalCarUserManager.createDriver
Eric Jeong1545f3b2019-09-16 13:56:52 -0700459 */
460 @Override
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700461 public AndroidFuture<UserCreationResult> createDriver(@NonNull String name, boolean admin) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700462 checkManageUsersPermission("createDriver");
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +0000463 Objects.requireNonNull(name, "name cannot be null");
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700464
465 AndroidFuture<UserCreationResult> future = new AndroidFuture<UserCreationResult>() {
466 @Override
467 protected void onCompleted(UserCreationResult result, Throwable err) {
468 if (result == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800469 Slog.w(TAG, "createDriver(" + name + "," + admin + ") failed: " + err);
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700470 } else {
471 if (result.getStatus() == UserCreationResult.STATUS_SUCCESSFUL) {
472 assignDefaultIcon(result.getUser());
473 }
474 }
475 super.onCompleted(result, err);
476 };
477 };
478 int flags = 0;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700479 if (admin) {
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700480 if (!(mUserManager.isAdminUser() || mUserManager.isSystemUser())) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800481 Slog.e(TAG, "Only admin users and system user can create other admins.");
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700482 sendUserCreationResultFailure(future, UserCreationResult.STATUS_INVALID_REQUEST);
483 return future;
484 }
485 flags = UserInfo.FLAG_ADMIN;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700486 }
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700487 createUser(name, UserInfo.getDefaultUserType(flags), flags, mHalTimeoutMs, future);
488 return future;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700489 }
490
491 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700492 * @see ExperimentalCarUserManager.createPassenger
Eric Jeong1545f3b2019-09-16 13:56:52 -0700493 */
494 @Override
495 @Nullable
496 public UserInfo createPassenger(@NonNull String name, @UserIdInt int driverId) {
497 checkManageUsersPermission("createPassenger");
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +0000498 Objects.requireNonNull(name, "name cannot be null");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700499 UserInfo driver = mUserManager.getUserInfo(driverId);
500 if (driver == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800501 Slog.w(TAG, "the driver is invalid");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700502 return null;
503 }
504 if (driver.isGuest()) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800505 Slog.w(TAG, "a guest driver cannot create a passenger");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700506 return null;
507 }
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700508 // createPassenger doesn't use user HAL because user HAL doesn't support profile user yet.
Bookatz42fb1a62019-10-30 11:45:01 -0700509 UserInfo user = mUserManager.createProfileForUser(name,
510 UserManager.USER_TYPE_PROFILE_MANAGED, /* flags */ 0, driverId);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700511 if (user == null) {
512 // Couldn't create user, most likely because there are too many.
Eric Jeongf75d4132020-12-21 13:48:23 -0800513 Slog.w(TAG, "can't create a profile for user" + driverId);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700514 return null;
515 }
516 // Passenger user should be a non-admin user.
Mayank Garge90a4082020-09-30 12:57:34 -0700517 UserHelper.setDefaultNonAdminRestrictions(mContext, user, /* enable= */ true);
Anthony Hugh6fed1e92019-10-22 16:22:03 -0700518 assignDefaultIcon(user);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700519 return user;
520 }
521
522 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700523 * @see ExperimentalCarUserManager.switchDriver
Eric Jeong1545f3b2019-09-16 13:56:52 -0700524 */
525 @Override
Eric Jeong25666cf2020-05-14 15:16:27 -0700526 public void switchDriver(@UserIdInt int driverId, AndroidFuture<UserSwitchResult> receiver) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700527 checkManageUsersPermission("switchDriver");
Mayank Garg94f3eb92020-08-12 12:38:58 -0700528 if (UserHelperLite.isHeadlessSystemUser(driverId)) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700529 // System user doesn't associate with real person, can not be switched to.
Eric Jeongf75d4132020-12-21 13:48:23 -0800530 Slog.w(TAG, "switching to system user in headless system user mode is not allowed");
felipealdfdf8512020-06-01 09:35:45 -0700531 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_INVALID_REQUEST);
Eric Jeong25666cf2020-05-14 15:16:27 -0700532 return;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700533 }
534 int userSwitchable = mUserManager.getUserSwitchability();
535 if (userSwitchable != UserManager.SWITCHABILITY_STATUS_OK) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800536 Slog.w(TAG, "current process is not allowed to switch user");
felipealdfdf8512020-06-01 09:35:45 -0700537 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_INVALID_REQUEST);
Eric Jeong25666cf2020-05-14 15:16:27 -0700538 return;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700539 }
Eric Jeong25666cf2020-05-14 15:16:27 -0700540 switchUser(driverId, mHalTimeoutMs, receiver);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700541 }
542
543 /**
Eric Jeonge7916fc2019-12-20 14:03:34 -0800544 * Returns all drivers who can occupy the driving zone. Guest users are included in the list.
545 *
546 * @return the list of {@link UserInfo} who can be a driver on the device.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700547 */
548 @Override
549 @NonNull
550 public List<UserInfo> getAllDrivers() {
felipeal2d0483c2019-11-02 14:07:22 -0700551 checkManageUsersOrDumpPermission("getAllDrivers");
Mayank Garg94f3eb92020-08-12 12:38:58 -0700552 return getUsers((user) -> !UserHelperLite.isHeadlessSystemUser(user.id) && user.isEnabled()
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700553 && !user.isManagedProfile() && !user.isEphemeral());
Eric Jeong1545f3b2019-09-16 13:56:52 -0700554 }
555
556 /**
Eric Jeonge7916fc2019-12-20 14:03:34 -0800557 * Returns all passengers under the given driver.
558 *
559 * @param driverId User id of a driver.
560 * @return the list of {@link UserInfo} who is a passenger under the given driver.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700561 */
562 @Override
563 @NonNull
564 public List<UserInfo> getPassengers(@UserIdInt int driverId) {
felipeal2d0483c2019-11-02 14:07:22 -0700565 checkManageUsersOrDumpPermission("getPassengers");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700566 return getUsers((user) -> {
Mayank Garg94f3eb92020-08-12 12:38:58 -0700567 return !UserHelperLite.isHeadlessSystemUser(user.id) && user.isEnabled()
Eric Jeong40f8fa32020-05-12 12:23:33 -0700568 && user.isManagedProfile() && user.profileGroupId == driverId;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700569 });
570 }
571
572 /**
573 * @see CarUserManager.startPassenger
574 */
575 @Override
576 public boolean startPassenger(@UserIdInt int passengerId, int zoneId) {
577 checkManageUsersPermission("startPassenger");
Eric Jeongc91f9452019-08-30 15:04:21 -0700578 synchronized (mLockUser) {
579 try {
580 if (!mAm.startUserInBackgroundWithListener(passengerId, null)) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800581 Slog.w(TAG, "could not start passenger");
Eric Jeongc91f9452019-08-30 15:04:21 -0700582 return false;
583 }
584 } catch (RemoteException e) {
585 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -0800586 Slog.w(TAG, "error while starting passenger", e);
Eric Jeongc91f9452019-08-30 15:04:21 -0700587 return false;
588 }
589 if (!assignUserToOccupantZone(passengerId, zoneId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800590 Slog.w(TAG, "could not assign passenger to zone");
Eric Jeongc91f9452019-08-30 15:04:21 -0700591 return false;
592 }
593 mLastPassengerId = passengerId;
594 }
595 for (PassengerCallback callback : mPassengerCallbacks) {
596 callback.onPassengerStarted(passengerId, zoneId);
597 }
598 return true;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700599 }
600
601 /**
602 * @see CarUserManager.stopPassenger
603 */
604 @Override
605 public boolean stopPassenger(@UserIdInt int passengerId) {
606 checkManageUsersPermission("stopPassenger");
Eric Jeongc91f9452019-08-30 15:04:21 -0700607 return stopPassengerInternal(passengerId, true);
608 }
609
610 private boolean stopPassengerInternal(@UserIdInt int passengerId, boolean checkCurrentDriver) {
611 synchronized (mLockUser) {
612 UserInfo passenger = mUserManager.getUserInfo(passengerId);
613 if (passenger == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800614 Slog.w(TAG, "passenger " + passengerId + " doesn't exist");
Eric Jeongc91f9452019-08-30 15:04:21 -0700615 return false;
616 }
617 if (mLastPassengerId != passengerId) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800618 Slog.w(TAG, "passenger " + passengerId + " hasn't been started");
Eric Jeongc91f9452019-08-30 15:04:21 -0700619 return true;
620 }
621 if (checkCurrentDriver) {
622 int currentUser = ActivityManager.getCurrentUser();
623 if (passenger.profileGroupId != currentUser) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800624 Slog.w(TAG, "passenger " + passengerId
Eric Jeongc91f9452019-08-30 15:04:21 -0700625 + " is not a profile of the current user");
626 return false;
627 }
628 }
629 // Passenger is a profile, so cannot be stopped through activity manager.
630 // Instead, activities started by the passenger are stopped and the passenger is
631 // unassigned from the zone.
632 stopAllTasks(passengerId);
633 if (!unassignUserFromOccupantZone(passengerId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800634 Slog.w(TAG, "could not unassign user from occupant zone");
Eric Jeongc91f9452019-08-30 15:04:21 -0700635 return false;
636 }
637 mLastPassengerId = UserHandle.USER_NULL;
638 }
639 for (PassengerCallback callback : mPassengerCallbacks) {
640 callback.onPassengerStopped(passengerId);
641 }
642 return true;
643 }
644
645 private void stopAllTasks(@UserIdInt int userId) {
646 try {
Louis Chang3bf2f202020-08-18 13:04:28 +0800647 for (RootTaskInfo info : mAm.getAllRootTaskInfos()) {
648 for (int i = 0; i < info.childTaskIds.length; i++) {
649 if (info.childTaskUserIds[i] == userId) {
650 int taskId = info.childTaskIds[i];
Eric Jeongc91f9452019-08-30 15:04:21 -0700651 if (!mAm.removeTask(taskId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800652 Slog.w(TAG, "could not remove task " + taskId);
Eric Jeongc91f9452019-08-30 15:04:21 -0700653 }
654 }
655 }
656 }
657 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800658 Slog.e(TAG, "could not get stack info", e);
Eric Jeongc91f9452019-08-30 15:04:21 -0700659 }
Eric Jeong1545f3b2019-09-16 13:56:52 -0700660 }
661
Felipe Leme5528ff72020-02-10 19:05:14 -0800662 @Override
663 public void setLifecycleListenerForUid(IResultReceiver listener) {
664 int uid = Binder.getCallingUid();
felipeal312416a2020-04-14 12:28:24 -0700665 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SET_LIFECYCLE_LISTENER, uid);
Felipe Leme5528ff72020-02-10 19:05:14 -0800666 checkInteractAcrossUsersPermission("setLifecycleListenerForUid" + uid);
667
668 try {
669 listener.asBinder().linkToDeath(() -> onListenerDeath(uid), 0);
670 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800671 Slog.wtf(TAG, "Cannot listen to death of " + uid);
Felipe Leme5528ff72020-02-10 19:05:14 -0800672 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700673 mHandler.post(() -> mAppLifecycleListeners.append(uid, listener));
Felipe Leme5528ff72020-02-10 19:05:14 -0800674 }
675
676 private void onListenerDeath(int uid) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800677 Slog.i(TAG, "Removing listeners for uid " + uid + " on binder death");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700678 mHandler.post(() -> mAppLifecycleListeners.remove(uid));
Felipe Leme5528ff72020-02-10 19:05:14 -0800679 }
680
681 @Override
682 public void resetLifecycleListenerForUid() {
683 int uid = Binder.getCallingUid();
felipeal312416a2020-04-14 12:28:24 -0700684 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_RESET_LIFECYCLE_LISTENER, uid);
Felipe Leme5528ff72020-02-10 19:05:14 -0800685 checkInteractAcrossUsersPermission("resetLifecycleListenerForUid-" + uid);
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700686 mHandler.post(() -> mAppLifecycleListeners.remove(uid));
Felipe Leme5528ff72020-02-10 19:05:14 -0800687 }
688
Felipe Lemee3cab982020-03-12 11:39:29 -0700689 /**
felipeal61ce3732020-04-03 11:01:00 -0700690 * Gets the initial foreground user after the device boots or resumes from suspension.
691 *
692 * <p>When the OEM supports the User HAL, the initial user won't be available until the HAL
693 * returns the initial value to {@code CarService} - if HAL takes too long or times out, this
694 * method returns {@code null}.
695 *
696 * <p>If the HAL eventually times out, {@code CarService} will fallback to its default behavior
697 * (like switching to the last active user), and this method will return the result of such
698 * operation.
699 *
700 * <p>Notice that if {@code CarService} crashes, subsequent calls to this method will return
701 * {@code null}.
702 *
703 * @hide
704 */
705 @Nullable
706 public UserInfo getInitialUser() {
707 checkInteractAcrossUsersPermission("getInitialUser");
708 synchronized (mLockUser) {
709 return mInitialUser;
710 }
711 }
712
felipeal61ce3732020-04-03 11:01:00 -0700713 /**
714 * Sets the initial foreground user after the device boots or resumes from suspension.
715 */
716 public void setInitialUser(@Nullable UserInfo user) {
felipeal312416a2020-04-14 12:28:24 -0700717 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SET_INITIAL_USER,
718 user == null ? UserHandle.USER_NULL : user.id);
felipeal61ce3732020-04-03 11:01:00 -0700719 synchronized (mLockUser) {
720 mInitialUser = user;
721 }
722 if (user == null) {
723 // This mean InitialUserSetter failed and could not fallback, so the initial user was
724 // not switched (and most likely is SYSTEM_USER).
725 // TODO(b/153104378): should we set it to ActivityManager.getCurrentUser() instead?
Eric Jeongf75d4132020-12-21 13:48:23 -0800726 Slog.wtf(TAG, "Initial user set to null");
felipeal61ce3732020-04-03 11:01:00 -0700727 }
728 }
729
Mayank Garg7e1450b2020-08-07 18:15:15 -0700730 private void initResumeReplaceGuest() {
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700731 int currentUserId = ActivityManager.getCurrentUser();
732 UserInfo currentUser = mUserManager.getUserInfo(currentUserId);
733
734 if (!mInitialUserSetter.canReplaceGuestUser(currentUser)) return; // Not a guest
735
736 InitialUserInfo info =
737 new InitialUserSetter.Builder(InitialUserSetter.TYPE_REPLACE_GUEST).build();
738
739 mInitialUserSetter.set(info);
740 }
741
742 /**
Mayank Garg0baf88a2020-08-30 21:57:36 -0700743 * Calls to switch user at the power suspend.
Mayank Garg7e1450b2020-08-07 18:15:15 -0700744 *
745 * <p><b>Note:</b> Should be used only by {@link CarPowerManagementService}
746 *
Mayank Garg7e1450b2020-08-07 18:15:15 -0700747 */
Mayank Garg0baf88a2020-08-30 21:57:36 -0700748 public void onSuspend() {
Eric Jeongf75d4132020-12-21 13:48:23 -0800749 if (Log.isLoggable(TAG, Log.DEBUG)) {
750 Slog.d(TAG, "onSuspend called.");
Mayank Garg7e1450b2020-08-07 18:15:15 -0700751 }
752
Mayank Garg0baf88a2020-08-30 21:57:36 -0700753 if (mSwitchGuestUserBeforeSleep) {
754 initResumeReplaceGuest();
Mayank Garg7e1450b2020-08-07 18:15:15 -0700755 }
Mayank Garg1bb1c382020-09-03 17:11:11 -0700756
Mayank Garga3b72d02021-03-14 23:05:51 -0700757 preCreateUsersInternal();
Mayank Garg7e1450b2020-08-07 18:15:15 -0700758 }
759
760 /**
Mayank Garg0baf88a2020-08-30 21:57:36 -0700761 * Calls to switch user at the power resume.
762 *
763 * <p>
764 * <b>Note:</b> Should be used only by {@link CarPowerManagementService}
765 *
766 */
767 public void onResume() {
Eric Jeongf75d4132020-12-21 13:48:23 -0800768 if (Log.isLoggable(TAG, Log.DEBUG)) {
769 Slog.d(TAG, "onResume called.");
Mayank Garg0baf88a2020-08-30 21:57:36 -0700770 }
771
Mayank Garg02576972021-02-18 16:46:07 -0800772 mHandler.post(() -> initBootUser(InitialUserInfoRequestType.RESUME));
Mayank Garg0baf88a2020-08-30 21:57:36 -0700773 }
774
775 /**
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700776 * Calls to start user at the android startup.
Mayank Garg70732a82020-08-05 20:17:47 -0700777 */
778 public void initBootUser() {
Mayank Garg02576972021-02-18 16:46:07 -0800779 mHandler.post(() -> initBootUser(getInitialUserInfoRequestType()));
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700780 }
781
Mayank Garg7e1450b2020-08-07 18:15:15 -0700782 private void initBootUser(int requestType) {
783 boolean replaceGuest =
784 requestType == InitialUserInfoRequestType.RESUME && !mSwitchGuestUserBeforeSleep;
Mayank Garg70732a82020-08-05 20:17:47 -0700785 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_REQ, requestType,
786 mHalTimeoutMs);
787 checkManageUsersPermission("startInitialUser");
788
789 if (!isUserHalSupported()) {
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700790 fallbackToDefaultInitialUserBehavior(/* userLocales= */ null, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700791 return;
792 }
793
794 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
795 mHal.getInitialUserInfo(requestType, mHalTimeoutMs, usersInfo, (status, resp) -> {
796 if (resp != null) {
797 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_RESP,
798 status, resp.action, resp.userToSwitchOrCreate.userId,
799 resp.userToSwitchOrCreate.flags, resp.userNameToCreate, resp.userLocales);
800
801 String userLocales = resp.userLocales;
802 InitialUserInfo info;
803 switch (resp.action) {
804 case InitialUserInfoResponseAction.SWITCH:
805 int userId = resp.userToSwitchOrCreate.userId;
806 if (userId <= 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800807 Slog.w(TAG, "invalid (or missing) user id sent by HAL: " + userId);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700808 fallbackToDefaultInitialUserBehavior(userLocales, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700809 break;
810 }
811 info = new InitialUserSetter.Builder(InitialUserSetter.TYPE_SWITCH)
812 .setUserLocales(userLocales)
813 .setSwitchUserId(userId)
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700814 .setReplaceGuest(replaceGuest)
Mayank Garg70732a82020-08-05 20:17:47 -0700815 .build();
816 mInitialUserSetter.set(info);
817 break;
818
819 case InitialUserInfoResponseAction.CREATE:
820 int halFlags = resp.userToSwitchOrCreate.flags;
821 String userName = resp.userNameToCreate;
822 info = new InitialUserSetter.Builder(InitialUserSetter.TYPE_CREATE)
823 .setUserLocales(userLocales)
824 .setNewUserName(userName)
825 .setNewUserFlags(halFlags)
826 .build();
827 mInitialUserSetter.set(info);
828 break;
829
830 case InitialUserInfoResponseAction.DEFAULT:
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700831 fallbackToDefaultInitialUserBehavior(userLocales, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700832 break;
833 default:
Eric Jeongf75d4132020-12-21 13:48:23 -0800834 Slog.w(TAG, "invalid response action on " + resp);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700835 fallbackToDefaultInitialUserBehavior(/* user locale */ null, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700836 break;
837
838 }
839 } else {
840 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_RESP, status);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700841 fallbackToDefaultInitialUserBehavior(/* user locale */ null, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700842 }
843 });
844 }
845
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700846 private void fallbackToDefaultInitialUserBehavior(String userLocales, boolean replaceGuest) {
Mayank Garg70732a82020-08-05 20:17:47 -0700847 InitialUserInfo info = new InitialUserSetter.Builder(
848 InitialUserSetter.TYPE_DEFAULT_BEHAVIOR)
849 .setUserLocales(userLocales)
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700850 .setReplaceGuest(replaceGuest)
Mayank Garg70732a82020-08-05 20:17:47 -0700851 .build();
852 mInitialUserSetter.set(info);
853 }
854
855 @VisibleForTesting
856 int getInitialUserInfoRequestType() {
Mayank Garge90a4082020-09-30 12:57:34 -0700857 if (!mInitialUserSetter.hasInitialUser()) {
Mayank Garg70732a82020-08-05 20:17:47 -0700858 return InitialUserInfoRequestType.FIRST_BOOT;
859 }
860 if (mContext.getPackageManager().isDeviceUpgrading()) {
861 return InitialUserInfoRequestType.FIRST_BOOT_AFTER_OTA;
862 }
863 return InitialUserInfoRequestType.COLD_BOOT;
864 }
865
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800866 /**
867 * Sets the {@link ICarServiceHelper} so it can receive UX restriction updates.
868 */
869 public void setCarServiceHelper(ICarServiceHelper helper) {
870 boolean restricted;
871 synchronized (mLockUser) {
872 mICarServiceHelper = helper;
873 restricted = mUxRestricted;
874 }
875 updateSafetyMode(helper, restricted);
876 }
877
878 private void updateSafetyMode(@Nullable ICarServiceHelper helper, boolean restricted) {
879 if (helper == null) return;
880
881 boolean isSafe = !restricted;
882 try {
883 helper.setSafetyMode(isSafe);
884 } catch (Exception e) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800885 Slog.e(TAG, "Exception calling helper.setDpmSafetyMode(" + isSafe + ")", e);
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800886 }
887 }
888
889 private void setUxRestrictions(@Nullable CarUxRestrictions restrictions) {
Felipe Leme5d5ab142020-10-27 13:49:10 -0700890 boolean restricted = restrictions != null
891 && (restrictions.getActiveRestrictions() & UX_RESTRICTIONS_NO_SETUP)
892 == UX_RESTRICTIONS_NO_SETUP;
Eric Jeongf75d4132020-12-21 13:48:23 -0800893 if (Log.isLoggable(TAG, Log.DEBUG)) {
894 Slog.d(TAG, "setUxRestrictions(" + restrictions + "): restricted=" + restricted);
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800895 } else {
Eric Jeongf75d4132020-12-21 13:48:23 -0800896 Slog.i(TAG, "Setting UX restricted to " + restricted);
Felipe Leme5d5ab142020-10-27 13:49:10 -0700897 }
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800898
899 ICarServiceHelper helper = null;
900
901 synchronized (mLockUser) {
902 mUxRestricted = restricted;
903 if (mICarServiceHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800904 Slog.e(TAG, "onUxRestrictionsChanged(): no mICarServiceHelper");
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800905 }
906 helper = mICarServiceHelper;
907 }
908 updateSafetyMode(helper, restricted);
909 }
910
911 private boolean isUxRestricted() {
912 synchronized (mLockUser) {
913 return mUxRestricted;
914 }
Felipe Leme5d5ab142020-10-27 13:49:10 -0700915 }
916
Mayank Garg70732a82020-08-05 20:17:47 -0700917 /**
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700918 * Calls the {@link UserHalService} and {@link IActivityManager} for user switch.
919 *
920 * <p>
Mayank Gargb08f6772020-05-01 18:06:48 -0700921 * When everything works well, the workflow is:
922 * <ol>
923 * <li> {@link UserHalService} is called for HAL user switch with ANDROID_SWITCH request
924 * type, current user id, target user id, and a callback.
925 * <li> HAL called back with SUCCESS.
926 * <li> {@link IActivityManager} is called for Android user switch.
927 * <li> Receiver would receive {@code STATUS_SUCCESSFUL}.
928 * <li> Once user is unlocked, {@link UserHalService} is again called with ANDROID_POST_SWITCH
929 * request type, current user id, and target user id. In this case, the current and target
930 * user IDs would be same.
931 * <ol/>
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700932 *
933 * <p>
Mayank Gargb08f6772020-05-01 18:06:48 -0700934 * Corner cases:
935 * <ul>
936 * <li> If target user is already the current user, no user switch is performed and receiver
Mayank Gargef1b9332020-06-11 17:36:56 -0700937 * would receive {@code STATUS_OK_USER_ALREADY_IN_FOREGROUND} right away.
Mayank Gargb08f6772020-05-01 18:06:48 -0700938 * <li> If HAL user switch call fails, no Android user switch. Receiver would receive
939 * {@code STATUS_HAL_INTERNAL_FAILURE}.
940 * <li> If HAL user switch call is successful, but android user switch call fails,
941 * {@link UserHalService} is again called with request type POST_SWITCH, current user id, and
942 * target user id, but in this case the current and target user IDs would be different.
943 * <li> If another user switch request for the same target user is received while previous
944 * request is in process, receiver would receive
945 * {@code STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO} for the new request right away.
946 * <li> If a user switch request is received while another user switch request for different
947 * target user is in process, the previous request would be abandoned and new request will be
948 * processed. No POST_SWITCH would be sent for the previous request.
949 * <ul/>
Mayank Garg59f22192020-03-27 00:51:45 -0700950 *
Mayank Garge19c2922020-03-30 18:05:53 -0700951 * @param targetUserId - target user Id
Mayank Garg59f22192020-03-27 00:51:45 -0700952 * @param timeoutMs - timeout for HAL to wait
953 * @param receiver - receiver for the results
954 */
Mayank Garge19c2922020-03-30 18:05:53 -0700955 @Override
956 public void switchUser(@UserIdInt int targetUserId, int timeoutMs,
felipeale5bf0322020-04-16 15:10:57 -0700957 @NonNull AndroidFuture<UserSwitchResult> receiver) {
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700958 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_REQ, targetUserId, timeoutMs);
Felipe Leme17799202020-09-03 12:55:53 -0700959 checkManageOrCreateUsersPermission("switchUser");
Mayank Garge19c2922020-03-30 18:05:53 -0700960 Objects.requireNonNull(receiver);
961 UserInfo targetUser = mUserManager.getUserInfo(targetUserId);
felipealf7368962020-04-16 12:55:19 -0700962 Preconditions.checkArgument(targetUser != null, "Target user doesn't exist");
Mayank Garg02576972021-02-18 16:46:07 -0800963 mHandler.post(()-> switchUserInternal(targetUser, timeoutMs, receiver));
964 }
Mayank Garg7a114c82020-04-08 21:25:06 -0700965
Mayank Garg02576972021-02-18 16:46:07 -0800966 private void switchUserInternal(@NonNull UserInfo targetUser, int timeoutMs,
967 @NonNull AndroidFuture<UserSwitchResult> receiver) {
felipealf7368962020-04-16 12:55:19 -0700968 int currentUser = ActivityManager.getCurrentUser();
Mayank Garg02576972021-02-18 16:46:07 -0800969 int targetUserId = targetUser.id;
felipealf7368962020-04-16 12:55:19 -0700970 if (currentUser == targetUserId) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800971 if (Log.isLoggable(TAG, Log.DEBUG)) {
972 Slog.d(TAG, "Current user is same as requested target user: " + targetUserId);
Mayank Garg0e239142020-04-14 19:16:31 -0700973 }
Mayank Gargef1b9332020-06-11 17:36:56 -0700974 int resultStatus = UserSwitchResult.STATUS_OK_USER_ALREADY_IN_FOREGROUND;
felipealdfdf8512020-06-01 09:35:45 -0700975 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg0e239142020-04-14 19:16:31 -0700976 return;
977 }
978
Felipe Leme5d5ab142020-10-27 13:49:10 -0700979 if (isUxRestricted()) {
980 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_UX_RESTRICTION_FAILURE);
981 return;
982 }
983
Mayank Garg9ed099e2020-06-04 16:05:20 -0700984 // If User Hal is not supported, just android user switch.
985 if (!isUserHalSupported()) {
986 try {
987 if (mAm.switchUser(targetUserId)) {
988 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_SUCCESSFUL);
989 return;
990 }
991 } catch (RemoteException e) {
992 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -0800993 Slog.w(TAG, "error while switching user " + targetUser.toFullString(), e);
Mayank Garg9ed099e2020-06-04 16:05:20 -0700994 }
995 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_ANDROID_FAILURE);
996 return;
997 }
998
Mayank Garg7a114c82020-04-08 21:25:06 -0700999 synchronized (mLockUser) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001000 if (Log.isLoggable(TAG, Log.DEBUG)) {
1001 Slog.d(TAG, "switchUser(" + targetUserId + "): currentuser=" + currentUser
felipealf7368962020-04-16 12:55:19 -07001002 + ", mUserIdForUserSwitchInProcess=" + mUserIdForUserSwitchInProcess);
1003 }
1004
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001005 // If there is another request for the same target user, return another request in
1006 // process, else {@link mUserIdForUserSwitchInProcess} is updated and {@link
1007 // mRequestIdForUserSwitchInProcess} is reset. It is possible that there may be another
1008 // user switch request in process for different target user, but that request is now
1009 // ignored.
felipealf7368962020-04-16 12:55:19 -07001010 if (mUserIdForUserSwitchInProcess == targetUserId) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001011 if (Log.isLoggable(TAG, Log.DEBUG)) {
1012 Slog.d(TAG,
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001013 "Another user switch request in process for the requested target user: "
1014 + targetUserId);
1015 }
1016
1017 int resultStatus = UserSwitchResult.STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO;
felipealdfdf8512020-06-01 09:35:45 -07001018 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg7a114c82020-04-08 21:25:06 -07001019 return;
Mayank Garg02576972021-02-18 16:46:07 -08001020 } else {
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001021 mUserIdForUserSwitchInProcess = targetUserId;
1022 mRequestIdForUserSwitchInProcess = 0;
1023 }
Mayank Garg7a114c82020-04-08 21:25:06 -07001024 }
1025
felipealdfdf8512020-06-01 09:35:45 -07001026 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
Mayank Gargeb37d092020-06-02 14:37:57 -07001027 SwitchUserRequest request = createUserSwitchRequest(targetUserId, usersInfo);
1028
Felipe Leme5d5ab142020-10-27 13:49:10 -07001029 mHal.switchUser(request, timeoutMs, (halCallbackStatus, resp) -> {
Eric Jeongf75d4132020-12-21 13:48:23 -08001030 if (Log.isLoggable(TAG, Log.DEBUG)) {
1031 Slog.d(TAG, "switch response: status="
Felipe Leme5d5ab142020-10-27 13:49:10 -07001032 + UserHalHelper.halCallbackStatusToString(halCallbackStatus)
1033 + ", resp=" + resp);
felipealf7368962020-04-16 12:55:19 -07001034 }
1035
felipeale5bf0322020-04-16 15:10:57 -07001036 int resultStatus = UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE;
felipealf7368962020-04-16 12:55:19 -07001037
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001038 synchronized (mLockUser) {
Felipe Leme5d5ab142020-10-27 13:49:10 -07001039 if (halCallbackStatus != HalCallback.STATUS_OK) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001040 Slog.w(TAG, "invalid callback status ("
Felipe Leme5d5ab142020-10-27 13:49:10 -07001041 + UserHalHelper.halCallbackStatusToString(halCallbackStatus)
1042 + ") for response " + resp);
felipealdfdf8512020-06-01 09:35:45 -07001043 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001044 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
1045 return;
1046 }
felipealf7368962020-04-16 12:55:19 -07001047
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001048 if (mUserIdForUserSwitchInProcess != targetUserId) {
1049 // Another user switch request received while HAL responded. No need to process
1050 // this request further
Eric Jeongf75d4132020-12-21 13:48:23 -08001051 if (Log.isLoggable(TAG, Log.DEBUG)) {
1052 Slog.d(TAG, "Another user switch received while HAL responsed. Request"
1053 + " abondoned for : " + targetUserId + ". Current user in process: "
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001054 + mUserIdForUserSwitchInProcess);
felipealf7368962020-04-16 12:55:19 -07001055 }
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001056 resultStatus =
1057 UserSwitchResult.STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST;
felipealdfdf8512020-06-01 09:35:45 -07001058 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001059 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
1060 return;
1061 }
1062
1063 switch (resp.status) {
1064 case SwitchUserStatus.SUCCESS:
1065 boolean switched;
1066 try {
1067 switched = mAm.switchUser(targetUserId);
1068 if (switched) {
Mayank Garg587f1942020-05-06 01:41:34 -07001069 sendUserSwitchUiCallback(targetUserId);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001070 resultStatus = UserSwitchResult.STATUS_SUCCESSFUL;
1071 mRequestIdForUserSwitchInProcess = resp.requestId;
1072 } else {
1073 resultStatus = UserSwitchResult.STATUS_ANDROID_FAILURE;
1074 postSwitchHalResponse(resp.requestId, targetUserId);
1075 }
1076 } catch (RemoteException e) {
1077 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001078 Slog.w(TAG,
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001079 "error while switching user " + targetUser.toFullString(), e);
1080 }
1081 break;
1082 case SwitchUserStatus.FAILURE:
1083 // HAL failed to switch user
1084 resultStatus = UserSwitchResult.STATUS_HAL_FAILURE;
1085 break;
felipealdfdf8512020-06-01 09:35:45 -07001086 default:
1087 // Shouldn't happen because UserHalService validates the status
Eric Jeongf75d4132020-12-21 13:48:23 -08001088 Slog.wtf(TAG, "Received invalid user switch status from HAL: " + resp);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001089 }
1090
1091 if (mRequestIdForUserSwitchInProcess == 0) {
1092 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
1093 }
Mayank Garg59f22192020-03-27 00:51:45 -07001094 }
Felipe Leme5d5ab142020-10-27 13:49:10 -07001095 sendUserSwitchResult(receiver, halCallbackStatus, resultStatus, resp.errorMessage);
Mayank Garg59f22192020-03-27 00:51:45 -07001096 });
1097 }
1098
Mayank Garga55c3092020-05-28 03:19:24 -07001099 @Override
Mayank Gargc9266482021-03-01 10:27:37 -08001100 public void removeUser(@UserIdInt int userId, AndroidFuture<UserRemovalResult> receiver) {
1101 removeUser(userId, /* hasCallerRestrictions= */ false, receiver);
Felipe Leme55236722020-10-16 16:54:32 -07001102 }
1103
1104 /**
1105 * Internal implementation of {@code removeUser()}, which is used by both
1106 * {@code ICarUserService} and {@code ICarDevicePolicyService}.
1107 *
1108 * @param userId user to be removed
1109 * @param hasCallerRestrictions when {@code true}, if the caller user is not an admin, it can
1110 * only remove itself.
Mayank Gargc9266482021-03-01 10:27:37 -08001111 * @param receiver to post results
Felipe Leme55236722020-10-16 16:54:32 -07001112 */
Mayank Gargc9266482021-03-01 10:27:37 -08001113 public void removeUser(@UserIdInt int userId, boolean hasCallerRestrictions,
1114 AndroidFuture<UserRemovalResult> receiver) {
Felipe Leme17799202020-09-03 12:55:53 -07001115 checkManageOrCreateUsersPermission("removeUser");
Felipe Leme55236722020-10-16 16:54:32 -07001116 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_REMOVE_USER_REQ, userId,
1117 hasCallerRestrictions ? 1 : 0);
Felipe Lemee5bb26b2020-10-26 15:49:17 -07001118
Felipe Lemee5bb26b2020-10-26 15:49:17 -07001119 if (hasCallerRestrictions) {
1120 // Restrictions: non-admin user can only remove itself, admins have no restrictions
1121 int callingUserId = Binder.getCallingUserHandle().getIdentifier();
1122 UserInfo callingUser = mUserManager.getUserInfo(callingUserId);
1123 if (!callingUser.isAdmin() && userId != callingUserId) {
1124 throw new SecurityException("Non-admin user " + callingUserId
1125 + " can only remove itself");
1126 }
1127 }
Mayank Gargc9266482021-03-01 10:27:37 -08001128 mHandler.post(()-> removeUserInternal(userId, hasCallerRestrictions, receiver));
1129 }
Felipe Lemee5bb26b2020-10-26 15:49:17 -07001130
Mayank Gargc9266482021-03-01 10:27:37 -08001131 private void removeUserInternal(@UserIdInt int userId, boolean hasCallerRestrictions,
1132 AndroidFuture<UserRemovalResult> receiver) {
1133 UserInfo userInfo = mUserManager.getUserInfo(userId);
1134 if (userInfo == null) {
1135 sendUserRemovalResult(userId, UserRemovalResult.STATUS_USER_DOES_NOT_EXIST, receiver);
1136 return;
1137 }
Mayank Garga55c3092020-05-28 03:19:24 -07001138 android.hardware.automotive.vehicle.V2_0.UserInfo halUser =
1139 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1140 halUser.userId = userInfo.id;
1141 halUser.flags = UserHalHelper.convertFlags(userInfo);
1142 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1143
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001144 // check if the user is last admin user.
1145 boolean isLastAdmin = false;
Mayank Garga55c3092020-05-28 03:19:24 -07001146 if (UserHalHelper.isAdmin(halUser.flags)) {
1147 int size = usersInfo.existingUsers.size();
1148 int totalAdminUsers = 0;
1149 for (int i = 0; i < size; i++) {
1150 if (UserHalHelper.isAdmin(usersInfo.existingUsers.get(i).flags)) {
1151 totalAdminUsers++;
1152 }
1153 }
1154 if (totalAdminUsers == 1) {
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001155 isLastAdmin = true;
Mayank Garga55c3092020-05-28 03:19:24 -07001156 }
1157 }
1158
1159 // First remove user from android and then remove from HAL because HAL remove user is one
1160 // way call.
Felipe Leme9a751912021-01-05 17:45:48 -08001161 // TODO(b/170887769): rename hasCallerRestrictions to fromCarDevicePolicyManager (or use an
1162 // int / enum to indicate if it's called from CarUserManager or CarDevicePolicyManager), as
1163 // it's counter-intuitive that it's "allowed even when disallowed" when it
1164 // "has caller restrictions"
1165 boolean evenWhenDisallowed = hasCallerRestrictions;
1166 int result = mUserManager.removeUserOrSetEphemeral(userId, evenWhenDisallowed);
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001167 if (result == UserManager.REMOVE_RESULT_ERROR) {
Mayank Gargc9266482021-03-01 10:27:37 -08001168 sendUserRemovalResult(userId, UserRemovalResult.STATUS_ANDROID_FAILURE, receiver);
1169 return;
Mayank Garga55c3092020-05-28 03:19:24 -07001170 }
1171
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001172 if (isLastAdmin) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001173 Slog.w(TAG,
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001174 "Last admin user successfully removed or set ephemeral. User Id: " + userId);
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001175 }
1176
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001177 switch (result) {
1178 case UserManager.REMOVE_RESULT_REMOVED:
1179 case UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED:
Mayank Gargc9266482021-03-01 10:27:37 -08001180 sendUserRemovalResult(userId,
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001181 isLastAdmin ? UserRemovalResult.STATUS_SUCCESSFUL_LAST_ADMIN_REMOVED
Mayank Gargc9266482021-03-01 10:27:37 -08001182 : UserRemovalResult.STATUS_SUCCESSFUL, receiver);
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001183 case UserManager.REMOVE_RESULT_SET_EPHEMERAL:
Mayank Gargc9266482021-03-01 10:27:37 -08001184 sendUserRemovalResult(userId,
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001185 isLastAdmin ? UserRemovalResult.STATUS_SUCCESSFUL_LAST_ADMIN_SET_EPHEMERAL
Mayank Gargc9266482021-03-01 10:27:37 -08001186 : UserRemovalResult.STATUS_SUCCESSFUL_SET_EPHEMERAL, receiver);
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001187 default:
Mayank Gargc9266482021-03-01 10:27:37 -08001188 sendUserRemovalResult(userId, UserRemovalResult.STATUS_ANDROID_FAILURE, receiver);
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001189 }
Mayank Garga55c3092020-05-28 03:19:24 -07001190 }
1191
Felipe Leme67d564c2020-11-13 15:35:34 -08001192 /**
1193 * Should be called by {@code ICarImpl} only.
1194 */
1195 public void onUserRemoved(@NonNull UserInfo user) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001196 if (Log.isLoggable(TAG, Log.DEBUG)) {
1197 Slog.d(TAG, "onUserRemoved: " + user.toFullString());
Felipe Leme67d564c2020-11-13 15:35:34 -08001198 }
1199 notifyHalUserRemoved(user);
1200 }
1201
1202 private void notifyHalUserRemoved(@NonNull UserInfo user) {
Felipe Leme6b34fc32020-10-26 15:49:17 -07001203 if (!isUserHalSupported()) return;
1204
Felipe Leme67d564c2020-11-13 15:35:34 -08001205 if (user == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001206 Slog.wtf(TAG, "notifyHalUserRemoved() called for null user");
Felipe Leme67d564c2020-11-13 15:35:34 -08001207 return;
1208 }
1209
1210 int userId = user.id;
1211
Felipe Leme6b34fc32020-10-26 15:49:17 -07001212 if (userId == UserHandle.USER_NULL) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001213 Slog.wtf(TAG, "notifyHalUserRemoved() called for UserHandle.USER_NULL");
Felipe Leme6b34fc32020-10-26 15:49:17 -07001214 return;
1215 }
1216
1217 synchronized (mLockUser) {
1218 if (mFailedToCreateUserIds.get(userId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001219 if (Log.isLoggable(TAG, Log.DEBUG)) {
1220 Slog.d(TAG, "notifyHalUserRemoved(): skipping " + userId);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001221 }
1222 mFailedToCreateUserIds.delete(userId);
1223 return;
1224 }
1225 }
1226
1227 android.hardware.automotive.vehicle.V2_0.UserInfo halUser =
1228 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1229 halUser.userId = userId;
Felipe Leme67d564c2020-11-13 15:35:34 -08001230 halUser.flags = UserHalHelper.convertFlags(user);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001231
1232 RemoveUserRequest request = new RemoveUserRequest();
1233 request.removedUserInfo = halUser;
1234 request.usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1235 mHal.removeUser(request);
1236 }
1237
Mayank Gargc9266482021-03-01 10:27:37 -08001238 private void sendUserRemovalResult(@UserIdInt int userId, @UserRemovalResult.Status int result,
1239 AndroidFuture<UserRemovalResult> receiver) {
Mayank Garga55c3092020-05-28 03:19:24 -07001240 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_REMOVE_USER_RESP, userId, result);
Mayank Gargc9266482021-03-01 10:27:37 -08001241 receiver.complete(new UserRemovalResult(result));
Mayank Garga55c3092020-05-28 03:19:24 -07001242 }
1243
Mayank Garg587f1942020-05-06 01:41:34 -07001244 private void sendUserSwitchUiCallback(@UserIdInt int targetUserId) {
1245 if (mUserSwitchUiReceiver == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001246 Slog.w(TAG, "No User switch UI receiver.");
Mayank Garg587f1942020-05-06 01:41:34 -07001247 return;
1248 }
1249
felipealdfdf8512020-06-01 09:35:45 -07001250 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_UI_REQ, targetUserId);
Mayank Garg587f1942020-05-06 01:41:34 -07001251 try {
Mayank Garg587f1942020-05-06 01:41:34 -07001252 mUserSwitchUiReceiver.send(targetUserId, null);
1253 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001254 Slog.e(TAG, "Error calling user switch UI receiver.", e);
Mayank Garg587f1942020-05-06 01:41:34 -07001255 }
1256 }
1257
Felipe Lemecceb2992020-11-18 18:22:44 -08001258 /**
1259 * Used to create the initial user, even when it's disallowed by {@code DevicePolicyManager}.
1260 */
1261 @Nullable
1262 UserInfo createUserEvenWhenDisallowed(@Nullable String name, @NonNull String userType,
1263 @UserInfoFlag int flags) {
1264 if (mICarServiceHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001265 Slog.wtf(TAG, "createUserEvenWhenDisallowed(): mICarServiceHelper not set yet",
Felipe Lemecceb2992020-11-18 18:22:44 -08001266 new Exception());
1267 return null;
1268 }
1269 try {
1270 return mICarServiceHelper.createUserEvenWhenDisallowed(name, userType, flags);
1271 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001272 Slog.e(TAG, "createUserEvenWhenDisallowed(" + UserHelperLite.safeName(name) + ", "
Felipe Lemecceb2992020-11-18 18:22:44 -08001273 + userType + ", " + UserInfo.flagsToString(flags) + ") failed", e);
1274 return null;
1275 }
1276 }
1277
felipeal5e3ede42020-04-23 18:04:07 -07001278 @Override
felipealdfdf8512020-06-01 09:35:45 -07001279 public void createUser(@Nullable String name, @NonNull String userType, @UserInfoFlag int flags,
1280 int timeoutMs, @NonNull AndroidFuture<UserCreationResult> receiver) {
Felipe Leme8c888ab2020-11-02 17:39:52 -08001281 createUser(name, userType, flags, timeoutMs, receiver, /* hasCallerRestrictions= */ false);
1282 }
1283
1284 /**
1285 * Internal implementation of {@code createUser()}, which is used by both
1286 * {@code ICarUserService} and {@code ICarDevicePolicyService}.
1287 *
1288 * @param hasCallerRestrictions when {@code true}, if the caller user is not an admin, it can
1289 * only create admin users
1290 */
1291 public void createUser(@Nullable String name, @NonNull String userType, @UserInfoFlag int flags,
1292 int timeoutMs, @NonNull AndroidFuture<UserCreationResult> receiver,
1293 boolean hasCallerRestrictions) {
felipealdfdf8512020-06-01 09:35:45 -07001294 Objects.requireNonNull(userType, "user type cannot be null");
1295 Objects.requireNonNull(receiver, "receiver cannot be null");
Felipe Leme17799202020-09-03 12:55:53 -07001296 checkManageOrCreateUsersPermission(flags);
Mayank Garg94f3eb92020-08-12 12:38:58 -07001297 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_REQ,
Felipe Leme8c888ab2020-11-02 17:39:52 -08001298 UserHelperLite.safeName(name), userType, flags, timeoutMs,
1299 hasCallerRestrictions ? 1 : 0);
Mayank Garg02576972021-02-18 16:46:07 -08001300 mHandler.post(() -> createUserInternal(name, userType, flags, timeoutMs, receiver,
1301 hasCallerRestrictions));
Felipe Leme8c888ab2020-11-02 17:39:52 -08001302
Mayank Garg02576972021-02-18 16:46:07 -08001303 }
1304
1305 private void createUserInternal(@Nullable String name, @NonNull String userType,
1306 @UserInfoFlag int flags, int timeoutMs,
1307 @NonNull AndroidFuture<UserCreationResult> receiver,
1308 boolean hasCallerRestrictions) {
Felipe Leme8c888ab2020-11-02 17:39:52 -08001309 if (hasCallerRestrictions) {
1310 // Restrictions:
1311 // - type/flag can only be normal user, admin, or guest
1312 // - non-admin user can only create non-admin users
1313
1314 boolean validCombination;
1315 switch (userType) {
1316 case UserManager.USER_TYPE_FULL_SECONDARY:
1317 validCombination = flags == 0
1318 || (flags & UserInfo.FLAG_ADMIN) == UserInfo.FLAG_ADMIN;
1319 break;
1320 case UserManager.USER_TYPE_FULL_GUEST:
1321 validCombination = flags == 0;
1322 break;
1323 default:
1324 validCombination = false;
1325 }
1326 if (!validCombination) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001327 if (Log.isLoggable(TAG, Log.DEBUG)) {
1328 Slog.d(TAG, "Invalid combination of user type(" + userType
Felipe Leme71d296f2020-11-04 12:11:42 -08001329 + ") and flags (" + UserInfo.flagsToString(flags)
1330 + ") for caller with restrictions");
1331 }
1332 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_INVALID_REQUEST);
1333 return;
1334
Felipe Leme8c888ab2020-11-02 17:39:52 -08001335 }
1336
1337 int callingUserId = Binder.getCallingUserHandle().getIdentifier();
1338 UserInfo callingUser = mUserManager.getUserInfo(callingUserId);
1339 if (!callingUser.isAdmin() && (flags & UserInfo.FLAG_ADMIN) == UserInfo.FLAG_ADMIN) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001340 if (Log.isLoggable(TAG, Log.DEBUG)) {
1341 Slog.d(TAG, "Non-admin user " + callingUserId
Felipe Leme71d296f2020-11-04 12:11:42 -08001342 + " can only create non-admin users");
1343 }
1344 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_INVALID_REQUEST);
1345 return;
Felipe Leme8c888ab2020-11-02 17:39:52 -08001346 }
Felipe Leme71d296f2020-11-04 12:11:42 -08001347
Felipe Leme8c888ab2020-11-02 17:39:52 -08001348 }
felipealdfdf8512020-06-01 09:35:45 -07001349
1350 UserInfo newUser;
1351 try {
1352 newUser = mUserManager.createUser(name, userType, flags);
1353 if (newUser == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001354 Slog.w(TAG, "um.createUser() returned null for user of type " + userType
felipealdfdf8512020-06-01 09:35:45 -07001355 + " and flags " + UserInfo.flagsToString(flags));
1356 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_ANDROID_FAILURE);
1357 return;
1358 }
Eric Jeongf75d4132020-12-21 13:48:23 -08001359 if (Log.isLoggable(TAG, Log.DEBUG)) {
1360 Slog.d(TAG, "Created user: " + newUser.toFullString());
felipealdfdf8512020-06-01 09:35:45 -07001361 }
1362 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_USER_CREATED, newUser.id,
Mayank Garg94f3eb92020-08-12 12:38:58 -07001363 UserHelperLite.safeName(newUser.name), newUser.userType, newUser.flags);
felipealdfdf8512020-06-01 09:35:45 -07001364 } catch (RuntimeException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001365 Slog.e(TAG, "Error creating user of type " + userType + " and flags"
felipealdfdf8512020-06-01 09:35:45 -07001366 + UserInfo.flagsToString(flags), e);
1367 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_ANDROID_FAILURE);
1368 return;
1369 }
1370
Mayank Garg9ed099e2020-06-04 16:05:20 -07001371 if (!isUserHalSupported()) {
1372 sendUserCreationResult(receiver, UserCreationResult.STATUS_SUCCESSFUL, newUser, null);
1373 return;
1374 }
1375
felipealdfdf8512020-06-01 09:35:45 -07001376 CreateUserRequest request = new CreateUserRequest();
1377 request.usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1378 if (!TextUtils.isEmpty(name)) {
1379 request.newUserName = name;
1380 }
1381 request.newUserInfo.userId = newUser.id;
1382 request.newUserInfo.flags = UserHalHelper.convertFlags(newUser);
Eric Jeongf75d4132020-12-21 13:48:23 -08001383 if (Log.isLoggable(TAG, Log.DEBUG)) {
1384 Slog.d(TAG, "Create user request: " + request);
felipealdfdf8512020-06-01 09:35:45 -07001385 }
1386
1387 try {
1388 mHal.createUser(request, timeoutMs, (status, resp) -> {
1389 int resultStatus = UserCreationResult.STATUS_HAL_INTERNAL_FAILURE;
Eric Jeongf75d4132020-12-21 13:48:23 -08001390 if (Log.isLoggable(TAG, Log.DEBUG)) {
1391 Slog.d(TAG, "createUserResponse: status="
felipealdfdf8512020-06-01 09:35:45 -07001392 + UserHalHelper.halCallbackStatusToString(status) + ", resp=" + resp);
1393 }
1394 UserInfo user = null; // user returned in the result
1395 if (status != HalCallback.STATUS_OK) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001396 Slog.w(TAG, "invalid callback status ("
felipealdfdf8512020-06-01 09:35:45 -07001397 + UserHalHelper.halCallbackStatusToString(status) + ") for response "
1398 + resp);
1399 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_RESP, status,
1400 resultStatus, resp.errorMessage);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001401 removeCreatedUser(newUser, "HAL call failed with "
felipealdfdf8512020-06-01 09:35:45 -07001402 + UserHalHelper.halCallbackStatusToString(status));
1403 sendUserCreationResult(receiver, resultStatus, user, /* errorMsg= */ null);
1404 return;
1405 }
1406
1407 switch (resp.status) {
1408 case CreateUserStatus.SUCCESS:
1409 resultStatus = UserCreationResult.STATUS_SUCCESSFUL;
1410 user = newUser;
1411 break;
1412 case CreateUserStatus.FAILURE:
1413 // HAL failed to switch user
1414 resultStatus = UserCreationResult.STATUS_HAL_FAILURE;
1415 break;
1416 default:
1417 // Shouldn't happen because UserHalService validates the status
Eric Jeongf75d4132020-12-21 13:48:23 -08001418 Slog.wtf(TAG, "Received invalid user switch status from HAL: " + resp);
felipealdfdf8512020-06-01 09:35:45 -07001419 }
1420 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_RESP, status,
1421 resultStatus, resp.errorMessage);
1422 if (user == null) {
Felipe Leme6b34fc32020-10-26 15:49:17 -07001423 removeCreatedUser(newUser, "HAL returned "
felipealdfdf8512020-06-01 09:35:45 -07001424 + UserCreationResult.statusToString(resultStatus));
1425 }
1426 sendUserCreationResult(receiver, resultStatus, user, resp.errorMessage);
1427 });
1428 } catch (Exception e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001429 Slog.w(TAG, "mHal.createUser(" + request + ") failed", e);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001430 removeCreatedUser(newUser, "mHal.createUser() failed");
felipealdfdf8512020-06-01 09:35:45 -07001431 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_HAL_INTERNAL_FAILURE);
1432 }
1433 }
1434
Felipe Leme6b34fc32020-10-26 15:49:17 -07001435 private void removeCreatedUser(@NonNull UserInfo user, @NonNull String reason) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001436 Slog.i(TAG, "removing " + user.toFullString() + "; reason: " + reason);
Felipe Leme67d564c2020-11-13 15:35:34 -08001437
Felipe Leme6b34fc32020-10-26 15:49:17 -07001438 int userId = user.id;
1439 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_USER_REMOVED, userId, reason);
1440
1441 synchronized (mLockUser) {
1442 mFailedToCreateUserIds.put(userId, true);
1443 }
1444
felipealdfdf8512020-06-01 09:35:45 -07001445 try {
Felipe Leme6b34fc32020-10-26 15:49:17 -07001446 if (!mUserManager.removeUser(userId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001447 Slog.w(TAG, "Failed to remove user " + user.toFullString());
felipealdfdf8512020-06-01 09:35:45 -07001448 }
1449 } catch (Exception e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001450 Slog.e(TAG, "Failed to remove user " + user.toFullString(), e);
felipealdfdf8512020-06-01 09:35:45 -07001451 }
1452 }
1453
1454 @Override
Mayank Garg3f566582020-10-02 22:10:16 -07001455 public UserIdentificationAssociationResponse getUserIdentificationAssociation(
1456 @UserIdentificationAssociationType int[] types) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001457 if (!isUserHalUserAssociationSupported()) {
1458 return UserIdentificationAssociationResponse.forFailure(VEHICLE_HAL_NOT_SUPPORTED);
1459 }
1460
felipeal5e3ede42020-04-23 18:04:07 -07001461 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type");
Felipe Leme17799202020-09-03 12:55:53 -07001462 checkManageOrCreateUsersPermission("getUserIdentificationAssociation");
felipeal5e3ede42020-04-23 18:04:07 -07001463
1464 int uid = getCallingUid();
1465 int userId = UserHandle.getUserId(uid);
1466 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_GET_USER_AUTH_REQ, uid, userId);
1467
1468 UserIdentificationGetRequest request = new UserIdentificationGetRequest();
1469 request.userInfo.userId = userId;
1470 request.userInfo.flags = getHalUserInfoFlags(userId);
1471
1472 request.numberAssociationTypes = types.length;
1473 for (int i = 0; i < types.length; i++) {
1474 request.associationTypes.add(types[i]);
1475 }
1476
1477 UserIdentificationResponse halResponse = mHal.getUserAssociation(request);
1478 if (halResponse == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001479 Slog.w(TAG, "getUserIdentificationAssociation(): HAL returned null for "
felipeal5e3ede42020-04-23 18:04:07 -07001480 + Arrays.toString(types));
felipeal159a2a42020-05-08 10:32:11 -07001481 return UserIdentificationAssociationResponse.forFailure();
felipeal5e3ede42020-04-23 18:04:07 -07001482 }
1483
1484 int[] values = new int[halResponse.associations.size()];
1485 for (int i = 0; i < values.length; i++) {
1486 values[i] = halResponse.associations.get(i).value;
1487 }
1488 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_GET_USER_AUTH_RESP, values.length);
1489
felipeal159a2a42020-05-08 10:32:11 -07001490 return UserIdentificationAssociationResponse.forSuccess(values, halResponse.errorMessage);
1491 }
1492
1493 @Override
Mayank Garg3f566582020-10-02 22:10:16 -07001494 public void setUserIdentificationAssociation(int timeoutMs,
1495 @UserIdentificationAssociationType int[] types,
1496 @UserIdentificationAssociationSetValue int[] values,
felipeal159a2a42020-05-08 10:32:11 -07001497 AndroidFuture<UserIdentificationAssociationResponse> result) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001498 if (!isUserHalUserAssociationSupported()) {
1499 result.complete(
1500 UserIdentificationAssociationResponse.forFailure(VEHICLE_HAL_NOT_SUPPORTED));
1501 return;
1502 }
1503
felipeal159a2a42020-05-08 10:32:11 -07001504 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type");
1505 Preconditions.checkArgument(!ArrayUtils.isEmpty(values), "must have at least one value");
1506 if (types.length != values.length) {
1507 throw new IllegalArgumentException("types (" + Arrays.toString(types) + ") and values ("
1508 + Arrays.toString(values) + ") should have the same length");
1509 }
Felipe Leme17799202020-09-03 12:55:53 -07001510 checkManageOrCreateUsersPermission("setUserIdentificationAssociation");
felipeal159a2a42020-05-08 10:32:11 -07001511
1512 int uid = getCallingUid();
1513 int userId = UserHandle.getUserId(uid);
1514 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_REQ, uid, userId, types.length);
1515
1516 UserIdentificationSetRequest request = new UserIdentificationSetRequest();
1517 request.userInfo.userId = userId;
1518 request.userInfo.flags = getHalUserInfoFlags(userId);
1519
1520 request.numberAssociations = types.length;
1521 for (int i = 0; i < types.length; i++) {
1522 UserIdentificationSetAssociation association = new UserIdentificationSetAssociation();
1523 association.type = types[i];
1524 association.value = values[i];
1525 request.associations.add(association);
1526 }
1527
1528 mHal.setUserAssociation(timeoutMs, request, (status, resp) -> {
1529 if (status != HalCallback.STATUS_OK) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001530 Slog.w(TAG, "setUserIdentificationAssociation(): invalid callback status ("
felipeal159a2a42020-05-08 10:32:11 -07001531 + UserHalHelper.halCallbackStatusToString(status) + ") for response "
1532 + resp);
1533 if (resp == null || TextUtils.isEmpty(resp.errorMessage)) {
1534 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, 0);
1535 result.complete(UserIdentificationAssociationResponse.forFailure());
1536 return;
1537 }
1538 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, 0,
1539 resp.errorMessage);
1540 result.complete(
1541 UserIdentificationAssociationResponse.forFailure(resp.errorMessage));
1542 return;
1543 }
1544 int respSize = resp.associations.size();
1545 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, respSize,
1546 resp.errorMessage);
1547
1548 int[] responseTypes = new int[respSize];
1549 for (int i = 0; i < respSize; i++) {
1550 responseTypes[i] = resp.associations.get(i).value;
1551 }
1552 UserIdentificationAssociationResponse response = UserIdentificationAssociationResponse
1553 .forSuccess(responseTypes, resp.errorMessage);
Eric Jeongf75d4132020-12-21 13:48:23 -08001554 if (Log.isLoggable(TAG, Log.DEBUG)) {
1555 Slog.d(TAG, "setUserIdentificationAssociation(): resp= " + resp
felipeal159a2a42020-05-08 10:32:11 -07001556 + ", converted=" + response);
1557 }
1558 result.complete(response);
1559 });
felipeal5e3ede42020-04-23 18:04:07 -07001560 }
1561
1562 /**
1563 * Gets the User HAL flags for the given user.
1564 *
1565 * @throws IllegalArgumentException if the user does not exist.
1566 */
1567 private int getHalUserInfoFlags(@UserIdInt int userId) {
1568 UserInfo user = mUserManager.getUserInfo(userId);
1569 Preconditions.checkArgument(user != null, "no user for id %d", userId);
1570 return UserHalHelper.convertFlags(user);
1571 }
1572
Mayank Garg0e239142020-04-14 19:16:31 -07001573 private void sendResult(@NonNull IResultReceiver receiver, int resultCode,
1574 @Nullable Bundle resultData) {
1575 try {
1576 receiver.send(resultCode, resultData);
1577 } catch (RemoteException e) {
1578 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001579 Slog.w(TAG, "error while sending results", e);
Mayank Garg0e239142020-04-14 19:16:31 -07001580 }
1581 }
1582
felipealdfdf8512020-06-01 09:35:45 -07001583 private void sendUserSwitchResult(@NonNull AndroidFuture<UserSwitchResult> receiver,
Felipe Leme5d5ab142020-10-27 13:49:10 -07001584 @UserSwitchResult.Status int userSwitchStatus) {
1585 sendUserSwitchResult(receiver, HalCallback.STATUS_INVALID, userSwitchStatus,
1586 /* errorMessage= */ null);
felipeale5bf0322020-04-16 15:10:57 -07001587 }
1588
felipealdfdf8512020-06-01 09:35:45 -07001589 private void sendUserSwitchResult(@NonNull AndroidFuture<UserSwitchResult> receiver,
Felipe Leme5d5ab142020-10-27 13:49:10 -07001590 @HalCallback.HalCallbackStatus int halCallbackStatus,
1591 @UserSwitchResult.Status int userSwitchStatus, @Nullable String errorMessage) {
1592 if (errorMessage != null) {
1593 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_RESP, halCallbackStatus,
1594 userSwitchStatus, errorMessage);
1595 } else {
1596 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_RESP, halCallbackStatus,
1597 userSwitchStatus);
1598 }
1599 receiver.complete(new UserSwitchResult(userSwitchStatus, errorMessage));
felipeale5bf0322020-04-16 15:10:57 -07001600 }
1601
felipealdfdf8512020-06-01 09:35:45 -07001602 private void sendUserCreationResultFailure(@NonNull AndroidFuture<UserCreationResult> receiver,
1603 @UserCreationResult.Status int status) {
1604 sendUserCreationResult(receiver, status, /* user= */ null, /* errorMessage= */ null);
1605 }
1606
1607 private void sendUserCreationResult(@NonNull AndroidFuture<UserCreationResult> receiver,
1608 @UserCreationResult.Status int status, @NonNull UserInfo user,
1609 @Nullable String errorMessage) {
1610 if (TextUtils.isEmpty(errorMessage)) {
1611 errorMessage = null;
1612 }
1613 receiver.complete(new UserCreationResult(status, user, errorMessage));
1614 }
1615
Mayank Garg6307fe42020-04-15 23:09:03 -07001616 /**
1617 * Calls activity manager for user switch.
1618 *
1619 * <p><b>NOTE</b> This method is meant to be called just by UserHalService.
1620 *
1621 * @param requestId for the user switch request
1622 * @param targetUserId of the target user
1623 *
1624 * @hide
1625 */
1626 public void switchAndroidUserFromHal(int requestId, @UserIdInt int targetUserId) {
1627 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_FROM_HAL_REQ, requestId,
1628 targetUserId);
Eric Jeongf75d4132020-12-21 13:48:23 -08001629 Slog.i(TAG, "User hal requested a user switch. Target user id " + targetUserId);
Mayank Garg6307fe42020-04-15 23:09:03 -07001630
1631 try {
1632 boolean result = mAm.switchUser(targetUserId);
1633 if (result) {
1634 updateUserSwitchInProcess(requestId, targetUserId);
1635 } else {
1636 postSwitchHalResponse(requestId, targetUserId);
1637 }
1638 } catch (RemoteException e) {
1639 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001640 Slog.w(TAG, "error while switching user " + targetUserId, e);
Mayank Garg6307fe42020-04-15 23:09:03 -07001641 }
1642 }
1643
1644 private void updateUserSwitchInProcess(int requestId, @UserIdInt int targetUserId) {
1645 synchronized (mLockUser) {
1646 if (mUserIdForUserSwitchInProcess != UserHandle.USER_NULL) {
1647 // Some other user switch is in process.
Eric Jeongf75d4132020-12-21 13:48:23 -08001648 if (Log.isLoggable(TAG, Log.DEBUG)) {
1649 Slog.d(TAG, "User switch for user: " + mUserIdForUserSwitchInProcess
Mayank Garg6307fe42020-04-15 23:09:03 -07001650 + " is in process. Abandoning it as a new user switch is requested"
1651 + " for the target user: " + targetUserId);
1652 }
1653 }
1654 mUserIdForUserSwitchInProcess = targetUserId;
1655 mRequestIdForUserSwitchInProcess = requestId;
1656 }
1657 }
Mayank Garg9ed099e2020-06-04 16:05:20 -07001658
Mayank Garg7a114c82020-04-08 21:25:06 -07001659 private void postSwitchHalResponse(int requestId, @UserIdInt int targetUserId) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001660 if (!isUserHalSupported()) return;
1661
felipealdfdf8512020-06-01 09:35:45 -07001662 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
Mayank Gargeb37d092020-06-02 14:37:57 -07001663 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_POST_SWITCH_USER_REQ, requestId,
1664 targetUserId, usersInfo.currentUser.userId);
1665 SwitchUserRequest request = createUserSwitchRequest(targetUserId, usersInfo);
1666 request.requestId = requestId;
1667 mHal.postSwitchResponse(request);
1668 }
1669
1670 private SwitchUserRequest createUserSwitchRequest(@UserIdInt int targetUserId,
1671 @NonNull UsersInfo usersInfo) {
1672 UserInfo targetUser = mUserManager.getUserInfo(targetUserId);
Mayank Garg7a114c82020-04-08 21:25:06 -07001673 android.hardware.automotive.vehicle.V2_0.UserInfo halTargetUser =
1674 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1675 halTargetUser.userId = targetUser.id;
1676 halTargetUser.flags = UserHalHelper.convertFlags(targetUser);
Mayank Gargeb37d092020-06-02 14:37:57 -07001677 SwitchUserRequest request = new SwitchUserRequest();
1678 request.targetUser = halTargetUser;
1679 request.usersInfo = usersInfo;
1680 return request;
Mayank Garg7a114c82020-04-08 21:25:06 -07001681 }
1682
Mayank Garg59f22192020-03-27 00:51:45 -07001683 /**
Felipe Lemee3cab982020-03-12 11:39:29 -07001684 * Checks if the User HAL is supported.
1685 */
1686 public boolean isUserHalSupported() {
1687 return mHal.isSupported();
1688 }
1689
Mayank Garg587f1942020-05-06 01:41:34 -07001690 /**
Mayank Garg9ed099e2020-06-04 16:05:20 -07001691 * Checks if the User HAL user association is supported.
1692 */
1693 @Override
1694 public boolean isUserHalUserAssociationSupported() {
1695 return mHal.isUserAssociationSupported();
1696 }
1697
1698 /**
Mayank Garg587f1942020-05-06 01:41:34 -07001699 * Sets a callback which is invoked before user switch.
1700 *
1701 * <p>
1702 * This method should only be called by the Car System UI. The purpose of this call is to notify
1703 * Car System UI to show the user switch UI before the user switch.
1704 */
1705 @Override
1706 public void setUserSwitchUiCallback(@NonNull IResultReceiver receiver) {
Yan Zhu67a383e2020-05-11 20:46:24 -07001707 checkManageUsersPermission("setUserSwitchUiCallback");
Mayank Garga480dd92020-05-14 03:14:57 -07001708
1709 // Confirm that caller is system UI.
1710 String systemUiPackageName = getSystemUiPackageName();
1711 if (systemUiPackageName == null) {
1712 throw new IllegalStateException("System UI package not found.");
1713 }
1714
1715 try {
1716 int systemUiUid = mContext
1717 .createContextAsUser(UserHandle.SYSTEM, /* flags= */ 0).getPackageManager()
1718 .getPackageUid(systemUiPackageName, PackageManager.MATCH_SYSTEM_ONLY);
1719 int callerUid = Binder.getCallingUid();
1720 if (systemUiUid != callerUid) {
1721 throw new SecurityException("Invalid caller. Only" + systemUiPackageName
1722 + " is allowed to make this call");
1723 }
1724 } catch (NameNotFoundException e) {
1725 throw new IllegalStateException("Package " + systemUiPackageName + " not found.");
1726 }
1727
Mayank Garg587f1942020-05-06 01:41:34 -07001728 mUserSwitchUiReceiver = receiver;
1729 }
1730
Mayank Garga480dd92020-05-14 03:14:57 -07001731 // TODO(157082995): This information can be taken from
1732 // PackageManageInternalImpl.getSystemUiServiceComponent
1733 @Nullable
1734 private String getSystemUiPackageName() {
1735 try {
1736 ComponentName componentName = ComponentName.unflattenFromString(mContext.getResources()
1737 .getString(com.android.internal.R.string.config_systemUIServiceComponent));
1738 return componentName.getPackageName();
1739 } catch (RuntimeException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001740 Slog.w(TAG, "error while getting system UI package name.", e);
Mayank Garga480dd92020-05-14 03:14:57 -07001741 return null;
1742 }
1743 }
1744
Keun young Park13a7a822019-04-04 15:53:08 -07001745 private void updateDefaultUserRestriction() {
1746 // We want to set restrictions on system and guest users only once. These are persisted
1747 // onto disk, so it's sufficient to do it once + we minimize the number of disk writes.
1748 if (Settings.Global.getInt(mContext.getContentResolver(),
Eric Jeong1545f3b2019-09-16 13:56:52 -07001749 CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, /* default= */ 0) != 0) {
1750 return;
Keun young Park13a7a822019-04-04 15:53:08 -07001751 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07001752 // Only apply the system user restrictions if the system user is headless.
1753 if (UserManager.isHeadlessSystemUserMode()) {
1754 setSystemUserRestrictions();
1755 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07001756 Settings.Global.putInt(mContext.getContentResolver(),
1757 CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, 1);
Keun young Park13a7a822019-04-04 15:53:08 -07001758 }
1759
Eric Jeong1545f3b2019-09-16 13:56:52 -07001760 private boolean isPersistentUser(@UserIdInt int userId) {
Anthony Hugh9932a252019-06-12 16:19:56 -07001761 return !mUserManager.getUserInfo(userId).isEphemeral();
1762 }
1763
Antonio Kantekc8114752020-03-05 21:37:39 -08001764 /**
Antonio Kantekc8114752020-03-05 21:37:39 -08001765 * Adds a new {@link UserLifecycleListener} to listen to user activity events.
1766 */
1767 public void addUserLifecycleListener(@NonNull UserLifecycleListener listener) {
1768 Objects.requireNonNull(listener, "listener cannot be null");
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001769 mHandler.post(() -> mUserLifecycleListeners.add(listener));
Antonio Kantekc8114752020-03-05 21:37:39 -08001770 }
1771
1772 /**
1773 * Removes previously added {@link UserLifecycleListener}.
1774 */
1775 public void removeUserLifecycleListener(@NonNull UserLifecycleListener listener) {
1776 Objects.requireNonNull(listener, "listener cannot be null");
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001777 mHandler.post(() -> mUserLifecycleListeners.remove(listener));
Antonio Kantekc8114752020-03-05 21:37:39 -08001778 }
1779
Eric Jeongc91f9452019-08-30 15:04:21 -07001780 /** Adds callback to listen to passenger activity events. */
1781 public void addPassengerCallback(@NonNull PassengerCallback callback) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00001782 Objects.requireNonNull(callback, "callback cannot be null");
Eric Jeongc91f9452019-08-30 15:04:21 -07001783 mPassengerCallbacks.add(callback);
1784 }
1785
1786 /** Removes previously added callback to listen passenger events. */
1787 public void removePassengerCallback(@NonNull PassengerCallback callback) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00001788 Objects.requireNonNull(callback, "callback cannot be null");
Eric Jeongc91f9452019-08-30 15:04:21 -07001789 mPassengerCallbacks.remove(callback);
1790 }
1791
1792 /** Sets the implementation of ZoneUserBindingHelper. */
1793 public void setZoneUserBindingHelper(@NonNull ZoneUserBindingHelper helper) {
1794 synchronized (mLockHelper) {
1795 mZoneUserBindingHelper = helper;
1796 }
1797 }
1798
felipeal98900c82020-04-09 09:05:02 -07001799 private void onUserUnlocked(@UserIdInt int userId) {
Keun-young Parkd462a912019-02-11 08:53:42 -08001800 ArrayList<Runnable> tasks = null;
Eric Jeongc91f9452019-08-30 15:04:21 -07001801 synchronized (mLockUser) {
Mayank Garg7a114c82020-04-08 21:25:06 -07001802 sendPostSwitchToHalLocked(userId);
Eric Jeong1545f3b2019-09-16 13:56:52 -07001803 if (userId == UserHandle.USER_SYSTEM) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001804 if (!mUser0Unlocked) { // user 0, unlocked, do this only once
1805 updateDefaultUserRestriction();
1806 tasks = new ArrayList<>(mUser0UnlockTasks);
1807 mUser0UnlockTasks.clear();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001808 mUser0Unlocked = true;
Keun young Parkf3523cd2019-04-08 10:09:17 -07001809 }
1810 } else { // none user0
Eric Jeong1545f3b2019-09-16 13:56:52 -07001811 Integer user = userId;
1812 if (isPersistentUser(userId)) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001813 // current foreground user should stay in top priority.
Anthony Hughfbb67762019-10-15 12:54:54 -07001814 if (userId == ActivityManager.getCurrentUser()) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001815 mBackgroundUsersToRestart.remove(user);
1816 mBackgroundUsersToRestart.add(0, user);
1817 }
1818 // -1 for user 0
1819 if (mBackgroundUsersToRestart.size() > (mMaxRunningUsers - 1)) {
Eric Jeong1545f3b2019-09-16 13:56:52 -07001820 int userToDrop = mBackgroundUsersToRestart.get(
Keun young Parkf3523cd2019-04-08 10:09:17 -07001821 mBackgroundUsersToRestart.size() - 1);
Eric Jeongf75d4132020-12-21 13:48:23 -08001822 Slog.i(TAG, "New user unlocked:" + userId
Keun young Parkf3523cd2019-04-08 10:09:17 -07001823 + ", dropping least recently user from restart list:" + userToDrop);
1824 // Drop the least recently used user.
1825 mBackgroundUsersToRestart.remove(mBackgroundUsersToRestart.size() - 1);
1826 }
1827 }
Keun-young Parkd462a912019-02-11 08:53:42 -08001828 }
1829 }
1830 if (tasks != null && tasks.size() > 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001831 Slog.d(TAG, "User0 unlocked, run queued tasks:" + tasks.size());
Keun-young Parkd462a912019-02-11 08:53:42 -08001832 for (Runnable r : tasks) {
1833 r.run();
1834 }
1835 }
1836 }
1837
1838 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -07001839 * Starts all background users that were active in system.
1840 *
Keun young Parkfb656372019-03-12 18:37:55 -07001841 * @return list of background users started successfully.
1842 */
Eric Jeong1545f3b2019-09-16 13:56:52 -07001843 @NonNull
Keun young Parkfb656372019-03-12 18:37:55 -07001844 public ArrayList<Integer> startAllBackgroundUsers() {
1845 ArrayList<Integer> users;
Eric Jeongc91f9452019-08-30 15:04:21 -07001846 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001847 users = new ArrayList<>(mBackgroundUsersToRestart);
1848 mBackgroundUsersRestartedHere.clear();
1849 mBackgroundUsersRestartedHere.addAll(mBackgroundUsersToRestart);
Keun young Parkfb656372019-03-12 18:37:55 -07001850 }
1851 ArrayList<Integer> startedUsers = new ArrayList<>();
1852 for (Integer user : users) {
Anthony Hughfbb67762019-10-15 12:54:54 -07001853 if (user == ActivityManager.getCurrentUser()) {
Keun young Parkfb656372019-03-12 18:37:55 -07001854 continue;
1855 }
1856 try {
1857 if (mAm.startUserInBackground(user)) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001858 if (mUserManager.isUserUnlockingOrUnlocked(user)) {
1859 // already unlocked / unlocking. No need to unlock.
Keun young Parkfb656372019-03-12 18:37:55 -07001860 startedUsers.add(user);
Keun young Parkf3523cd2019-04-08 10:09:17 -07001861 } else if (mAm.unlockUser(user, null, null, null)) {
1862 startedUsers.add(user);
1863 } else { // started but cannot unlock
Eric Jeongf75d4132020-12-21 13:48:23 -08001864 Slog.w(TAG, "Background user started but cannot be unlocked:" + user);
Keun young Parkf3523cd2019-04-08 10:09:17 -07001865 if (mUserManager.isUserRunning(user)) {
1866 // add to started list so that it can be stopped later.
1867 startedUsers.add(user);
1868 }
Keun young Parkfb656372019-03-12 18:37:55 -07001869 }
1870 }
1871 } catch (RemoteException e) {
1872 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001873 Slog.w(TAG, "error while starting user in background", e);
Keun young Parkfb656372019-03-12 18:37:55 -07001874 }
1875 }
Keun young Parkf3523cd2019-04-08 10:09:17 -07001876 // Keep only users that were re-started in mBackgroundUsersRestartedHere
Eric Jeongc91f9452019-08-30 15:04:21 -07001877 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001878 ArrayList<Integer> usersToRemove = new ArrayList<>();
1879 for (Integer user : mBackgroundUsersToRestart) {
1880 if (!startedUsers.contains(user)) {
1881 usersToRemove.add(user);
1882 }
1883 }
1884 mBackgroundUsersRestartedHere.removeAll(usersToRemove);
1885 }
Keun young Parkfb656372019-03-12 18:37:55 -07001886 return startedUsers;
1887 }
1888
1889 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -07001890 * Stops all background users that were active in system.
1891 *
1892 * @return whether stopping succeeds.
Keun young Parkfb656372019-03-12 18:37:55 -07001893 */
Eric Jeong1545f3b2019-09-16 13:56:52 -07001894 public boolean stopBackgroundUser(@UserIdInt int userId) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001895 if (userId == UserHandle.USER_SYSTEM) {
1896 return false;
1897 }
Anthony Hughfbb67762019-10-15 12:54:54 -07001898 if (userId == ActivityManager.getCurrentUser()) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001899 Slog.i(TAG, "stopBackgroundUser, already a FG user:" + userId);
Keun young Parkfb656372019-03-12 18:37:55 -07001900 return false;
1901 }
1902 try {
Keun young Parked9e6282019-09-19 17:38:26 -07001903 int r = mAm.stopUserWithDelayedLocking(userId, true, null);
Keun young Parkf3523cd2019-04-08 10:09:17 -07001904 if (r == ActivityManager.USER_OP_SUCCESS) {
Eric Jeongc91f9452019-08-30 15:04:21 -07001905 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001906 Integer user = userId;
1907 mBackgroundUsersRestartedHere.remove(user);
1908 }
1909 } else if (r == ActivityManager.USER_OP_IS_CURRENT) {
1910 return false;
1911 } else {
Eric Jeongf75d4132020-12-21 13:48:23 -08001912 Slog.i(TAG, "stopBackgroundUser failed, user:" + userId + " err:" + r);
Keun young Parkfb656372019-03-12 18:37:55 -07001913 return false;
1914 }
1915 } catch (RemoteException e) {
1916 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001917 Slog.w(TAG, "error while stopping user", e);
Keun young Parkfb656372019-03-12 18:37:55 -07001918 }
1919 return true;
1920 }
1921
1922 /**
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001923 * Notifies all registered {@link UserLifecycleListener} with the event passed as argument.
Pavel Maltsev17e81832019-04-04 14:38:41 -07001924 */
Mayank Gargccad8062020-08-30 15:05:10 -07001925 public void onUserLifecycleEvent(@UserLifecycleEventType int eventType,
felipeale8c5dce2020-04-15 11:27:06 -07001926 @UserIdInt int fromUserId, @UserIdInt int toUserId) {
1927 int userId = toUserId;
felipeal98900c82020-04-09 09:05:02 -07001928
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001929 // Handle special cases first...
felipeal98900c82020-04-09 09:05:02 -07001930 if (eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING) {
Mayank Garge5de0f92020-04-23 21:38:38 -07001931 onUserSwitching(fromUserId, toUserId);
felipeal98900c82020-04-09 09:05:02 -07001932 } else if (eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_UNLOCKED) {
1933 onUserUnlocked(userId);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001934 }
1935
felipeale8c5dce2020-04-15 11:27:06 -07001936 // ...then notify listeners.
Yan Zhue7921522020-04-16 15:59:25 -07001937 UserLifecycleEvent event = new UserLifecycleEvent(eventType, fromUserId, userId);
felipeale8c5dce2020-04-15 11:27:06 -07001938
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001939 mHandler.post(() -> {
1940 handleNotifyServiceUserLifecycleListeners(event);
1941 handleNotifyAppUserLifecycleListeners(event);
1942 });
felipeale8c5dce2020-04-15 11:27:06 -07001943 }
1944
Mayank Garg7a114c82020-04-08 21:25:06 -07001945 private void sendPostSwitchToHalLocked(@UserIdInt int userId) {
felipealf7368962020-04-16 12:55:19 -07001946 if (mUserIdForUserSwitchInProcess == UserHandle.USER_NULL
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001947 || mUserIdForUserSwitchInProcess != userId
1948 || mRequestIdForUserSwitchInProcess == 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001949 if (Log.isLoggable(TAG, Log.DEBUG)) {
1950 Slog.d(TAG, "No user switch request Id. No android post switch sent.");
Mayank Garg7a114c82020-04-08 21:25:06 -07001951 }
1952 return;
1953 }
felipealf7368962020-04-16 12:55:19 -07001954 postSwitchHalResponse(mRequestIdForUserSwitchInProcess, mUserIdForUserSwitchInProcess);
1955 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001956 mRequestIdForUserSwitchInProcess = 0;
Mayank Garg7a114c82020-04-08 21:25:06 -07001957 }
1958
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001959 private void handleNotifyAppUserLifecycleListeners(UserLifecycleEvent event) {
1960 int listenersSize = mAppLifecycleListeners.size();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001961 if (listenersSize == 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001962 if (Log.isLoggable(TAG, Log.DEBUG)) {
1963 Slog.d(TAG, "No app listener to be notified of " + event);
felipeal2a84d512020-04-06 18:52:15 -07001964 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001965 return;
1966 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001967 // Must use a different TimingsTraceLog because it's another thread
Eric Jeongf75d4132020-12-21 13:48:23 -08001968 if (Log.isLoggable(TAG, Log.DEBUG)) {
1969 Slog.d(TAG, "Notifying " + listenersSize + " app listeners of " + event);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001970 }
felipeal2a84d512020-04-06 18:52:15 -07001971 int userId = event.getUserId();
Eric Jeongf75d4132020-12-21 13:48:23 -08001972 TimingsTraceLog t = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
felipealde1e16d2020-06-03 13:20:48 -07001973 int eventType = event.getEventType();
1974 t.traceBegin("notify-app-listeners-user-" + userId + "-event-" + eventType);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001975 for (int i = 0; i < listenersSize; i++) {
1976 int uid = mAppLifecycleListeners.keyAt(i);
felipealde1e16d2020-06-03 13:20:48 -07001977
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001978 IResultReceiver listener = mAppLifecycleListeners.valueAt(i);
1979 Bundle data = new Bundle();
felipealde1e16d2020-06-03 13:20:48 -07001980 data.putInt(CarUserManager.BUNDLE_PARAM_ACTION, eventType);
Yan Zhue7921522020-04-16 15:59:25 -07001981
felipealde1e16d2020-06-03 13:20:48 -07001982 int fromUserId = event.getPreviousUserId();
1983 if (fromUserId != UserHandle.USER_NULL) {
1984 data.putInt(CarUserManager.BUNDLE_PARAM_PREVIOUS_USER_ID, fromUserId);
Yan Zhue7921522020-04-16 15:59:25 -07001985 }
1986
Eric Jeongf75d4132020-12-21 13:48:23 -08001987 if (Log.isLoggable(TAG, Log.DEBUG)) {
1988 Slog.d(TAG, "Notifying listener for uid " + uid);
felipeal2a84d512020-04-06 18:52:15 -07001989 }
felipealde1e16d2020-06-03 13:20:48 -07001990 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_NOTIFY_APP_LIFECYCLE_LISTENER,
1991 uid, eventType, fromUserId, userId);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001992 try {
felipealde1e16d2020-06-03 13:20:48 -07001993 t.traceBegin("notify-app-listener-uid-" + uid);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001994 listener.send(userId, data);
1995 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001996 Slog.e(TAG, "Error calling lifecycle listener", e);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001997 } finally {
1998 t.traceEnd();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001999 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002000 }
2001 t.traceEnd(); // notify-app-listeners-user-USERID-event-EVENT_TYPE
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002002 }
2003
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002004 private void handleNotifyServiceUserLifecycleListeners(UserLifecycleEvent event) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002005 TimingsTraceLog t = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002006 if (mUserLifecycleListeners.isEmpty()) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002007 Slog.w(TAG, "Not notifying internal UserLifecycleListeners");
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002008 return;
Eric Jeongf75d4132020-12-21 13:48:23 -08002009 } else if (Log.isLoggable(TAG, Log.DEBUG)) {
2010 Slog.d(TAG, "Notifying " + mUserLifecycleListeners.size()
2011 + " service listeners of " + event);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002012 }
felipeal2a84d512020-04-06 18:52:15 -07002013
felipealde1e16d2020-06-03 13:20:48 -07002014 int userId = event.getUserId();
2015 int eventType = event.getEventType();
2016 t.traceBegin("notify-listeners-user-" + userId + "-event-" + eventType);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002017 for (UserLifecycleListener listener : mUserLifecycleListeners) {
felipeal2a84d512020-04-06 18:52:15 -07002018 String listenerName = FunctionalUtils.getLambdaName(listener);
felipealde1e16d2020-06-03 13:20:48 -07002019 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_NOTIFY_INTERNAL_LIFECYCLE_LISTENER,
2020 listenerName, eventType, event.getPreviousUserId(), userId);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002021 try {
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002022 t.traceBegin("notify-listener-" + listenerName);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002023 listener.onEvent(event);
2024 } catch (RuntimeException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002025 Slog.e(TAG,
felipeal2a84d512020-04-06 18:52:15 -07002026 "Exception raised when invoking onEvent for " + listenerName, e);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002027 } finally {
2028 t.traceEnd();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002029 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002030 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002031 t.traceEnd(); // notify-listeners-user-USERID-event-EVENT_TYPE
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002032 }
2033
Mayank Garge5de0f92020-04-23 21:38:38 -07002034 private void onUserSwitching(@UserIdInt int fromUserId, @UserIdInt int toUserId) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002035 Slog.i(TAG, "onUserSwitching() callback for user " + toUserId);
2036 TimingsTraceLog t = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
Mayank Garge5de0f92020-04-23 21:38:38 -07002037 t.traceBegin("onUserSwitching-" + toUserId);
Felipe Leme5528ff72020-02-10 19:05:14 -08002038
Mayank Garge5de0f92020-04-23 21:38:38 -07002039 // Switch HAL users if user switch is not requested by CarUserService
2040 notifyHalLegacySwitch(fromUserId, toUserId);
2041
Mayank Garge90a4082020-09-30 12:57:34 -07002042 mInitialUserSetter.setLastActiveUser(toUserId);
felipealbf327652020-06-03 11:33:29 -07002043
Eric Jeongc91f9452019-08-30 15:04:21 -07002044 if (mLastPassengerId != UserHandle.USER_NULL) {
2045 stopPassengerInternal(mLastPassengerId, false);
2046 }
2047 if (mEnablePassengerSupport && isPassengerDisplayAvailable()) {
2048 setupPassengerUser();
Mayank Garge5de0f92020-04-23 21:38:38 -07002049 startFirstPassenger(toUserId);
Eric Jeongc91f9452019-08-30 15:04:21 -07002050 }
felipeal98900c82020-04-09 09:05:02 -07002051 t.traceEnd();
Pavel Maltsev17e81832019-04-04 14:38:41 -07002052 }
2053
Mayank Garge5de0f92020-04-23 21:38:38 -07002054 private void notifyHalLegacySwitch(@UserIdInt int fromUserId, @UserIdInt int toUserId) {
2055 synchronized (mLockUser) {
felipeal7d12ee22020-06-05 09:30:19 -07002056 if (mUserIdForUserSwitchInProcess != UserHandle.USER_NULL) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002057 if (Log.isLoggable(TAG, Log.DEBUG)) {
2058 Slog.d(TAG, "notifyHalLegacySwitch(" + fromUserId + ", " + toUserId
felipeal7d12ee22020-06-05 09:30:19 -07002059 + "): not needed, normal switch for " + mUserIdForUserSwitchInProcess);
2060 }
2061 return;
2062 }
Mayank Garge5de0f92020-04-23 21:38:38 -07002063 }
2064
Mayank Garg9ed099e2020-06-04 16:05:20 -07002065 if (!isUserHalSupported()) return;
2066
Mayank Garge5de0f92020-04-23 21:38:38 -07002067 // switch HAL user
felipeal7d12ee22020-06-05 09:30:19 -07002068 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager, fromUserId);
Mayank Gargeb37d092020-06-02 14:37:57 -07002069 SwitchUserRequest request = createUserSwitchRequest(toUserId, usersInfo);
2070 mHal.legacyUserSwitch(request);
Mayank Garge5de0f92020-04-23 21:38:38 -07002071 }
2072
Pavel Maltsev17e81832019-04-04 14:38:41 -07002073 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -07002074 * 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 -08002075 * run inside this call.
Eric Jeong1545f3b2019-09-16 13:56:52 -07002076 *
Keun-young Parkd462a912019-02-11 08:53:42 -08002077 * @param r Runnable to run.
2078 */
Eric Jeong1545f3b2019-09-16 13:56:52 -07002079 public void runOnUser0Unlock(@NonNull Runnable r) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00002080 Objects.requireNonNull(r, "runnable cannot be null");
Keun-young Parkd462a912019-02-11 08:53:42 -08002081 boolean runNow = false;
Eric Jeongc91f9452019-08-30 15:04:21 -07002082 synchronized (mLockUser) {
Keun-young Parkd462a912019-02-11 08:53:42 -08002083 if (mUser0Unlocked) {
2084 runNow = true;
2085 } else {
2086 mUser0UnlockTasks.add(r);
2087 }
2088 }
2089 if (runNow) {
2090 r.run();
2091 }
2092 }
2093
Keun young Parkf3523cd2019-04-08 10:09:17 -07002094 @VisibleForTesting
Eric Jeong1545f3b2019-09-16 13:56:52 -07002095 @NonNull
2096 ArrayList<Integer> getBackgroundUsersToRestart() {
2097 ArrayList<Integer> backgroundUsersToRestart = null;
Eric Jeongc91f9452019-08-30 15:04:21 -07002098 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07002099 backgroundUsersToRestart = new ArrayList<>(mBackgroundUsersToRestart);
2100 }
2101 return backgroundUsersToRestart;
2102 }
2103
Ying Zheng1ab32b62018-06-26 12:47:26 -07002104 private void setSystemUserRestrictions() {
Ying Zheng1ab32b62018-06-26 12:47:26 -07002105 // Disable Location service for system user.
2106 LocationManager locationManager =
2107 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
Anthony Hugh04ee04f2019-12-17 16:11:33 -08002108 locationManager.setLocationEnabledForUser(
2109 /* enabled= */ false, UserHandle.of(UserHandle.USER_SYSTEM));
Ying Zheng1ab32b62018-06-26 12:47:26 -07002110 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07002111
2112 /**
Anthony Hugh6fed1e92019-10-22 16:22:03 -07002113 * Assigns a default icon to a user according to the user's id.
2114 *
2115 * @param userInfo User whose avatar is set to default icon.
Anthony Hugh6fed1e92019-10-22 16:22:03 -07002116 */
Eric Jeongb2dc6ff2020-06-05 17:00:26 -07002117 private void assignDefaultIcon(UserInfo userInfo) {
Anthony Hugh6fed1e92019-10-22 16:22:03 -07002118 int idForIcon = userInfo.isGuest() ? UserHandle.USER_NULL : userInfo.id;
2119 Bitmap bitmap = UserIcons.convertToBitmap(
2120 UserIcons.getDefaultUserIcon(mContext.getResources(), idForIcon, false));
2121 mUserManager.setUserIcon(userInfo.id, bitmap);
Anthony Hugh6fed1e92019-10-22 16:22:03 -07002122 }
2123
Eric Jeong1545f3b2019-09-16 13:56:52 -07002124 private interface UserFilter {
2125 boolean isEligibleUser(UserInfo user);
2126 }
2127
2128 /** Returns all users who are matched by the given filter. */
2129 private List<UserInfo> getUsers(UserFilter filter) {
Colin Cross0df71ea2020-08-27 04:12:26 +00002130 List<UserInfo> users = mUserManager.getAliveUsers();
Eric Jeong1545f3b2019-09-16 13:56:52 -07002131
2132 for (Iterator<UserInfo> iterator = users.iterator(); iterator.hasNext(); ) {
2133 UserInfo user = iterator.next();
2134 if (!filter.isEligibleUser(user)) {
2135 iterator.remove();
2136 }
2137 }
2138 return users;
2139 }
2140
felipeal2d0483c2019-11-02 14:07:22 -07002141 private static void checkManageUsersOrDumpPermission(String message) {
Felipe Leme55236722020-10-16 16:54:32 -07002142 checkHasAtLeastOnePermissionGranted(message,
felipeal2d0483c2019-11-02 14:07:22 -07002143 android.Manifest.permission.MANAGE_USERS,
2144 android.Manifest.permission.DUMP);
2145 }
2146
Felipe Leme5528ff72020-02-10 19:05:14 -08002147 private void checkInteractAcrossUsersPermission(String message) {
Felipe Leme55236722020-10-16 16:54:32 -07002148 checkHasAtLeastOnePermissionGranted(message,
2149 android.Manifest.permission.INTERACT_ACROSS_USERS,
Felipe Leme5528ff72020-02-10 19:05:14 -08002150 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
2151 }
2152
Eric Jeongc91f9452019-08-30 15:04:21 -07002153 private int getNumberOfManagedProfiles(@UserIdInt int userId) {
Colin Cross0df71ea2020-08-27 04:12:26 +00002154 List<UserInfo> users = mUserManager.getAliveUsers();
Eric Jeongc91f9452019-08-30 15:04:21 -07002155 // Count all users that are managed profiles of the given user.
2156 int managedProfilesCount = 0;
2157 for (UserInfo user : users) {
2158 if (user.isManagedProfile() && user.profileGroupId == userId) {
2159 managedProfilesCount++;
2160 }
2161 }
2162 return managedProfilesCount;
2163 }
2164
2165 /**
2166 * Starts the first passenger of the given driver and assigns the passenger to the front
2167 * passenger zone.
2168 *
2169 * @param driverId User id of the driver.
2170 * @return whether it succeeds.
2171 */
2172 private boolean startFirstPassenger(@UserIdInt int driverId) {
2173 int zoneId = getAvailablePassengerZone();
2174 if (zoneId == OccupantZoneInfo.INVALID_ZONE_ID) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002175 Slog.w(TAG, "passenger occupant zone is not found");
Eric Jeongc91f9452019-08-30 15:04:21 -07002176 return false;
2177 }
2178 List<UserInfo> passengers = getPassengers(driverId);
2179 if (passengers.size() < 1) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002180 Slog.w(TAG, "passenger is not found");
Eric Jeongc91f9452019-08-30 15:04:21 -07002181 return false;
2182 }
2183 // Only one passenger is supported. If there are two or more passengers, the first passenger
2184 // is chosen.
2185 int passengerId = passengers.get(0).id;
2186 if (!startPassenger(passengerId, zoneId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002187 Slog.w(TAG, "cannot start passenger " + passengerId);
Eric Jeongc91f9452019-08-30 15:04:21 -07002188 return false;
2189 }
2190 return true;
2191 }
2192
2193 private int getAvailablePassengerZone() {
2194 int[] occupantTypes = new int[] {CarOccupantZoneManager.OCCUPANT_TYPE_FRONT_PASSENGER,
2195 CarOccupantZoneManager.OCCUPANT_TYPE_REAR_PASSENGER};
2196 for (int occupantType : occupantTypes) {
2197 int zoneId = getZoneId(occupantType);
2198 if (zoneId != OccupantZoneInfo.INVALID_ZONE_ID) {
2199 return zoneId;
2200 }
2201 }
2202 return OccupantZoneInfo.INVALID_ZONE_ID;
2203 }
2204
2205 /**
2206 * Creates a new passenger user when there is no passenger user.
2207 */
2208 private void setupPassengerUser() {
2209 int currentUser = ActivityManager.getCurrentUser();
2210 int profileCount = getNumberOfManagedProfiles(currentUser);
2211 if (profileCount > 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002212 Slog.w(TAG, "max profile of user" + currentUser
Eric Jeongc91f9452019-08-30 15:04:21 -07002213 + " is exceeded: current profile count is " + profileCount);
2214 return;
2215 }
2216 // TODO(b/140311342): Use resource string for the default passenger name.
2217 UserInfo passenger = createPassenger("Passenger", currentUser);
2218 if (passenger == null) {
2219 // Couldn't create user, most likely because there are too many.
Eric Jeongf75d4132020-12-21 13:48:23 -08002220 Slog.w(TAG, "cannot create a passenger user");
Eric Jeongc91f9452019-08-30 15:04:21 -07002221 return;
2222 }
2223 }
2224
2225 @NonNull
2226 private List<OccupantZoneInfo> getOccupantZones(@OccupantTypeEnum int occupantType) {
2227 ZoneUserBindingHelper helper = null;
2228 synchronized (mLockHelper) {
2229 if (mZoneUserBindingHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002230 Slog.w(TAG, "implementation is not delegated");
Eric Jeongc91f9452019-08-30 15:04:21 -07002231 return new ArrayList<OccupantZoneInfo>();
2232 }
2233 helper = mZoneUserBindingHelper;
2234 }
2235 return helper.getOccupantZones(occupantType);
2236 }
2237
2238 private boolean assignUserToOccupantZone(@UserIdInt int userId, int zoneId) {
2239 ZoneUserBindingHelper helper = null;
2240 synchronized (mLockHelper) {
2241 if (mZoneUserBindingHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002242 Slog.w(TAG, "implementation is not delegated");
Eric Jeongc91f9452019-08-30 15:04:21 -07002243 return false;
2244 }
2245 helper = mZoneUserBindingHelper;
2246 }
2247 return helper.assignUserToOccupantZone(userId, zoneId);
2248 }
2249
2250 private boolean unassignUserFromOccupantZone(@UserIdInt int userId) {
2251 ZoneUserBindingHelper helper = null;
2252 synchronized (mLockHelper) {
2253 if (mZoneUserBindingHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002254 Slog.w(TAG, "implementation is not delegated");
Eric Jeongc91f9452019-08-30 15:04:21 -07002255 return false;
2256 }
2257 helper = mZoneUserBindingHelper;
2258 }
2259 return helper.unassignUserFromOccupantZone(userId);
2260 }
2261
2262 private boolean isPassengerDisplayAvailable() {
2263 ZoneUserBindingHelper helper = null;
2264 synchronized (mLockHelper) {
2265 if (mZoneUserBindingHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002266 Slog.w(TAG, "implementation is not delegated");
Eric Jeongc91f9452019-08-30 15:04:21 -07002267 return false;
2268 }
2269 helper = mZoneUserBindingHelper;
2270 }
2271 return helper.isPassengerDisplayAvailable();
2272 }
2273
2274 /**
2275 * Gets the zone id of the given occupant type. If there are two or more zones, the first found
2276 * zone is returned.
2277 *
2278 * @param occupantType The type of an occupant.
2279 * @return The zone id of the given occupant type. {@link OccupantZoneInfo.INVALID_ZONE_ID},
2280 * if not found.
2281 */
2282 private int getZoneId(@OccupantTypeEnum int occupantType) {
2283 List<OccupantZoneInfo> zoneInfos = getOccupantZones(occupantType);
2284 return (zoneInfos.size() > 0) ? zoneInfos.get(0).zoneId : OccupantZoneInfo.INVALID_ZONE_ID;
2285 }
Mayank Garg9732d602020-08-09 21:02:40 -07002286
2287 /**
2288 * Manages the required number of pre-created users.
2289 */
Mayank Garga3b72d02021-03-14 23:05:51 -07002290 @Override
2291 public void updatePreCreatedUsers() {
2292 checkManageOrCreateUsersPermission("preCreateUsers");
2293 preCreateUsersInternal();
Mayank Garg02576972021-02-18 16:46:07 -08002294 }
2295
Mayank Garga3b72d02021-03-14 23:05:51 -07002296 private void preCreateUsersInternal() {
2297 mHandler.post(() -> mUserPreCreator.managePreCreatedUsers());
Mayank Garg9732d602020-08-09 21:02:40 -07002298 }
Felipe Leme17799202020-09-03 12:55:53 -07002299
2300 // TODO(b/167698977): members below were copied from UserManagerService; it would be better to
2301 // move them to some internal android.os class instead.
2302
2303 private static final int ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION =
2304 UserInfo.FLAG_MANAGED_PROFILE
2305 | UserInfo.FLAG_PROFILE
2306 | UserInfo.FLAG_EPHEMERAL
2307 | UserInfo.FLAG_RESTRICTED
2308 | UserInfo.FLAG_GUEST
2309 | UserInfo.FLAG_DEMO
2310 | UserInfo.FLAG_FULL;
2311
2312 private static void checkManageUsersPermission(String message) {
2313 if (!hasManageUsersPermission()) {
2314 throw new SecurityException("You need " + MANAGE_USERS + " permission to: " + message);
2315 }
2316 }
2317
2318 private static void checkManageOrCreateUsersPermission(String message) {
2319 if (!hasManageOrCreateUsersPermission()) {
2320 throw new SecurityException(
2321 "You either need " + MANAGE_USERS + " or " + CREATE_USERS + " permission to: "
2322 + message);
2323 }
2324 }
2325
2326 private static void checkManageOrCreateUsersPermission(int creationFlags) {
2327 if ((creationFlags & ~ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION) == 0) {
2328 if (!hasManageOrCreateUsersPermission()) {
2329 throw new SecurityException("You either need " + MANAGE_USERS + " or "
2330 + CREATE_USERS + "permission to create a user with flags "
2331 + creationFlags);
2332 }
2333 } else if (!hasManageUsersPermission()) {
2334 throw new SecurityException("You need " + MANAGE_USERS + " permission to create a user"
2335 + " with flags " + creationFlags);
2336 }
2337 }
2338
2339 private static boolean hasManageUsersPermission() {
2340 final int callingUid = Binder.getCallingUid();
2341 return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
2342 || callingUid == Process.ROOT_UID
2343 || hasPermissionGranted(MANAGE_USERS, callingUid);
2344 }
2345
2346 private static boolean hasManageUsersOrPermission(String alternativePermission) {
2347 final int callingUid = Binder.getCallingUid();
2348 return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
2349 || callingUid == Process.ROOT_UID
2350 || hasPermissionGranted(MANAGE_USERS, callingUid)
2351 || hasPermissionGranted(alternativePermission, callingUid);
2352 }
2353
2354 private static boolean hasManageOrCreateUsersPermission() {
2355 return hasManageUsersOrPermission(CREATE_USERS);
2356 }
2357
2358 private static boolean hasPermissionGranted(String permission, int uid) {
2359 return ActivityManager.checkComponentPermission(permission, uid, /* owningUid= */ -1,
2360 /* exported= */ true) == PackageManager.PERMISSION_GRANTED;
2361 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002362}