blob: bac388b0a16515edf9ca7e3c8a24beb2b1edc977 [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
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700155 private final Context mContext;
Keun young Parkfb656372019-03-12 18:37:55 -0700156 private final IActivityManager mAm;
Anthony Hugh9932a252019-06-12 16:19:56 -0700157 private final UserManager mUserManager;
158 private final int mMaxRunningUsers;
Mayank Garg70732a82020-08-05 20:17:47 -0700159 private final InitialUserSetter mInitialUserSetter;
Eric Jeongc91f9452019-08-30 15:04:21 -0700160 private final boolean mEnablePassengerSupport;
Mayank Garg9732d602020-08-09 21:02:40 -0700161 private final UserPreCreator mUserPreCreator;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700162
Eric Jeongc91f9452019-08-30 15:04:21 -0700163 private final Object mLockUser = new Object();
164 @GuardedBy("mLockUser")
Keun-young Parkd462a912019-02-11 08:53:42 -0800165 private boolean mUser0Unlocked;
Eric Jeongc91f9452019-08-30 15:04:21 -0700166 @GuardedBy("mLockUser")
Keun-young Parkd462a912019-02-11 08:53:42 -0800167 private final ArrayList<Runnable> mUser0UnlockTasks = new ArrayList<>();
Eric Jeongc91f9452019-08-30 15:04:21 -0700168 // Only one passenger is supported.
169 @GuardedBy("mLockUser")
170 private @UserIdInt int mLastPassengerId;
Keun young Parkf3523cd2019-04-08 10:09:17 -0700171 /**
172 * Background users that will be restarted in garage mode. This list can include the
Mayank Garg31e73042020-01-23 00:10:38 -0800173 * current foreground user but the current foreground user should not be restarted.
Keun young Parkf3523cd2019-04-08 10:09:17 -0700174 */
Eric Jeongc91f9452019-08-30 15:04:21 -0700175 @GuardedBy("mLockUser")
Keun young Parkf3523cd2019-04-08 10:09:17 -0700176 private final ArrayList<Integer> mBackgroundUsersToRestart = new ArrayList<>();
177 /**
178 * Keep the list of background users started here. This is wholly for debugging purpose.
179 */
Eric Jeongc91f9452019-08-30 15:04:21 -0700180 @GuardedBy("mLockUser")
Keun young Parkf3523cd2019-04-08 10:09:17 -0700181 private final ArrayList<Integer> mBackgroundUsersRestartedHere = new ArrayList<>();
182
Felipe Leme58412202020-01-09 13:45:33 -0800183 private final UserHalService mHal;
184
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700185 // HandlerThread and Handler used when notifying app listeners (mAppLifecycleListeners).
Keun young Parkb241d022020-04-20 20:31:34 -0700186 private final HandlerThread mHandlerThread = CarServiceUtils.getHandlerThread(
187 getClass().getSimpleName());
188 private final Handler mHandler = new Handler(mHandlerThread.getLooper());
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700189
Felipe Leme5528ff72020-02-10 19:05:14 -0800190 /**
Antonio Kantekc8114752020-03-05 21:37:39 -0800191 * List of listeners to be notified on new user activities events.
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700192 * This collection should be accessed and manipulated by mHandlerThread only.
Antonio Kantekc8114752020-03-05 21:37:39 -0800193 */
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700194 private final List<UserLifecycleListener> mUserLifecycleListeners = new ArrayList<>();
Antonio Kantekc8114752020-03-05 21:37:39 -0800195
196 /**
Felipe Leme5528ff72020-02-10 19:05:14 -0800197 * List of lifecycle listeners by uid.
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700198 * This collection should be accessed and manipulated by mHandlerThread only.
Felipe Leme5528ff72020-02-10 19:05:14 -0800199 */
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700200 private final SparseArray<IResultReceiver> mAppLifecycleListeners = new SparseArray<>();
Felipe Leme5528ff72020-02-10 19:05:14 -0800201
Mayank Garg7a114c82020-04-08 21:25:06 -0700202 /**
203 * User Id for the user switch in process, if any.
204 */
205 @GuardedBy("mLockUser")
felipealf7368962020-04-16 12:55:19 -0700206 private int mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
Mayank Garg7a114c82020-04-08 21:25:06 -0700207 /**
208 * Request Id for the user switch in process, if any.
209 */
210 @GuardedBy("mLockUser")
felipealf7368962020-04-16 12:55:19 -0700211 private int mRequestIdForUserSwitchInProcess;
Felipe Lemee3cab982020-03-12 11:39:29 -0700212 private final int mHalTimeoutMs = CarProperties.user_hal_timeout().orElse(5_000);
213
Eric Jeongc91f9452019-08-30 15:04:21 -0700214 private final CopyOnWriteArrayList<PassengerCallback> mPassengerCallbacks =
215 new CopyOnWriteArrayList<>();
216
Mayank Garg7e1450b2020-08-07 18:15:15 -0700217 // TODO(b/163566866): Use mSwitchGuestUserBeforeSleep for new create guest request
218 private final boolean mSwitchGuestUserBeforeSleep;
219
felipeal61ce3732020-04-03 11:01:00 -0700220 @Nullable
221 @GuardedBy("mLockUser")
222 private UserInfo mInitialUser;
223
Mayank Garg587f1942020-05-06 01:41:34 -0700224 private IResultReceiver mUserSwitchUiReceiver;
225
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800226 private final CarUxRestrictionsManagerService mCarUxRestrictionService;
227
228 /**
229 * Whether some operations - like user switch - are restricted by driving safety constraints.
230 */
231 @GuardedBy("mLockUser")
232 private boolean mUxRestricted;
233
234 /**
235 * Callback to notify {@code CarServiceHelper} about driving safety changes (through
236 * {@link ICarServiceHelper#setSafetyMode(boolean).
237 *
238 * <p>NOTE: in theory, that logic should belong to {@code CarDevicePolicyService}, but it's
239 * simpler to do it here (and that service already depends on this one).
240 */
241 @GuardedBy("mLockUser")
242 private ICarServiceHelper mICarServiceHelper;
243
244 private final ICarUxRestrictionsChangeListener mCarUxRestrictionsChangeListener =
245 new ICarUxRestrictionsChangeListener.Stub() {
246 @Override
247 public void onUxRestrictionsChanged(CarUxRestrictions restrictions) {
248 setUxRestrictions(restrictions);
249 }
250 };
Felipe Leme5d5ab142020-10-27 13:49:10 -0700251
Eric Jeongc91f9452019-08-30 15:04:21 -0700252 /** Interface for callbaks related to passenger activities. */
253 public interface PassengerCallback {
254 /** Called when passenger is started at a certain zone. */
255 void onPassengerStarted(@UserIdInt int passengerId, int zoneId);
256 /** Called when passenger is stopped. */
257 void onPassengerStopped(@UserIdInt int passengerId);
258 }
259
260 /** Interface for delegating zone-related implementation to CarOccupantZoneService. */
261 public interface ZoneUserBindingHelper {
262 /** Gets occupant zones corresponding to the occupant type. */
263 @NonNull
264 List<OccupantZoneInfo> getOccupantZones(@OccupantTypeEnum int occupantType);
265 /** Assigns the user to the occupant zone. */
266 boolean assignUserToOccupantZone(@UserIdInt int userId, int zoneId);
267 /** Makes the occupant zone unoccupied. */
268 boolean unassignUserFromOccupantZone(@UserIdInt int userId);
269 /** Returns whether there is a passenger display. */
270 boolean isPassengerDisplayAvailable();
271 }
272
273 private final Object mLockHelper = new Object();
274 @GuardedBy("mLockHelper")
275 private ZoneUserBindingHelper mZoneUserBindingHelper;
276
Felipe Leme6b34fc32020-10-26 15:49:17 -0700277 /** Map used to avoid calling UserHAL when a user was removed because HAL creation failed. */
278 @GuardedBy("mLockUser")
279 private final SparseBooleanArray mFailedToCreateUserIds = new SparseBooleanArray(1);
280
Felipe Leme58412202020-01-09 13:45:33 -0800281 public CarUserService(@NonNull Context context, @NonNull UserHalService hal,
Mayank Garge90a4082020-09-30 12:57:34 -0700282 @NonNull UserManager userManager,
Felipe Leme5d5ab142020-10-27 13:49:10 -0700283 @NonNull IActivityManager am, int maxRunningUsers,
284 @NonNull CarUxRestrictionsManagerService uxRestrictionService) {
Mayank Garge90a4082020-09-30 12:57:34 -0700285 this(context, hal, userManager, am, maxRunningUsers,
Felipe Leme5d5ab142020-10-27 13:49:10 -0700286 /* initialUserSetter= */ null, /* userPreCreator= */ null, uxRestrictionService);
Mayank Garg71661ea2020-04-29 01:25:03 -0700287 }
288
289 @VisibleForTesting
290 CarUserService(@NonNull Context context, @NonNull UserHalService hal,
Mayank Garge90a4082020-09-30 12:57:34 -0700291 @NonNull UserManager userManager,
Mayank Gargccad8062020-08-30 15:05:10 -0700292 @NonNull IActivityManager am, int maxRunningUsers,
Mayank Garg1bb1c382020-09-03 17:11:11 -0700293 @Nullable InitialUserSetter initialUserSetter,
Felipe Leme5d5ab142020-10-27 13:49:10 -0700294 @Nullable UserPreCreator userPreCreator,
295 @NonNull CarUxRestrictionsManagerService uxRestrictionService) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800296 if (Log.isLoggable(TAG, Log.DEBUG)) {
Felipe Leme8725a2f2020-12-09 16:04:51 -0800297 Slog.d(TAG, "constructed for user " + context.getUserId());
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700298 }
299 mContext = context;
Felipe Leme58412202020-01-09 13:45:33 -0800300 mHal = hal;
Keun young Parkf3523cd2019-04-08 10:09:17 -0700301 mAm = am;
302 mMaxRunningUsers = maxRunningUsers;
Anthony Hugh9932a252019-06-12 16:19:56 -0700303 mUserManager = userManager;
Eric Jeongc91f9452019-08-30 15:04:21 -0700304 mLastPassengerId = UserHandle.USER_NULL;
Mayank Garg1bb1c382020-09-03 17:11:11 -0700305 mInitialUserSetter =
Felipe Lemecceb2992020-11-18 18:22:44 -0800306 initialUserSetter == null ? new InitialUserSetter(context, this,
307 (u) -> setInitialUser(u)) : initialUserSetter;
Mayank Garg1bb1c382020-09-03 17:11:11 -0700308 mUserPreCreator =
309 userPreCreator == null ? new UserPreCreator(mUserManager) : userPreCreator;
Mayank Garg7e1450b2020-08-07 18:15:15 -0700310 Resources resources = context.getResources();
311 mEnablePassengerSupport = resources.getBoolean(R.bool.enablePassengerSupport);
312 mSwitchGuestUserBeforeSleep = resources.getBoolean(
313 R.bool.config_switchGuestUserBeforeGoingSleep);
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800314 mCarUxRestrictionService = uxRestrictionService;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700315 }
316
317 @Override
318 public void init() {
Eric Jeongf75d4132020-12-21 13:48:23 -0800319 if (Log.isLoggable(TAG, Log.DEBUG)) {
320 Slog.d(TAG, "init()");
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700321 }
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800322 mCarUxRestrictionService.registerUxRestrictionsChangeListener(
323 mCarUxRestrictionsChangeListener, Display.DEFAULT_DISPLAY);
324
325 setUxRestrictions(mCarUxRestrictionService.getCurrentUxRestrictions());
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700326 }
327
328 @Override
329 public void release() {
Eric Jeongf75d4132020-12-21 13:48:23 -0800330 if (Log.isLoggable(TAG, Log.DEBUG)) {
331 Slog.d(TAG, "release()");
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700332 }
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800333 mCarUxRestrictionService
334 .unregisterUxRestrictionsChangeListener(mCarUxRestrictionsChangeListener);
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700335 }
336
337 @Override
Felipe Leme176a5fd2021-01-20 15:48:33 -0800338 public void dump(@NonNull IndentingPrintWriter writer) {
Felipe Leme55236722020-10-16 16:54:32 -0700339 checkHasDumpPermissionGranted("dump()");
340
Eric Jeong1545f3b2019-09-16 13:56:52 -0700341 writer.println("*CarUserService*");
Felipe Leme5528ff72020-02-10 19:05:14 -0800342 String indent = " ";
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700343 handleDumpListeners(writer, indent);
Mayank Garg587f1942020-05-06 01:41:34 -0700344 writer.printf("User switch UI receiver %s\n", mUserSwitchUiReceiver);
Eric Jeongc91f9452019-08-30 15:04:21 -0700345 synchronized (mLockUser) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700346 writer.println("User0Unlocked: " + mUser0Unlocked);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700347 writer.println("BackgroundUsersToRestart: " + mBackgroundUsersToRestart);
348 writer.println("BackgroundUsersRestarted: " + mBackgroundUsersRestartedHere);
Felipe Leme6b34fc32020-10-26 15:49:17 -0700349 if (mFailedToCreateUserIds.size() > 0) {
350 writer.println("FailedToCreateUserIds: " + mFailedToCreateUserIds);
351 }
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800352 writer.printf("Is UX restricted: %b\n", mUxRestricted);
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700353 }
354 writer.println("MaxRunningUsers: " + mMaxRunningUsers);
355 List<UserInfo> allDrivers = getAllDrivers();
356 int driversSize = allDrivers.size();
357 writer.println("NumberOfDrivers: " + driversSize);
358 for (int i = 0; i < driversSize; i++) {
359 int driverId = allDrivers.get(i).id;
360 writer.print(indent + "#" + i + ": id=" + driverId);
361 List<UserInfo> passengers = getPassengers(driverId);
362 int passengersSize = passengers.size();
363 writer.print(" NumberPassengers: " + passengersSize);
364 if (passengersSize > 0) {
365 writer.print(" [");
366 for (int j = 0; j < passengersSize; j++) {
367 writer.print(passengers.get(j).id);
368 if (j < passengersSize - 1) {
369 writer.print(" ");
felipeal2d0483c2019-11-02 14:07:22 -0700370 }
felipeal2d0483c2019-11-02 14:07:22 -0700371 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700372 writer.print("]");
felipeal2d0483c2019-11-02 14:07:22 -0700373 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700374 writer.println();
375 }
376 writer.printf("EnablePassengerSupport: %s\n", mEnablePassengerSupport);
377 writer.printf("User HAL timeout: %dms\n", mHalTimeoutMs);
378 writer.printf("Initial user: %s\n", mInitialUser);
felipealbf327652020-06-03 11:33:29 -0700379
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700380 writer.println("Relevant overlayable properties");
381 Resources res = mContext.getResources();
382 writer.printf("%sowner_name=%s\n", indent,
383 res.getString(com.android.internal.R.string.owner_name));
384 writer.printf("%sdefault_guest_name=%s\n", indent,
385 res.getString(R.string.default_guest_name));
felipealf7368962020-04-16 12:55:19 -0700386 writer.printf("User switch in process=%d\n", mUserIdForUserSwitchInProcess);
Mayank Garg7a114c82020-04-08 21:25:06 -0700387 writer.printf("Request Id for the user switch in process=%d\n ",
388 mRequestIdForUserSwitchInProcess);
Mayank Garga480dd92020-05-14 03:14:57 -0700389 writer.printf("System UI package name=%s\n", getSystemUiPackageName());
felipeale8c5dce2020-04-15 11:27:06 -0700390
felipealbf327652020-06-03 11:33:29 -0700391 writer.println("Relevant Global settings");
392 dumpGlobalProperty(writer, indent, CarSettings.Global.LAST_ACTIVE_USER_ID);
393 dumpGlobalProperty(writer, indent, CarSettings.Global.LAST_ACTIVE_PERSISTENT_USER_ID);
394
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700395 mInitialUserSetter.dump(writer);
felipeale8c5dce2020-04-15 11:27:06 -0700396 }
397
felipealbf327652020-06-03 11:33:29 -0700398 private void dumpGlobalProperty(PrintWriter writer, String indent, String property) {
399 String value = Settings.Global.getString(mContext.getContentResolver(), property);
400 writer.printf("%s%s=%s\n", indent, property, value);
401 }
402
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700403 private void handleDumpListeners(@NonNull PrintWriter writer, String indent) {
404 CountDownLatch latch = new CountDownLatch(1);
405 mHandler.post(() -> {
felipealde1e16d2020-06-03 13:20:48 -0700406 handleDumpServiceLifecycleListeners(writer);
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700407 handleDumpAppLifecycleListeners(writer, indent);
408 latch.countDown();
409 });
410 int timeout = 5;
411 try {
412 if (!latch.await(timeout, TimeUnit.SECONDS)) {
413 writer.printf("Handler thread didn't respond in %ds when dumping listeners\n",
414 timeout);
415 }
416 } catch (InterruptedException e) {
417 Thread.currentThread().interrupt();
418 writer.println("Interrupted waiting for handler thread to dump app and user listeners");
419 }
420 }
421
felipealde1e16d2020-06-03 13:20:48 -0700422 private void handleDumpServiceLifecycleListeners(@NonNull PrintWriter writer) {
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700423 if (mUserLifecycleListeners.isEmpty()) {
felipealde1e16d2020-06-03 13:20:48 -0700424 writer.println("No lifecycle listeners for internal services");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700425 return;
426 }
felipealde1e16d2020-06-03 13:20:48 -0700427 int size = mUserLifecycleListeners.size();
428 writer.printf("%d lifecycle listener%s for services\n", size, size == 1 ? "" : "s");
429 String indent = " ";
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700430 for (UserLifecycleListener listener : mUserLifecycleListeners) {
felipealde1e16d2020-06-03 13:20:48 -0700431 writer.printf("%s%s\n", indent, FunctionalUtils.getLambdaName(listener));
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700432 }
433 }
434
435 private void handleDumpAppLifecycleListeners(@NonNull PrintWriter writer, String indent) {
felipealde1e16d2020-06-03 13:20:48 -0700436 int size = mAppLifecycleListeners.size();
437 if (size == 0) {
438 writer.println("No lifecycle listeners for apps");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700439 return;
440 }
felipealde1e16d2020-06-03 13:20:48 -0700441 writer.printf("%d lifecycle listener%s for apps \n", size, size == 1 ? "" : "s");
442 for (int i = 0; i < size; i++) {
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700443 int uid = mAppLifecycleListeners.keyAt(i);
444 IResultReceiver listener = mAppLifecycleListeners.valueAt(i);
Felipe Lemeea4b5322020-10-26 15:33:36 -0700445 writer.printf("%suid: %d listener: %s\n", indent, uid,
446 FunctionalUtils.getLambdaName(listener));
Keun-young Parkd462a912019-02-11 08:53:42 -0800447 }
Eric Jeong1545f3b2019-09-16 13:56:52 -0700448 }
449
450 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700451 * @see ExperimentalCarUserManager.createDriver
Eric Jeong1545f3b2019-09-16 13:56:52 -0700452 */
453 @Override
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700454 public AndroidFuture<UserCreationResult> createDriver(@NonNull String name, boolean admin) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700455 checkManageUsersPermission("createDriver");
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +0000456 Objects.requireNonNull(name, "name cannot be null");
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700457
458 AndroidFuture<UserCreationResult> future = new AndroidFuture<UserCreationResult>() {
459 @Override
460 protected void onCompleted(UserCreationResult result, Throwable err) {
461 if (result == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800462 Slog.w(TAG, "createDriver(" + name + "," + admin + ") failed: " + err);
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700463 } else {
464 if (result.getStatus() == UserCreationResult.STATUS_SUCCESSFUL) {
465 assignDefaultIcon(result.getUser());
466 }
467 }
468 super.onCompleted(result, err);
469 };
470 };
471 int flags = 0;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700472 if (admin) {
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700473 if (!(mUserManager.isAdminUser() || mUserManager.isSystemUser())) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800474 Slog.e(TAG, "Only admin users and system user can create other admins.");
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700475 sendUserCreationResultFailure(future, UserCreationResult.STATUS_INVALID_REQUEST);
476 return future;
477 }
478 flags = UserInfo.FLAG_ADMIN;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700479 }
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700480 createUser(name, UserInfo.getDefaultUserType(flags), flags, mHalTimeoutMs, future);
481 return future;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700482 }
483
484 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700485 * @see ExperimentalCarUserManager.createPassenger
Eric Jeong1545f3b2019-09-16 13:56:52 -0700486 */
487 @Override
488 @Nullable
489 public UserInfo createPassenger(@NonNull String name, @UserIdInt int driverId) {
490 checkManageUsersPermission("createPassenger");
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +0000491 Objects.requireNonNull(name, "name cannot be null");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700492 UserInfo driver = mUserManager.getUserInfo(driverId);
493 if (driver == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800494 Slog.w(TAG, "the driver is invalid");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700495 return null;
496 }
497 if (driver.isGuest()) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800498 Slog.w(TAG, "a guest driver cannot create a passenger");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700499 return null;
500 }
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700501 // createPassenger doesn't use user HAL because user HAL doesn't support profile user yet.
Bookatz42fb1a62019-10-30 11:45:01 -0700502 UserInfo user = mUserManager.createProfileForUser(name,
503 UserManager.USER_TYPE_PROFILE_MANAGED, /* flags */ 0, driverId);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700504 if (user == null) {
505 // Couldn't create user, most likely because there are too many.
Eric Jeongf75d4132020-12-21 13:48:23 -0800506 Slog.w(TAG, "can't create a profile for user" + driverId);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700507 return null;
508 }
509 // Passenger user should be a non-admin user.
Mayank Garge90a4082020-09-30 12:57:34 -0700510 UserHelper.setDefaultNonAdminRestrictions(mContext, user, /* enable= */ true);
Anthony Hugh6fed1e92019-10-22 16:22:03 -0700511 assignDefaultIcon(user);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700512 return user;
513 }
514
515 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700516 * @see ExperimentalCarUserManager.switchDriver
Eric Jeong1545f3b2019-09-16 13:56:52 -0700517 */
518 @Override
Eric Jeong25666cf2020-05-14 15:16:27 -0700519 public void switchDriver(@UserIdInt int driverId, AndroidFuture<UserSwitchResult> receiver) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700520 checkManageUsersPermission("switchDriver");
Mayank Garg94f3eb92020-08-12 12:38:58 -0700521 if (UserHelperLite.isHeadlessSystemUser(driverId)) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700522 // System user doesn't associate with real person, can not be switched to.
Eric Jeongf75d4132020-12-21 13:48:23 -0800523 Slog.w(TAG, "switching to system user in headless system user mode is not allowed");
felipealdfdf8512020-06-01 09:35:45 -0700524 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_INVALID_REQUEST);
Eric Jeong25666cf2020-05-14 15:16:27 -0700525 return;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700526 }
527 int userSwitchable = mUserManager.getUserSwitchability();
528 if (userSwitchable != UserManager.SWITCHABILITY_STATUS_OK) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800529 Slog.w(TAG, "current process is not allowed to switch user");
felipealdfdf8512020-06-01 09:35:45 -0700530 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_INVALID_REQUEST);
Eric Jeong25666cf2020-05-14 15:16:27 -0700531 return;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700532 }
Eric Jeong25666cf2020-05-14 15:16:27 -0700533 switchUser(driverId, mHalTimeoutMs, receiver);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700534 }
535
536 /**
Eric Jeonge7916fc2019-12-20 14:03:34 -0800537 * Returns all drivers who can occupy the driving zone. Guest users are included in the list.
538 *
539 * @return the list of {@link UserInfo} who can be a driver on the device.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700540 */
541 @Override
542 @NonNull
543 public List<UserInfo> getAllDrivers() {
felipeal2d0483c2019-11-02 14:07:22 -0700544 checkManageUsersOrDumpPermission("getAllDrivers");
Mayank Garg94f3eb92020-08-12 12:38:58 -0700545 return getUsers((user) -> !UserHelperLite.isHeadlessSystemUser(user.id) && user.isEnabled()
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700546 && !user.isManagedProfile() && !user.isEphemeral());
Eric Jeong1545f3b2019-09-16 13:56:52 -0700547 }
548
549 /**
Eric Jeonge7916fc2019-12-20 14:03:34 -0800550 * Returns all passengers under the given driver.
551 *
552 * @param driverId User id of a driver.
553 * @return the list of {@link UserInfo} who is a passenger under the given driver.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700554 */
555 @Override
556 @NonNull
557 public List<UserInfo> getPassengers(@UserIdInt int driverId) {
felipeal2d0483c2019-11-02 14:07:22 -0700558 checkManageUsersOrDumpPermission("getPassengers");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700559 return getUsers((user) -> {
Mayank Garg94f3eb92020-08-12 12:38:58 -0700560 return !UserHelperLite.isHeadlessSystemUser(user.id) && user.isEnabled()
Eric Jeong40f8fa32020-05-12 12:23:33 -0700561 && user.isManagedProfile() && user.profileGroupId == driverId;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700562 });
563 }
564
565 /**
566 * @see CarUserManager.startPassenger
567 */
568 @Override
569 public boolean startPassenger(@UserIdInt int passengerId, int zoneId) {
570 checkManageUsersPermission("startPassenger");
Eric Jeongc91f9452019-08-30 15:04:21 -0700571 synchronized (mLockUser) {
572 try {
573 if (!mAm.startUserInBackgroundWithListener(passengerId, null)) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800574 Slog.w(TAG, "could not start passenger");
Eric Jeongc91f9452019-08-30 15:04:21 -0700575 return false;
576 }
577 } catch (RemoteException e) {
578 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -0800579 Slog.w(TAG, "error while starting passenger", e);
Eric Jeongc91f9452019-08-30 15:04:21 -0700580 return false;
581 }
582 if (!assignUserToOccupantZone(passengerId, zoneId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800583 Slog.w(TAG, "could not assign passenger to zone");
Eric Jeongc91f9452019-08-30 15:04:21 -0700584 return false;
585 }
586 mLastPassengerId = passengerId;
587 }
588 for (PassengerCallback callback : mPassengerCallbacks) {
589 callback.onPassengerStarted(passengerId, zoneId);
590 }
591 return true;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700592 }
593
594 /**
595 * @see CarUserManager.stopPassenger
596 */
597 @Override
598 public boolean stopPassenger(@UserIdInt int passengerId) {
599 checkManageUsersPermission("stopPassenger");
Eric Jeongc91f9452019-08-30 15:04:21 -0700600 return stopPassengerInternal(passengerId, true);
601 }
602
603 private boolean stopPassengerInternal(@UserIdInt int passengerId, boolean checkCurrentDriver) {
604 synchronized (mLockUser) {
605 UserInfo passenger = mUserManager.getUserInfo(passengerId);
606 if (passenger == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800607 Slog.w(TAG, "passenger " + passengerId + " doesn't exist");
Eric Jeongc91f9452019-08-30 15:04:21 -0700608 return false;
609 }
610 if (mLastPassengerId != passengerId) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800611 Slog.w(TAG, "passenger " + passengerId + " hasn't been started");
Eric Jeongc91f9452019-08-30 15:04:21 -0700612 return true;
613 }
614 if (checkCurrentDriver) {
615 int currentUser = ActivityManager.getCurrentUser();
616 if (passenger.profileGroupId != currentUser) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800617 Slog.w(TAG, "passenger " + passengerId
Eric Jeongc91f9452019-08-30 15:04:21 -0700618 + " is not a profile of the current user");
619 return false;
620 }
621 }
622 // Passenger is a profile, so cannot be stopped through activity manager.
623 // Instead, activities started by the passenger are stopped and the passenger is
624 // unassigned from the zone.
625 stopAllTasks(passengerId);
626 if (!unassignUserFromOccupantZone(passengerId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800627 Slog.w(TAG, "could not unassign user from occupant zone");
Eric Jeongc91f9452019-08-30 15:04:21 -0700628 return false;
629 }
630 mLastPassengerId = UserHandle.USER_NULL;
631 }
632 for (PassengerCallback callback : mPassengerCallbacks) {
633 callback.onPassengerStopped(passengerId);
634 }
635 return true;
636 }
637
638 private void stopAllTasks(@UserIdInt int userId) {
639 try {
Louis Chang3bf2f202020-08-18 13:04:28 +0800640 for (RootTaskInfo info : mAm.getAllRootTaskInfos()) {
641 for (int i = 0; i < info.childTaskIds.length; i++) {
642 if (info.childTaskUserIds[i] == userId) {
643 int taskId = info.childTaskIds[i];
Eric Jeongc91f9452019-08-30 15:04:21 -0700644 if (!mAm.removeTask(taskId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800645 Slog.w(TAG, "could not remove task " + taskId);
Eric Jeongc91f9452019-08-30 15:04:21 -0700646 }
647 }
648 }
649 }
650 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800651 Slog.e(TAG, "could not get stack info", e);
Eric Jeongc91f9452019-08-30 15:04:21 -0700652 }
Eric Jeong1545f3b2019-09-16 13:56:52 -0700653 }
654
Felipe Leme5528ff72020-02-10 19:05:14 -0800655 @Override
656 public void setLifecycleListenerForUid(IResultReceiver listener) {
657 int uid = Binder.getCallingUid();
felipeal312416a2020-04-14 12:28:24 -0700658 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SET_LIFECYCLE_LISTENER, uid);
Felipe Leme5528ff72020-02-10 19:05:14 -0800659 checkInteractAcrossUsersPermission("setLifecycleListenerForUid" + uid);
660
661 try {
662 listener.asBinder().linkToDeath(() -> onListenerDeath(uid), 0);
663 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800664 Slog.wtf(TAG, "Cannot listen to death of " + uid);
Felipe Leme5528ff72020-02-10 19:05:14 -0800665 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700666 mHandler.post(() -> mAppLifecycleListeners.append(uid, listener));
Felipe Leme5528ff72020-02-10 19:05:14 -0800667 }
668
669 private void onListenerDeath(int uid) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800670 Slog.i(TAG, "Removing listeners for uid " + uid + " on binder death");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700671 mHandler.post(() -> mAppLifecycleListeners.remove(uid));
Felipe Leme5528ff72020-02-10 19:05:14 -0800672 }
673
674 @Override
675 public void resetLifecycleListenerForUid() {
676 int uid = Binder.getCallingUid();
felipeal312416a2020-04-14 12:28:24 -0700677 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_RESET_LIFECYCLE_LISTENER, uid);
Felipe Leme5528ff72020-02-10 19:05:14 -0800678 checkInteractAcrossUsersPermission("resetLifecycleListenerForUid-" + uid);
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700679 mHandler.post(() -> mAppLifecycleListeners.remove(uid));
Felipe Leme5528ff72020-02-10 19:05:14 -0800680 }
681
Felipe Lemee3cab982020-03-12 11:39:29 -0700682 /**
felipeal61ce3732020-04-03 11:01:00 -0700683 * Gets the initial foreground user after the device boots or resumes from suspension.
684 *
685 * <p>When the OEM supports the User HAL, the initial user won't be available until the HAL
686 * returns the initial value to {@code CarService} - if HAL takes too long or times out, this
687 * method returns {@code null}.
688 *
689 * <p>If the HAL eventually times out, {@code CarService} will fallback to its default behavior
690 * (like switching to the last active user), and this method will return the result of such
691 * operation.
692 *
693 * <p>Notice that if {@code CarService} crashes, subsequent calls to this method will return
694 * {@code null}.
695 *
696 * @hide
697 */
698 @Nullable
699 public UserInfo getInitialUser() {
700 checkInteractAcrossUsersPermission("getInitialUser");
701 synchronized (mLockUser) {
702 return mInitialUser;
703 }
704 }
705
felipeal61ce3732020-04-03 11:01:00 -0700706 /**
707 * Sets the initial foreground user after the device boots or resumes from suspension.
708 */
709 public void setInitialUser(@Nullable UserInfo user) {
felipeal312416a2020-04-14 12:28:24 -0700710 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SET_INITIAL_USER,
711 user == null ? UserHandle.USER_NULL : user.id);
felipeal61ce3732020-04-03 11:01:00 -0700712 synchronized (mLockUser) {
713 mInitialUser = user;
714 }
715 if (user == null) {
716 // This mean InitialUserSetter failed and could not fallback, so the initial user was
717 // not switched (and most likely is SYSTEM_USER).
718 // TODO(b/153104378): should we set it to ActivityManager.getCurrentUser() instead?
Eric Jeongf75d4132020-12-21 13:48:23 -0800719 Slog.wtf(TAG, "Initial user set to null");
felipeal61ce3732020-04-03 11:01:00 -0700720 }
721 }
722
Mayank Garg7e1450b2020-08-07 18:15:15 -0700723 private void initResumeReplaceGuest() {
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700724 int currentUserId = ActivityManager.getCurrentUser();
725 UserInfo currentUser = mUserManager.getUserInfo(currentUserId);
726
727 if (!mInitialUserSetter.canReplaceGuestUser(currentUser)) return; // Not a guest
728
729 InitialUserInfo info =
730 new InitialUserSetter.Builder(InitialUserSetter.TYPE_REPLACE_GUEST).build();
731
732 mInitialUserSetter.set(info);
733 }
734
735 /**
Mayank Garg0baf88a2020-08-30 21:57:36 -0700736 * Calls to switch user at the power suspend.
Mayank Garg7e1450b2020-08-07 18:15:15 -0700737 *
738 * <p><b>Note:</b> Should be used only by {@link CarPowerManagementService}
739 *
Mayank Garg7e1450b2020-08-07 18:15:15 -0700740 */
Mayank Garg0baf88a2020-08-30 21:57:36 -0700741 public void onSuspend() {
Eric Jeongf75d4132020-12-21 13:48:23 -0800742 if (Log.isLoggable(TAG, Log.DEBUG)) {
743 Slog.d(TAG, "onSuspend called.");
Mayank Garg7e1450b2020-08-07 18:15:15 -0700744 }
745
Mayank Garg0baf88a2020-08-30 21:57:36 -0700746 if (mSwitchGuestUserBeforeSleep) {
747 initResumeReplaceGuest();
Mayank Garg7e1450b2020-08-07 18:15:15 -0700748 }
Mayank Garg1bb1c382020-09-03 17:11:11 -0700749
750 preCreateUsers();
Mayank Garg7e1450b2020-08-07 18:15:15 -0700751 }
752
753 /**
Mayank Garg0baf88a2020-08-30 21:57:36 -0700754 * Calls to switch user at the power resume.
755 *
756 * <p>
757 * <b>Note:</b> Should be used only by {@link CarPowerManagementService}
758 *
759 */
760 public void onResume() {
Eric Jeongf75d4132020-12-21 13:48:23 -0800761 if (Log.isLoggable(TAG, Log.DEBUG)) {
762 Slog.d(TAG, "onResume called.");
Mayank Garg0baf88a2020-08-30 21:57:36 -0700763 }
764
765 initBootUser(InitialUserInfoRequestType.RESUME);
766 }
767
768 /**
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700769 * Calls to start user at the android startup.
Mayank Garg70732a82020-08-05 20:17:47 -0700770 */
771 public void initBootUser() {
772 int requestType = getInitialUserInfoRequestType();
Mayank Garg7e1450b2020-08-07 18:15:15 -0700773 initBootUser(requestType);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700774 }
775
Mayank Garg7e1450b2020-08-07 18:15:15 -0700776 private void initBootUser(int requestType) {
777 boolean replaceGuest =
778 requestType == InitialUserInfoRequestType.RESUME && !mSwitchGuestUserBeforeSleep;
Mayank Garg70732a82020-08-05 20:17:47 -0700779 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_REQ, requestType,
780 mHalTimeoutMs);
781 checkManageUsersPermission("startInitialUser");
782
783 if (!isUserHalSupported()) {
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700784 fallbackToDefaultInitialUserBehavior(/* userLocales= */ null, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700785 return;
786 }
787
788 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
789 mHal.getInitialUserInfo(requestType, mHalTimeoutMs, usersInfo, (status, resp) -> {
790 if (resp != null) {
791 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_RESP,
792 status, resp.action, resp.userToSwitchOrCreate.userId,
793 resp.userToSwitchOrCreate.flags, resp.userNameToCreate, resp.userLocales);
794
795 String userLocales = resp.userLocales;
796 InitialUserInfo info;
797 switch (resp.action) {
798 case InitialUserInfoResponseAction.SWITCH:
799 int userId = resp.userToSwitchOrCreate.userId;
800 if (userId <= 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800801 Slog.w(TAG, "invalid (or missing) user id sent by HAL: " + userId);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700802 fallbackToDefaultInitialUserBehavior(userLocales, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700803 break;
804 }
805 info = new InitialUserSetter.Builder(InitialUserSetter.TYPE_SWITCH)
806 .setUserLocales(userLocales)
807 .setSwitchUserId(userId)
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700808 .setReplaceGuest(replaceGuest)
Mayank Garg70732a82020-08-05 20:17:47 -0700809 .build();
810 mInitialUserSetter.set(info);
811 break;
812
813 case InitialUserInfoResponseAction.CREATE:
814 int halFlags = resp.userToSwitchOrCreate.flags;
815 String userName = resp.userNameToCreate;
816 info = new InitialUserSetter.Builder(InitialUserSetter.TYPE_CREATE)
817 .setUserLocales(userLocales)
818 .setNewUserName(userName)
819 .setNewUserFlags(halFlags)
820 .build();
821 mInitialUserSetter.set(info);
822 break;
823
824 case InitialUserInfoResponseAction.DEFAULT:
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700825 fallbackToDefaultInitialUserBehavior(userLocales, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700826 break;
827 default:
Eric Jeongf75d4132020-12-21 13:48:23 -0800828 Slog.w(TAG, "invalid response action on " + resp);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700829 fallbackToDefaultInitialUserBehavior(/* user locale */ null, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700830 break;
831
832 }
833 } else {
834 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_RESP, status);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700835 fallbackToDefaultInitialUserBehavior(/* user locale */ null, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700836 }
837 });
838 }
839
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700840 private void fallbackToDefaultInitialUserBehavior(String userLocales, boolean replaceGuest) {
Mayank Garg70732a82020-08-05 20:17:47 -0700841 InitialUserInfo info = new InitialUserSetter.Builder(
842 InitialUserSetter.TYPE_DEFAULT_BEHAVIOR)
843 .setUserLocales(userLocales)
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700844 .setReplaceGuest(replaceGuest)
Mayank Garg70732a82020-08-05 20:17:47 -0700845 .build();
846 mInitialUserSetter.set(info);
847 }
848
849 @VisibleForTesting
850 int getInitialUserInfoRequestType() {
Mayank Garge90a4082020-09-30 12:57:34 -0700851 if (!mInitialUserSetter.hasInitialUser()) {
Mayank Garg70732a82020-08-05 20:17:47 -0700852 return InitialUserInfoRequestType.FIRST_BOOT;
853 }
854 if (mContext.getPackageManager().isDeviceUpgrading()) {
855 return InitialUserInfoRequestType.FIRST_BOOT_AFTER_OTA;
856 }
857 return InitialUserInfoRequestType.COLD_BOOT;
858 }
859
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800860 /**
861 * Sets the {@link ICarServiceHelper} so it can receive UX restriction updates.
862 */
863 public void setCarServiceHelper(ICarServiceHelper helper) {
864 boolean restricted;
865 synchronized (mLockUser) {
866 mICarServiceHelper = helper;
867 restricted = mUxRestricted;
868 }
869 updateSafetyMode(helper, restricted);
870 }
871
872 private void updateSafetyMode(@Nullable ICarServiceHelper helper, boolean restricted) {
873 if (helper == null) return;
874
875 boolean isSafe = !restricted;
876 try {
877 helper.setSafetyMode(isSafe);
878 } catch (Exception e) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800879 Slog.e(TAG, "Exception calling helper.setDpmSafetyMode(" + isSafe + ")", e);
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800880 }
881 }
882
883 private void setUxRestrictions(@Nullable CarUxRestrictions restrictions) {
Felipe Leme5d5ab142020-10-27 13:49:10 -0700884 boolean restricted = restrictions != null
885 && (restrictions.getActiveRestrictions() & UX_RESTRICTIONS_NO_SETUP)
886 == UX_RESTRICTIONS_NO_SETUP;
Eric Jeongf75d4132020-12-21 13:48:23 -0800887 if (Log.isLoggable(TAG, Log.DEBUG)) {
888 Slog.d(TAG, "setUxRestrictions(" + restrictions + "): restricted=" + restricted);
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800889 } else {
Eric Jeongf75d4132020-12-21 13:48:23 -0800890 Slog.i(TAG, "Setting UX restricted to " + restricted);
Felipe Leme5d5ab142020-10-27 13:49:10 -0700891 }
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800892
893 ICarServiceHelper helper = null;
894
895 synchronized (mLockUser) {
896 mUxRestricted = restricted;
897 if (mICarServiceHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800898 Slog.e(TAG, "onUxRestrictionsChanged(): no mICarServiceHelper");
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800899 }
900 helper = mICarServiceHelper;
901 }
902 updateSafetyMode(helper, restricted);
903 }
904
905 private boolean isUxRestricted() {
906 synchronized (mLockUser) {
907 return mUxRestricted;
908 }
Felipe Leme5d5ab142020-10-27 13:49:10 -0700909 }
910
Mayank Garg70732a82020-08-05 20:17:47 -0700911 /**
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700912 * Calls the {@link UserHalService} and {@link IActivityManager} for user switch.
913 *
914 * <p>
Mayank Gargb08f6772020-05-01 18:06:48 -0700915 * When everything works well, the workflow is:
916 * <ol>
917 * <li> {@link UserHalService} is called for HAL user switch with ANDROID_SWITCH request
918 * type, current user id, target user id, and a callback.
919 * <li> HAL called back with SUCCESS.
920 * <li> {@link IActivityManager} is called for Android user switch.
921 * <li> Receiver would receive {@code STATUS_SUCCESSFUL}.
922 * <li> Once user is unlocked, {@link UserHalService} is again called with ANDROID_POST_SWITCH
923 * request type, current user id, and target user id. In this case, the current and target
924 * user IDs would be same.
925 * <ol/>
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700926 *
927 * <p>
Mayank Gargb08f6772020-05-01 18:06:48 -0700928 * Corner cases:
929 * <ul>
930 * <li> If target user is already the current user, no user switch is performed and receiver
Mayank Gargef1b9332020-06-11 17:36:56 -0700931 * would receive {@code STATUS_OK_USER_ALREADY_IN_FOREGROUND} right away.
Mayank Gargb08f6772020-05-01 18:06:48 -0700932 * <li> If HAL user switch call fails, no Android user switch. Receiver would receive
933 * {@code STATUS_HAL_INTERNAL_FAILURE}.
934 * <li> If HAL user switch call is successful, but android user switch call fails,
935 * {@link UserHalService} is again called with request type POST_SWITCH, current user id, and
936 * target user id, but in this case the current and target user IDs would be different.
937 * <li> If another user switch request for the same target user is received while previous
938 * request is in process, receiver would receive
939 * {@code STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO} for the new request right away.
940 * <li> If a user switch request is received while another user switch request for different
941 * target user is in process, the previous request would be abandoned and new request will be
942 * processed. No POST_SWITCH would be sent for the previous request.
943 * <ul/>
Mayank Garg59f22192020-03-27 00:51:45 -0700944 *
Mayank Garge19c2922020-03-30 18:05:53 -0700945 * @param targetUserId - target user Id
Mayank Garg59f22192020-03-27 00:51:45 -0700946 * @param timeoutMs - timeout for HAL to wait
947 * @param receiver - receiver for the results
948 */
Mayank Garge19c2922020-03-30 18:05:53 -0700949 @Override
950 public void switchUser(@UserIdInt int targetUserId, int timeoutMs,
felipeale5bf0322020-04-16 15:10:57 -0700951 @NonNull AndroidFuture<UserSwitchResult> receiver) {
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700952 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_REQ, targetUserId, timeoutMs);
Felipe Leme17799202020-09-03 12:55:53 -0700953 checkManageOrCreateUsersPermission("switchUser");
Mayank Garge19c2922020-03-30 18:05:53 -0700954 Objects.requireNonNull(receiver);
955 UserInfo targetUser = mUserManager.getUserInfo(targetUserId);
felipealf7368962020-04-16 12:55:19 -0700956 Preconditions.checkArgument(targetUser != null, "Target user doesn't exist");
Mayank Garg7a114c82020-04-08 21:25:06 -0700957
felipealf7368962020-04-16 12:55:19 -0700958 int currentUser = ActivityManager.getCurrentUser();
959 if (currentUser == targetUserId) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800960 if (Log.isLoggable(TAG, Log.DEBUG)) {
961 Slog.d(TAG, "Current user is same as requested target user: " + targetUserId);
Mayank Garg0e239142020-04-14 19:16:31 -0700962 }
Mayank Gargef1b9332020-06-11 17:36:56 -0700963 int resultStatus = UserSwitchResult.STATUS_OK_USER_ALREADY_IN_FOREGROUND;
felipealdfdf8512020-06-01 09:35:45 -0700964 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg0e239142020-04-14 19:16:31 -0700965 return;
966 }
967
Felipe Leme5d5ab142020-10-27 13:49:10 -0700968 if (isUxRestricted()) {
969 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_UX_RESTRICTION_FAILURE);
970 return;
971 }
972
Mayank Garg9ed099e2020-06-04 16:05:20 -0700973 // If User Hal is not supported, just android user switch.
974 if (!isUserHalSupported()) {
975 try {
976 if (mAm.switchUser(targetUserId)) {
977 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_SUCCESSFUL);
978 return;
979 }
980 } catch (RemoteException e) {
981 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -0800982 Slog.w(TAG, "error while switching user " + targetUser.toFullString(), e);
Mayank Garg9ed099e2020-06-04 16:05:20 -0700983 }
984 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_ANDROID_FAILURE);
985 return;
986 }
987
Mayank Garg7a114c82020-04-08 21:25:06 -0700988 synchronized (mLockUser) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800989 if (Log.isLoggable(TAG, Log.DEBUG)) {
990 Slog.d(TAG, "switchUser(" + targetUserId + "): currentuser=" + currentUser
felipealf7368962020-04-16 12:55:19 -0700991 + ", mUserIdForUserSwitchInProcess=" + mUserIdForUserSwitchInProcess);
992 }
993
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700994 // If there is another request for the same target user, return another request in
995 // process, else {@link mUserIdForUserSwitchInProcess} is updated and {@link
996 // mRequestIdForUserSwitchInProcess} is reset. It is possible that there may be another
997 // user switch request in process for different target user, but that request is now
998 // ignored.
felipealf7368962020-04-16 12:55:19 -0700999 if (mUserIdForUserSwitchInProcess == targetUserId) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001000 if (Log.isLoggable(TAG, Log.DEBUG)) {
1001 Slog.d(TAG,
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001002 "Another user switch request in process for the requested target user: "
1003 + targetUserId);
1004 }
1005
1006 int resultStatus = UserSwitchResult.STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO;
felipealdfdf8512020-06-01 09:35:45 -07001007 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg7a114c82020-04-08 21:25:06 -07001008 return;
1009 }
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001010 else {
1011 mUserIdForUserSwitchInProcess = targetUserId;
1012 mRequestIdForUserSwitchInProcess = 0;
1013 }
Mayank Garg7a114c82020-04-08 21:25:06 -07001014 }
1015
felipealdfdf8512020-06-01 09:35:45 -07001016 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
Mayank Gargeb37d092020-06-02 14:37:57 -07001017 SwitchUserRequest request = createUserSwitchRequest(targetUserId, usersInfo);
1018
Felipe Leme5d5ab142020-10-27 13:49:10 -07001019 mHal.switchUser(request, timeoutMs, (halCallbackStatus, resp) -> {
Eric Jeongf75d4132020-12-21 13:48:23 -08001020 if (Log.isLoggable(TAG, Log.DEBUG)) {
1021 Slog.d(TAG, "switch response: status="
Felipe Leme5d5ab142020-10-27 13:49:10 -07001022 + UserHalHelper.halCallbackStatusToString(halCallbackStatus)
1023 + ", resp=" + resp);
felipealf7368962020-04-16 12:55:19 -07001024 }
1025
felipeale5bf0322020-04-16 15:10:57 -07001026 int resultStatus = UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE;
felipealf7368962020-04-16 12:55:19 -07001027
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001028 synchronized (mLockUser) {
Felipe Leme5d5ab142020-10-27 13:49:10 -07001029 if (halCallbackStatus != HalCallback.STATUS_OK) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001030 Slog.w(TAG, "invalid callback status ("
Felipe Leme5d5ab142020-10-27 13:49:10 -07001031 + UserHalHelper.halCallbackStatusToString(halCallbackStatus)
1032 + ") for response " + resp);
felipealdfdf8512020-06-01 09:35:45 -07001033 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001034 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
1035 return;
1036 }
felipealf7368962020-04-16 12:55:19 -07001037
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001038 if (mUserIdForUserSwitchInProcess != targetUserId) {
1039 // Another user switch request received while HAL responded. No need to process
1040 // this request further
Eric Jeongf75d4132020-12-21 13:48:23 -08001041 if (Log.isLoggable(TAG, Log.DEBUG)) {
1042 Slog.d(TAG, "Another user switch received while HAL responsed. Request"
1043 + " abondoned for : " + targetUserId + ". Current user in process: "
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001044 + mUserIdForUserSwitchInProcess);
felipealf7368962020-04-16 12:55:19 -07001045 }
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001046 resultStatus =
1047 UserSwitchResult.STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST;
felipealdfdf8512020-06-01 09:35:45 -07001048 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001049 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
1050 return;
1051 }
1052
1053 switch (resp.status) {
1054 case SwitchUserStatus.SUCCESS:
1055 boolean switched;
1056 try {
1057 switched = mAm.switchUser(targetUserId);
1058 if (switched) {
Mayank Garg587f1942020-05-06 01:41:34 -07001059 sendUserSwitchUiCallback(targetUserId);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001060 resultStatus = UserSwitchResult.STATUS_SUCCESSFUL;
1061 mRequestIdForUserSwitchInProcess = resp.requestId;
1062 } else {
1063 resultStatus = UserSwitchResult.STATUS_ANDROID_FAILURE;
1064 postSwitchHalResponse(resp.requestId, targetUserId);
1065 }
1066 } catch (RemoteException e) {
1067 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001068 Slog.w(TAG,
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001069 "error while switching user " + targetUser.toFullString(), e);
1070 }
1071 break;
1072 case SwitchUserStatus.FAILURE:
1073 // HAL failed to switch user
1074 resultStatus = UserSwitchResult.STATUS_HAL_FAILURE;
1075 break;
felipealdfdf8512020-06-01 09:35:45 -07001076 default:
1077 // Shouldn't happen because UserHalService validates the status
Eric Jeongf75d4132020-12-21 13:48:23 -08001078 Slog.wtf(TAG, "Received invalid user switch status from HAL: " + resp);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001079 }
1080
1081 if (mRequestIdForUserSwitchInProcess == 0) {
1082 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
1083 }
Mayank Garg59f22192020-03-27 00:51:45 -07001084 }
Felipe Leme5d5ab142020-10-27 13:49:10 -07001085 sendUserSwitchResult(receiver, halCallbackStatus, resultStatus, resp.errorMessage);
Mayank Garg59f22192020-03-27 00:51:45 -07001086 });
1087 }
1088
Mayank Garga55c3092020-05-28 03:19:24 -07001089 @Override
Felipe Leme55236722020-10-16 16:54:32 -07001090 public UserRemovalResult removeUser(@UserIdInt int userId) {
1091 return removeUser(userId, /* hasCallerRestrictions= */ false);
1092 }
1093
1094 /**
1095 * Internal implementation of {@code removeUser()}, which is used by both
1096 * {@code ICarUserService} and {@code ICarDevicePolicyService}.
1097 *
1098 * @param userId user to be removed
1099 * @param hasCallerRestrictions when {@code true}, if the caller user is not an admin, it can
1100 * only remove itself.
1101 *
1102 * @return result of the operation.
1103 */
Felipe Lemee5bb26b2020-10-26 15:49:17 -07001104 public UserRemovalResult removeUser(@UserIdInt int userId, boolean hasCallerRestrictions) {
Felipe Leme17799202020-09-03 12:55:53 -07001105 checkManageOrCreateUsersPermission("removeUser");
Felipe Leme55236722020-10-16 16:54:32 -07001106 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_REMOVE_USER_REQ, userId,
1107 hasCallerRestrictions ? 1 : 0);
Felipe Lemee5bb26b2020-10-26 15:49:17 -07001108
Mayank Garga55c3092020-05-28 03:19:24 -07001109 // If requested user is the only admin user, return error.
1110 UserInfo userInfo = mUserManager.getUserInfo(userId);
1111 if (userInfo == null) {
1112 return logAndGetResults(userId, UserRemovalResult.STATUS_USER_DOES_NOT_EXIST);
1113 }
1114
Felipe Lemee5bb26b2020-10-26 15:49:17 -07001115 if (hasCallerRestrictions) {
1116 // Restrictions: non-admin user can only remove itself, admins have no restrictions
1117 int callingUserId = Binder.getCallingUserHandle().getIdentifier();
1118 UserInfo callingUser = mUserManager.getUserInfo(callingUserId);
1119 if (!callingUser.isAdmin() && userId != callingUserId) {
1120 throw new SecurityException("Non-admin user " + callingUserId
1121 + " can only remove itself");
1122 }
1123 }
1124
Mayank Garga55c3092020-05-28 03:19:24 -07001125 android.hardware.automotive.vehicle.V2_0.UserInfo halUser =
1126 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1127 halUser.userId = userInfo.id;
1128 halUser.flags = UserHalHelper.convertFlags(userInfo);
1129 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1130
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001131 // check if the user is last admin user.
1132 boolean isLastAdmin = false;
Mayank Garga55c3092020-05-28 03:19:24 -07001133 if (UserHalHelper.isAdmin(halUser.flags)) {
1134 int size = usersInfo.existingUsers.size();
1135 int totalAdminUsers = 0;
1136 for (int i = 0; i < size; i++) {
1137 if (UserHalHelper.isAdmin(usersInfo.existingUsers.get(i).flags)) {
1138 totalAdminUsers++;
1139 }
1140 }
1141 if (totalAdminUsers == 1) {
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001142 isLastAdmin = true;
Mayank Garga55c3092020-05-28 03:19:24 -07001143 }
1144 }
1145
1146 // First remove user from android and then remove from HAL because HAL remove user is one
1147 // way call.
Felipe Leme9a751912021-01-05 17:45:48 -08001148 // TODO(b/170887769): rename hasCallerRestrictions to fromCarDevicePolicyManager (or use an
1149 // int / enum to indicate if it's called from CarUserManager or CarDevicePolicyManager), as
1150 // it's counter-intuitive that it's "allowed even when disallowed" when it
1151 // "has caller restrictions"
1152 boolean evenWhenDisallowed = hasCallerRestrictions;
1153 int result = mUserManager.removeUserOrSetEphemeral(userId, evenWhenDisallowed);
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001154 if (result == UserManager.REMOVE_RESULT_ERROR) {
Mayank Garga55c3092020-05-28 03:19:24 -07001155 return logAndGetResults(userId, UserRemovalResult.STATUS_ANDROID_FAILURE);
1156 }
1157
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001158 if (isLastAdmin) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001159 Slog.w(TAG,
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001160 "Last admin user successfully removed or set ephemeral. User Id: " + userId);
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001161 }
1162
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001163 switch (result) {
1164 case UserManager.REMOVE_RESULT_REMOVED:
1165 case UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED:
1166 return logAndGetResults(userId,
1167 isLastAdmin ? UserRemovalResult.STATUS_SUCCESSFUL_LAST_ADMIN_REMOVED
1168 : UserRemovalResult.STATUS_SUCCESSFUL);
1169 case UserManager.REMOVE_RESULT_SET_EPHEMERAL:
1170 return logAndGetResults(userId,
1171 isLastAdmin ? UserRemovalResult.STATUS_SUCCESSFUL_LAST_ADMIN_SET_EPHEMERAL
1172 : UserRemovalResult.STATUS_SUCCESSFUL_SET_EPHEMERAL);
1173 default:
1174 throw new IllegalStateException("Unknown user removal result code " + result);
1175 }
Mayank Garga55c3092020-05-28 03:19:24 -07001176 }
1177
Felipe Leme67d564c2020-11-13 15:35:34 -08001178 /**
1179 * Should be called by {@code ICarImpl} only.
1180 */
1181 public void onUserRemoved(@NonNull UserInfo user) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001182 if (Log.isLoggable(TAG, Log.DEBUG)) {
1183 Slog.d(TAG, "onUserRemoved: " + user.toFullString());
Felipe Leme67d564c2020-11-13 15:35:34 -08001184 }
1185 notifyHalUserRemoved(user);
1186 }
1187
1188 private void notifyHalUserRemoved(@NonNull UserInfo user) {
Felipe Leme6b34fc32020-10-26 15:49:17 -07001189 if (!isUserHalSupported()) return;
1190
Felipe Leme67d564c2020-11-13 15:35:34 -08001191 if (user == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001192 Slog.wtf(TAG, "notifyHalUserRemoved() called for null user");
Felipe Leme67d564c2020-11-13 15:35:34 -08001193 return;
1194 }
1195
1196 int userId = user.id;
1197
Felipe Leme6b34fc32020-10-26 15:49:17 -07001198 if (userId == UserHandle.USER_NULL) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001199 Slog.wtf(TAG, "notifyHalUserRemoved() called for UserHandle.USER_NULL");
Felipe Leme6b34fc32020-10-26 15:49:17 -07001200 return;
1201 }
1202
1203 synchronized (mLockUser) {
1204 if (mFailedToCreateUserIds.get(userId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001205 if (Log.isLoggable(TAG, Log.DEBUG)) {
1206 Slog.d(TAG, "notifyHalUserRemoved(): skipping " + userId);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001207 }
1208 mFailedToCreateUserIds.delete(userId);
1209 return;
1210 }
1211 }
1212
1213 android.hardware.automotive.vehicle.V2_0.UserInfo halUser =
1214 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1215 halUser.userId = userId;
Felipe Leme67d564c2020-11-13 15:35:34 -08001216 halUser.flags = UserHalHelper.convertFlags(user);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001217
1218 RemoveUserRequest request = new RemoveUserRequest();
1219 request.removedUserInfo = halUser;
1220 request.usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1221 mHal.removeUser(request);
1222 }
1223
Mayank Garga55c3092020-05-28 03:19:24 -07001224 private UserRemovalResult logAndGetResults(@UserIdInt int userId,
1225 @UserRemovalResult.Status int result) {
1226 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_REMOVE_USER_RESP, userId, result);
1227 return new UserRemovalResult(result);
1228 }
1229
Mayank Garg587f1942020-05-06 01:41:34 -07001230 private void sendUserSwitchUiCallback(@UserIdInt int targetUserId) {
1231 if (mUserSwitchUiReceiver == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001232 Slog.w(TAG, "No User switch UI receiver.");
Mayank Garg587f1942020-05-06 01:41:34 -07001233 return;
1234 }
1235
felipealdfdf8512020-06-01 09:35:45 -07001236 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_UI_REQ, targetUserId);
Mayank Garg587f1942020-05-06 01:41:34 -07001237 try {
Mayank Garg587f1942020-05-06 01:41:34 -07001238 mUserSwitchUiReceiver.send(targetUserId, null);
1239 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001240 Slog.e(TAG, "Error calling user switch UI receiver.", e);
Mayank Garg587f1942020-05-06 01:41:34 -07001241 }
1242 }
1243
Felipe Lemecceb2992020-11-18 18:22:44 -08001244 /**
1245 * Used to create the initial user, even when it's disallowed by {@code DevicePolicyManager}.
1246 */
1247 @Nullable
1248 UserInfo createUserEvenWhenDisallowed(@Nullable String name, @NonNull String userType,
1249 @UserInfoFlag int flags) {
1250 if (mICarServiceHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001251 Slog.wtf(TAG, "createUserEvenWhenDisallowed(): mICarServiceHelper not set yet",
Felipe Lemecceb2992020-11-18 18:22:44 -08001252 new Exception());
1253 return null;
1254 }
1255 try {
1256 return mICarServiceHelper.createUserEvenWhenDisallowed(name, userType, flags);
1257 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001258 Slog.e(TAG, "createUserEvenWhenDisallowed(" + UserHelperLite.safeName(name) + ", "
Felipe Lemecceb2992020-11-18 18:22:44 -08001259 + userType + ", " + UserInfo.flagsToString(flags) + ") failed", e);
1260 return null;
1261 }
1262 }
1263
felipeal5e3ede42020-04-23 18:04:07 -07001264 @Override
felipealdfdf8512020-06-01 09:35:45 -07001265 public void createUser(@Nullable String name, @NonNull String userType, @UserInfoFlag int flags,
1266 int timeoutMs, @NonNull AndroidFuture<UserCreationResult> receiver) {
Felipe Leme8c888ab2020-11-02 17:39:52 -08001267 createUser(name, userType, flags, timeoutMs, receiver, /* hasCallerRestrictions= */ false);
1268 }
1269
1270 /**
1271 * Internal implementation of {@code createUser()}, which is used by both
1272 * {@code ICarUserService} and {@code ICarDevicePolicyService}.
1273 *
1274 * @param hasCallerRestrictions when {@code true}, if the caller user is not an admin, it can
1275 * only create admin users
1276 */
1277 public void createUser(@Nullable String name, @NonNull String userType, @UserInfoFlag int flags,
1278 int timeoutMs, @NonNull AndroidFuture<UserCreationResult> receiver,
1279 boolean hasCallerRestrictions) {
felipealdfdf8512020-06-01 09:35:45 -07001280 Objects.requireNonNull(userType, "user type cannot be null");
1281 Objects.requireNonNull(receiver, "receiver cannot be null");
Felipe Leme17799202020-09-03 12:55:53 -07001282 checkManageOrCreateUsersPermission(flags);
1283
Mayank Garg94f3eb92020-08-12 12:38:58 -07001284 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_REQ,
Felipe Leme8c888ab2020-11-02 17:39:52 -08001285 UserHelperLite.safeName(name), userType, flags, timeoutMs,
1286 hasCallerRestrictions ? 1 : 0);
1287
1288 if (hasCallerRestrictions) {
1289 // Restrictions:
1290 // - type/flag can only be normal user, admin, or guest
1291 // - non-admin user can only create non-admin users
1292
1293 boolean validCombination;
1294 switch (userType) {
1295 case UserManager.USER_TYPE_FULL_SECONDARY:
1296 validCombination = flags == 0
1297 || (flags & UserInfo.FLAG_ADMIN) == UserInfo.FLAG_ADMIN;
1298 break;
1299 case UserManager.USER_TYPE_FULL_GUEST:
1300 validCombination = flags == 0;
1301 break;
1302 default:
1303 validCombination = false;
1304 }
1305 if (!validCombination) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001306 if (Log.isLoggable(TAG, Log.DEBUG)) {
1307 Slog.d(TAG, "Invalid combination of user type(" + userType
Felipe Leme71d296f2020-11-04 12:11:42 -08001308 + ") and flags (" + UserInfo.flagsToString(flags)
1309 + ") for caller with restrictions");
1310 }
1311 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_INVALID_REQUEST);
1312 return;
1313
Felipe Leme8c888ab2020-11-02 17:39:52 -08001314 }
1315
1316 int callingUserId = Binder.getCallingUserHandle().getIdentifier();
1317 UserInfo callingUser = mUserManager.getUserInfo(callingUserId);
1318 if (!callingUser.isAdmin() && (flags & UserInfo.FLAG_ADMIN) == UserInfo.FLAG_ADMIN) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001319 if (Log.isLoggable(TAG, Log.DEBUG)) {
1320 Slog.d(TAG, "Non-admin user " + callingUserId
Felipe Leme71d296f2020-11-04 12:11:42 -08001321 + " can only create non-admin users");
1322 }
1323 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_INVALID_REQUEST);
1324 return;
Felipe Leme8c888ab2020-11-02 17:39:52 -08001325 }
Felipe Leme71d296f2020-11-04 12:11:42 -08001326
Felipe Leme8c888ab2020-11-02 17:39:52 -08001327 }
felipealdfdf8512020-06-01 09:35:45 -07001328
1329 UserInfo newUser;
1330 try {
1331 newUser = mUserManager.createUser(name, userType, flags);
1332 if (newUser == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001333 Slog.w(TAG, "um.createUser() returned null for user of type " + userType
felipealdfdf8512020-06-01 09:35:45 -07001334 + " and flags " + UserInfo.flagsToString(flags));
1335 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_ANDROID_FAILURE);
1336 return;
1337 }
Eric Jeongf75d4132020-12-21 13:48:23 -08001338 if (Log.isLoggable(TAG, Log.DEBUG)) {
1339 Slog.d(TAG, "Created user: " + newUser.toFullString());
felipealdfdf8512020-06-01 09:35:45 -07001340 }
1341 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_USER_CREATED, newUser.id,
Mayank Garg94f3eb92020-08-12 12:38:58 -07001342 UserHelperLite.safeName(newUser.name), newUser.userType, newUser.flags);
felipealdfdf8512020-06-01 09:35:45 -07001343 } catch (RuntimeException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001344 Slog.e(TAG, "Error creating user of type " + userType + " and flags"
felipealdfdf8512020-06-01 09:35:45 -07001345 + UserInfo.flagsToString(flags), e);
1346 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_ANDROID_FAILURE);
1347 return;
1348 }
1349
Mayank Garg9ed099e2020-06-04 16:05:20 -07001350 if (!isUserHalSupported()) {
1351 sendUserCreationResult(receiver, UserCreationResult.STATUS_SUCCESSFUL, newUser, null);
1352 return;
1353 }
1354
felipealdfdf8512020-06-01 09:35:45 -07001355 CreateUserRequest request = new CreateUserRequest();
1356 request.usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1357 if (!TextUtils.isEmpty(name)) {
1358 request.newUserName = name;
1359 }
1360 request.newUserInfo.userId = newUser.id;
1361 request.newUserInfo.flags = UserHalHelper.convertFlags(newUser);
Eric Jeongf75d4132020-12-21 13:48:23 -08001362 if (Log.isLoggable(TAG, Log.DEBUG)) {
1363 Slog.d(TAG, "Create user request: " + request);
felipealdfdf8512020-06-01 09:35:45 -07001364 }
1365
1366 try {
1367 mHal.createUser(request, timeoutMs, (status, resp) -> {
1368 int resultStatus = UserCreationResult.STATUS_HAL_INTERNAL_FAILURE;
Eric Jeongf75d4132020-12-21 13:48:23 -08001369 if (Log.isLoggable(TAG, Log.DEBUG)) {
1370 Slog.d(TAG, "createUserResponse: status="
felipealdfdf8512020-06-01 09:35:45 -07001371 + UserHalHelper.halCallbackStatusToString(status) + ", resp=" + resp);
1372 }
1373 UserInfo user = null; // user returned in the result
1374 if (status != HalCallback.STATUS_OK) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001375 Slog.w(TAG, "invalid callback status ("
felipealdfdf8512020-06-01 09:35:45 -07001376 + UserHalHelper.halCallbackStatusToString(status) + ") for response "
1377 + resp);
1378 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_RESP, status,
1379 resultStatus, resp.errorMessage);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001380 removeCreatedUser(newUser, "HAL call failed with "
felipealdfdf8512020-06-01 09:35:45 -07001381 + UserHalHelper.halCallbackStatusToString(status));
1382 sendUserCreationResult(receiver, resultStatus, user, /* errorMsg= */ null);
1383 return;
1384 }
1385
1386 switch (resp.status) {
1387 case CreateUserStatus.SUCCESS:
1388 resultStatus = UserCreationResult.STATUS_SUCCESSFUL;
1389 user = newUser;
1390 break;
1391 case CreateUserStatus.FAILURE:
1392 // HAL failed to switch user
1393 resultStatus = UserCreationResult.STATUS_HAL_FAILURE;
1394 break;
1395 default:
1396 // Shouldn't happen because UserHalService validates the status
Eric Jeongf75d4132020-12-21 13:48:23 -08001397 Slog.wtf(TAG, "Received invalid user switch status from HAL: " + resp);
felipealdfdf8512020-06-01 09:35:45 -07001398 }
1399 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_RESP, status,
1400 resultStatus, resp.errorMessage);
1401 if (user == null) {
Felipe Leme6b34fc32020-10-26 15:49:17 -07001402 removeCreatedUser(newUser, "HAL returned "
felipealdfdf8512020-06-01 09:35:45 -07001403 + UserCreationResult.statusToString(resultStatus));
1404 }
1405 sendUserCreationResult(receiver, resultStatus, user, resp.errorMessage);
1406 });
1407 } catch (Exception e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001408 Slog.w(TAG, "mHal.createUser(" + request + ") failed", e);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001409 removeCreatedUser(newUser, "mHal.createUser() failed");
felipealdfdf8512020-06-01 09:35:45 -07001410 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_HAL_INTERNAL_FAILURE);
1411 }
1412 }
1413
Felipe Leme6b34fc32020-10-26 15:49:17 -07001414 private void removeCreatedUser(@NonNull UserInfo user, @NonNull String reason) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001415 Slog.i(TAG, "removing " + user.toFullString() + "; reason: " + reason);
Felipe Leme67d564c2020-11-13 15:35:34 -08001416
Felipe Leme6b34fc32020-10-26 15:49:17 -07001417 int userId = user.id;
1418 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_USER_REMOVED, userId, reason);
1419
1420 synchronized (mLockUser) {
1421 mFailedToCreateUserIds.put(userId, true);
1422 }
1423
felipealdfdf8512020-06-01 09:35:45 -07001424 try {
Felipe Leme6b34fc32020-10-26 15:49:17 -07001425 if (!mUserManager.removeUser(userId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001426 Slog.w(TAG, "Failed to remove user " + user.toFullString());
felipealdfdf8512020-06-01 09:35:45 -07001427 }
1428 } catch (Exception e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001429 Slog.e(TAG, "Failed to remove user " + user.toFullString(), e);
felipealdfdf8512020-06-01 09:35:45 -07001430 }
1431 }
1432
1433 @Override
Mayank Garg3f566582020-10-02 22:10:16 -07001434 public UserIdentificationAssociationResponse getUserIdentificationAssociation(
1435 @UserIdentificationAssociationType int[] types) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001436 if (!isUserHalUserAssociationSupported()) {
1437 return UserIdentificationAssociationResponse.forFailure(VEHICLE_HAL_NOT_SUPPORTED);
1438 }
1439
felipeal5e3ede42020-04-23 18:04:07 -07001440 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type");
Felipe Leme17799202020-09-03 12:55:53 -07001441 checkManageOrCreateUsersPermission("getUserIdentificationAssociation");
felipeal5e3ede42020-04-23 18:04:07 -07001442
1443 int uid = getCallingUid();
1444 int userId = UserHandle.getUserId(uid);
1445 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_GET_USER_AUTH_REQ, uid, userId);
1446
1447 UserIdentificationGetRequest request = new UserIdentificationGetRequest();
1448 request.userInfo.userId = userId;
1449 request.userInfo.flags = getHalUserInfoFlags(userId);
1450
1451 request.numberAssociationTypes = types.length;
1452 for (int i = 0; i < types.length; i++) {
1453 request.associationTypes.add(types[i]);
1454 }
1455
1456 UserIdentificationResponse halResponse = mHal.getUserAssociation(request);
1457 if (halResponse == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001458 Slog.w(TAG, "getUserIdentificationAssociation(): HAL returned null for "
felipeal5e3ede42020-04-23 18:04:07 -07001459 + Arrays.toString(types));
felipeal159a2a42020-05-08 10:32:11 -07001460 return UserIdentificationAssociationResponse.forFailure();
felipeal5e3ede42020-04-23 18:04:07 -07001461 }
1462
1463 int[] values = new int[halResponse.associations.size()];
1464 for (int i = 0; i < values.length; i++) {
1465 values[i] = halResponse.associations.get(i).value;
1466 }
1467 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_GET_USER_AUTH_RESP, values.length);
1468
felipeal159a2a42020-05-08 10:32:11 -07001469 return UserIdentificationAssociationResponse.forSuccess(values, halResponse.errorMessage);
1470 }
1471
1472 @Override
Mayank Garg3f566582020-10-02 22:10:16 -07001473 public void setUserIdentificationAssociation(int timeoutMs,
1474 @UserIdentificationAssociationType int[] types,
1475 @UserIdentificationAssociationSetValue int[] values,
felipeal159a2a42020-05-08 10:32:11 -07001476 AndroidFuture<UserIdentificationAssociationResponse> result) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001477 if (!isUserHalUserAssociationSupported()) {
1478 result.complete(
1479 UserIdentificationAssociationResponse.forFailure(VEHICLE_HAL_NOT_SUPPORTED));
1480 return;
1481 }
1482
felipeal159a2a42020-05-08 10:32:11 -07001483 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type");
1484 Preconditions.checkArgument(!ArrayUtils.isEmpty(values), "must have at least one value");
1485 if (types.length != values.length) {
1486 throw new IllegalArgumentException("types (" + Arrays.toString(types) + ") and values ("
1487 + Arrays.toString(values) + ") should have the same length");
1488 }
Felipe Leme17799202020-09-03 12:55:53 -07001489 checkManageOrCreateUsersPermission("setUserIdentificationAssociation");
felipeal159a2a42020-05-08 10:32:11 -07001490
1491 int uid = getCallingUid();
1492 int userId = UserHandle.getUserId(uid);
1493 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_REQ, uid, userId, types.length);
1494
1495 UserIdentificationSetRequest request = new UserIdentificationSetRequest();
1496 request.userInfo.userId = userId;
1497 request.userInfo.flags = getHalUserInfoFlags(userId);
1498
1499 request.numberAssociations = types.length;
1500 for (int i = 0; i < types.length; i++) {
1501 UserIdentificationSetAssociation association = new UserIdentificationSetAssociation();
1502 association.type = types[i];
1503 association.value = values[i];
1504 request.associations.add(association);
1505 }
1506
1507 mHal.setUserAssociation(timeoutMs, request, (status, resp) -> {
1508 if (status != HalCallback.STATUS_OK) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001509 Slog.w(TAG, "setUserIdentificationAssociation(): invalid callback status ("
felipeal159a2a42020-05-08 10:32:11 -07001510 + UserHalHelper.halCallbackStatusToString(status) + ") for response "
1511 + resp);
1512 if (resp == null || TextUtils.isEmpty(resp.errorMessage)) {
1513 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, 0);
1514 result.complete(UserIdentificationAssociationResponse.forFailure());
1515 return;
1516 }
1517 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, 0,
1518 resp.errorMessage);
1519 result.complete(
1520 UserIdentificationAssociationResponse.forFailure(resp.errorMessage));
1521 return;
1522 }
1523 int respSize = resp.associations.size();
1524 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, respSize,
1525 resp.errorMessage);
1526
1527 int[] responseTypes = new int[respSize];
1528 for (int i = 0; i < respSize; i++) {
1529 responseTypes[i] = resp.associations.get(i).value;
1530 }
1531 UserIdentificationAssociationResponse response = UserIdentificationAssociationResponse
1532 .forSuccess(responseTypes, resp.errorMessage);
Eric Jeongf75d4132020-12-21 13:48:23 -08001533 if (Log.isLoggable(TAG, Log.DEBUG)) {
1534 Slog.d(TAG, "setUserIdentificationAssociation(): resp= " + resp
felipeal159a2a42020-05-08 10:32:11 -07001535 + ", converted=" + response);
1536 }
1537 result.complete(response);
1538 });
felipeal5e3ede42020-04-23 18:04:07 -07001539 }
1540
1541 /**
1542 * Gets the User HAL flags for the given user.
1543 *
1544 * @throws IllegalArgumentException if the user does not exist.
1545 */
1546 private int getHalUserInfoFlags(@UserIdInt int userId) {
1547 UserInfo user = mUserManager.getUserInfo(userId);
1548 Preconditions.checkArgument(user != null, "no user for id %d", userId);
1549 return UserHalHelper.convertFlags(user);
1550 }
1551
Mayank Garg0e239142020-04-14 19:16:31 -07001552 private void sendResult(@NonNull IResultReceiver receiver, int resultCode,
1553 @Nullable Bundle resultData) {
1554 try {
1555 receiver.send(resultCode, resultData);
1556 } catch (RemoteException e) {
1557 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001558 Slog.w(TAG, "error while sending results", e);
Mayank Garg0e239142020-04-14 19:16:31 -07001559 }
1560 }
1561
felipealdfdf8512020-06-01 09:35:45 -07001562 private void sendUserSwitchResult(@NonNull AndroidFuture<UserSwitchResult> receiver,
Felipe Leme5d5ab142020-10-27 13:49:10 -07001563 @UserSwitchResult.Status int userSwitchStatus) {
1564 sendUserSwitchResult(receiver, HalCallback.STATUS_INVALID, userSwitchStatus,
1565 /* errorMessage= */ null);
felipeale5bf0322020-04-16 15:10:57 -07001566 }
1567
felipealdfdf8512020-06-01 09:35:45 -07001568 private void sendUserSwitchResult(@NonNull AndroidFuture<UserSwitchResult> receiver,
Felipe Leme5d5ab142020-10-27 13:49:10 -07001569 @HalCallback.HalCallbackStatus int halCallbackStatus,
1570 @UserSwitchResult.Status int userSwitchStatus, @Nullable String errorMessage) {
1571 if (errorMessage != null) {
1572 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_RESP, halCallbackStatus,
1573 userSwitchStatus, errorMessage);
1574 } else {
1575 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_RESP, halCallbackStatus,
1576 userSwitchStatus);
1577 }
1578 receiver.complete(new UserSwitchResult(userSwitchStatus, errorMessage));
felipeale5bf0322020-04-16 15:10:57 -07001579 }
1580
felipealdfdf8512020-06-01 09:35:45 -07001581 private void sendUserCreationResultFailure(@NonNull AndroidFuture<UserCreationResult> receiver,
1582 @UserCreationResult.Status int status) {
1583 sendUserCreationResult(receiver, status, /* user= */ null, /* errorMessage= */ null);
1584 }
1585
1586 private void sendUserCreationResult(@NonNull AndroidFuture<UserCreationResult> receiver,
1587 @UserCreationResult.Status int status, @NonNull UserInfo user,
1588 @Nullable String errorMessage) {
1589 if (TextUtils.isEmpty(errorMessage)) {
1590 errorMessage = null;
1591 }
1592 receiver.complete(new UserCreationResult(status, user, errorMessage));
1593 }
1594
Mayank Garg6307fe42020-04-15 23:09:03 -07001595 /**
1596 * Calls activity manager for user switch.
1597 *
1598 * <p><b>NOTE</b> This method is meant to be called just by UserHalService.
1599 *
1600 * @param requestId for the user switch request
1601 * @param targetUserId of the target user
1602 *
1603 * @hide
1604 */
1605 public void switchAndroidUserFromHal(int requestId, @UserIdInt int targetUserId) {
1606 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_FROM_HAL_REQ, requestId,
1607 targetUserId);
Eric Jeongf75d4132020-12-21 13:48:23 -08001608 Slog.i(TAG, "User hal requested a user switch. Target user id " + targetUserId);
Mayank Garg6307fe42020-04-15 23:09:03 -07001609
1610 try {
1611 boolean result = mAm.switchUser(targetUserId);
1612 if (result) {
1613 updateUserSwitchInProcess(requestId, targetUserId);
1614 } else {
1615 postSwitchHalResponse(requestId, targetUserId);
1616 }
1617 } catch (RemoteException e) {
1618 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001619 Slog.w(TAG, "error while switching user " + targetUserId, e);
Mayank Garg6307fe42020-04-15 23:09:03 -07001620 }
1621 }
1622
1623 private void updateUserSwitchInProcess(int requestId, @UserIdInt int targetUserId) {
1624 synchronized (mLockUser) {
1625 if (mUserIdForUserSwitchInProcess != UserHandle.USER_NULL) {
1626 // Some other user switch is in process.
Eric Jeongf75d4132020-12-21 13:48:23 -08001627 if (Log.isLoggable(TAG, Log.DEBUG)) {
1628 Slog.d(TAG, "User switch for user: " + mUserIdForUserSwitchInProcess
Mayank Garg6307fe42020-04-15 23:09:03 -07001629 + " is in process. Abandoning it as a new user switch is requested"
1630 + " for the target user: " + targetUserId);
1631 }
1632 }
1633 mUserIdForUserSwitchInProcess = targetUserId;
1634 mRequestIdForUserSwitchInProcess = requestId;
1635 }
1636 }
Mayank Garg9ed099e2020-06-04 16:05:20 -07001637
Mayank Garg7a114c82020-04-08 21:25:06 -07001638 private void postSwitchHalResponse(int requestId, @UserIdInt int targetUserId) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001639 if (!isUserHalSupported()) return;
1640
felipealdfdf8512020-06-01 09:35:45 -07001641 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
Mayank Gargeb37d092020-06-02 14:37:57 -07001642 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_POST_SWITCH_USER_REQ, requestId,
1643 targetUserId, usersInfo.currentUser.userId);
1644 SwitchUserRequest request = createUserSwitchRequest(targetUserId, usersInfo);
1645 request.requestId = requestId;
1646 mHal.postSwitchResponse(request);
1647 }
1648
1649 private SwitchUserRequest createUserSwitchRequest(@UserIdInt int targetUserId,
1650 @NonNull UsersInfo usersInfo) {
1651 UserInfo targetUser = mUserManager.getUserInfo(targetUserId);
Mayank Garg7a114c82020-04-08 21:25:06 -07001652 android.hardware.automotive.vehicle.V2_0.UserInfo halTargetUser =
1653 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1654 halTargetUser.userId = targetUser.id;
1655 halTargetUser.flags = UserHalHelper.convertFlags(targetUser);
Mayank Gargeb37d092020-06-02 14:37:57 -07001656 SwitchUserRequest request = new SwitchUserRequest();
1657 request.targetUser = halTargetUser;
1658 request.usersInfo = usersInfo;
1659 return request;
Mayank Garg7a114c82020-04-08 21:25:06 -07001660 }
1661
Mayank Garg59f22192020-03-27 00:51:45 -07001662 /**
Felipe Lemee3cab982020-03-12 11:39:29 -07001663 * Checks if the User HAL is supported.
1664 */
1665 public boolean isUserHalSupported() {
1666 return mHal.isSupported();
1667 }
1668
Mayank Garg587f1942020-05-06 01:41:34 -07001669 /**
Mayank Garg9ed099e2020-06-04 16:05:20 -07001670 * Checks if the User HAL user association is supported.
1671 */
1672 @Override
1673 public boolean isUserHalUserAssociationSupported() {
1674 return mHal.isUserAssociationSupported();
1675 }
1676
1677 /**
Mayank Garg587f1942020-05-06 01:41:34 -07001678 * Sets a callback which is invoked before user switch.
1679 *
1680 * <p>
1681 * This method should only be called by the Car System UI. The purpose of this call is to notify
1682 * Car System UI to show the user switch UI before the user switch.
1683 */
1684 @Override
1685 public void setUserSwitchUiCallback(@NonNull IResultReceiver receiver) {
Yan Zhu67a383e2020-05-11 20:46:24 -07001686 checkManageUsersPermission("setUserSwitchUiCallback");
Mayank Garga480dd92020-05-14 03:14:57 -07001687
1688 // Confirm that caller is system UI.
1689 String systemUiPackageName = getSystemUiPackageName();
1690 if (systemUiPackageName == null) {
1691 throw new IllegalStateException("System UI package not found.");
1692 }
1693
1694 try {
1695 int systemUiUid = mContext
1696 .createContextAsUser(UserHandle.SYSTEM, /* flags= */ 0).getPackageManager()
1697 .getPackageUid(systemUiPackageName, PackageManager.MATCH_SYSTEM_ONLY);
1698 int callerUid = Binder.getCallingUid();
1699 if (systemUiUid != callerUid) {
1700 throw new SecurityException("Invalid caller. Only" + systemUiPackageName
1701 + " is allowed to make this call");
1702 }
1703 } catch (NameNotFoundException e) {
1704 throw new IllegalStateException("Package " + systemUiPackageName + " not found.");
1705 }
1706
Mayank Garg587f1942020-05-06 01:41:34 -07001707 mUserSwitchUiReceiver = receiver;
1708 }
1709
Mayank Garga480dd92020-05-14 03:14:57 -07001710 // TODO(157082995): This information can be taken from
1711 // PackageManageInternalImpl.getSystemUiServiceComponent
1712 @Nullable
1713 private String getSystemUiPackageName() {
1714 try {
1715 ComponentName componentName = ComponentName.unflattenFromString(mContext.getResources()
1716 .getString(com.android.internal.R.string.config_systemUIServiceComponent));
1717 return componentName.getPackageName();
1718 } catch (RuntimeException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001719 Slog.w(TAG, "error while getting system UI package name.", e);
Mayank Garga480dd92020-05-14 03:14:57 -07001720 return null;
1721 }
1722 }
1723
Keun young Park13a7a822019-04-04 15:53:08 -07001724 private void updateDefaultUserRestriction() {
1725 // We want to set restrictions on system and guest users only once. These are persisted
1726 // onto disk, so it's sufficient to do it once + we minimize the number of disk writes.
1727 if (Settings.Global.getInt(mContext.getContentResolver(),
Eric Jeong1545f3b2019-09-16 13:56:52 -07001728 CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, /* default= */ 0) != 0) {
1729 return;
Keun young Park13a7a822019-04-04 15:53:08 -07001730 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07001731 // Only apply the system user restrictions if the system user is headless.
1732 if (UserManager.isHeadlessSystemUserMode()) {
1733 setSystemUserRestrictions();
1734 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07001735 Settings.Global.putInt(mContext.getContentResolver(),
1736 CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, 1);
Keun young Park13a7a822019-04-04 15:53:08 -07001737 }
1738
Eric Jeong1545f3b2019-09-16 13:56:52 -07001739 private boolean isPersistentUser(@UserIdInt int userId) {
Anthony Hugh9932a252019-06-12 16:19:56 -07001740 return !mUserManager.getUserInfo(userId).isEphemeral();
1741 }
1742
Antonio Kantekc8114752020-03-05 21:37:39 -08001743 /**
Antonio Kantekc8114752020-03-05 21:37:39 -08001744 * Adds a new {@link UserLifecycleListener} to listen to user activity events.
1745 */
1746 public void addUserLifecycleListener(@NonNull UserLifecycleListener listener) {
1747 Objects.requireNonNull(listener, "listener cannot be null");
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001748 mHandler.post(() -> mUserLifecycleListeners.add(listener));
Antonio Kantekc8114752020-03-05 21:37:39 -08001749 }
1750
1751 /**
1752 * Removes previously added {@link UserLifecycleListener}.
1753 */
1754 public void removeUserLifecycleListener(@NonNull UserLifecycleListener listener) {
1755 Objects.requireNonNull(listener, "listener cannot be null");
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001756 mHandler.post(() -> mUserLifecycleListeners.remove(listener));
Antonio Kantekc8114752020-03-05 21:37:39 -08001757 }
1758
Eric Jeongc91f9452019-08-30 15:04:21 -07001759 /** Adds callback to listen to passenger activity events. */
1760 public void addPassengerCallback(@NonNull PassengerCallback callback) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00001761 Objects.requireNonNull(callback, "callback cannot be null");
Eric Jeongc91f9452019-08-30 15:04:21 -07001762 mPassengerCallbacks.add(callback);
1763 }
1764
1765 /** Removes previously added callback to listen passenger events. */
1766 public void removePassengerCallback(@NonNull PassengerCallback callback) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00001767 Objects.requireNonNull(callback, "callback cannot be null");
Eric Jeongc91f9452019-08-30 15:04:21 -07001768 mPassengerCallbacks.remove(callback);
1769 }
1770
1771 /** Sets the implementation of ZoneUserBindingHelper. */
1772 public void setZoneUserBindingHelper(@NonNull ZoneUserBindingHelper helper) {
1773 synchronized (mLockHelper) {
1774 mZoneUserBindingHelper = helper;
1775 }
1776 }
1777
felipeal98900c82020-04-09 09:05:02 -07001778 private void onUserUnlocked(@UserIdInt int userId) {
Keun-young Parkd462a912019-02-11 08:53:42 -08001779 ArrayList<Runnable> tasks = null;
Eric Jeongc91f9452019-08-30 15:04:21 -07001780 synchronized (mLockUser) {
Mayank Garg7a114c82020-04-08 21:25:06 -07001781 sendPostSwitchToHalLocked(userId);
Eric Jeong1545f3b2019-09-16 13:56:52 -07001782 if (userId == UserHandle.USER_SYSTEM) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001783 if (!mUser0Unlocked) { // user 0, unlocked, do this only once
1784 updateDefaultUserRestriction();
1785 tasks = new ArrayList<>(mUser0UnlockTasks);
1786 mUser0UnlockTasks.clear();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001787 mUser0Unlocked = true;
Keun young Parkf3523cd2019-04-08 10:09:17 -07001788 }
1789 } else { // none user0
Eric Jeong1545f3b2019-09-16 13:56:52 -07001790 Integer user = userId;
1791 if (isPersistentUser(userId)) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001792 // current foreground user should stay in top priority.
Anthony Hughfbb67762019-10-15 12:54:54 -07001793 if (userId == ActivityManager.getCurrentUser()) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001794 mBackgroundUsersToRestart.remove(user);
1795 mBackgroundUsersToRestart.add(0, user);
1796 }
1797 // -1 for user 0
1798 if (mBackgroundUsersToRestart.size() > (mMaxRunningUsers - 1)) {
Eric Jeong1545f3b2019-09-16 13:56:52 -07001799 int userToDrop = mBackgroundUsersToRestart.get(
Keun young Parkf3523cd2019-04-08 10:09:17 -07001800 mBackgroundUsersToRestart.size() - 1);
Eric Jeongf75d4132020-12-21 13:48:23 -08001801 Slog.i(TAG, "New user unlocked:" + userId
Keun young Parkf3523cd2019-04-08 10:09:17 -07001802 + ", dropping least recently user from restart list:" + userToDrop);
1803 // Drop the least recently used user.
1804 mBackgroundUsersToRestart.remove(mBackgroundUsersToRestart.size() - 1);
1805 }
1806 }
Keun-young Parkd462a912019-02-11 08:53:42 -08001807 }
1808 }
1809 if (tasks != null && tasks.size() > 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001810 Slog.d(TAG, "User0 unlocked, run queued tasks:" + tasks.size());
Keun-young Parkd462a912019-02-11 08:53:42 -08001811 for (Runnable r : tasks) {
1812 r.run();
1813 }
1814 }
1815 }
1816
1817 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -07001818 * Starts all background users that were active in system.
1819 *
Keun young Parkfb656372019-03-12 18:37:55 -07001820 * @return list of background users started successfully.
1821 */
Eric Jeong1545f3b2019-09-16 13:56:52 -07001822 @NonNull
Keun young Parkfb656372019-03-12 18:37:55 -07001823 public ArrayList<Integer> startAllBackgroundUsers() {
1824 ArrayList<Integer> users;
Eric Jeongc91f9452019-08-30 15:04:21 -07001825 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001826 users = new ArrayList<>(mBackgroundUsersToRestart);
1827 mBackgroundUsersRestartedHere.clear();
1828 mBackgroundUsersRestartedHere.addAll(mBackgroundUsersToRestart);
Keun young Parkfb656372019-03-12 18:37:55 -07001829 }
1830 ArrayList<Integer> startedUsers = new ArrayList<>();
1831 for (Integer user : users) {
Anthony Hughfbb67762019-10-15 12:54:54 -07001832 if (user == ActivityManager.getCurrentUser()) {
Keun young Parkfb656372019-03-12 18:37:55 -07001833 continue;
1834 }
1835 try {
1836 if (mAm.startUserInBackground(user)) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001837 if (mUserManager.isUserUnlockingOrUnlocked(user)) {
1838 // already unlocked / unlocking. No need to unlock.
Keun young Parkfb656372019-03-12 18:37:55 -07001839 startedUsers.add(user);
Keun young Parkf3523cd2019-04-08 10:09:17 -07001840 } else if (mAm.unlockUser(user, null, null, null)) {
1841 startedUsers.add(user);
1842 } else { // started but cannot unlock
Eric Jeongf75d4132020-12-21 13:48:23 -08001843 Slog.w(TAG, "Background user started but cannot be unlocked:" + user);
Keun young Parkf3523cd2019-04-08 10:09:17 -07001844 if (mUserManager.isUserRunning(user)) {
1845 // add to started list so that it can be stopped later.
1846 startedUsers.add(user);
1847 }
Keun young Parkfb656372019-03-12 18:37:55 -07001848 }
1849 }
1850 } catch (RemoteException e) {
1851 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001852 Slog.w(TAG, "error while starting user in background", e);
Keun young Parkfb656372019-03-12 18:37:55 -07001853 }
1854 }
Keun young Parkf3523cd2019-04-08 10:09:17 -07001855 // Keep only users that were re-started in mBackgroundUsersRestartedHere
Eric Jeongc91f9452019-08-30 15:04:21 -07001856 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001857 ArrayList<Integer> usersToRemove = new ArrayList<>();
1858 for (Integer user : mBackgroundUsersToRestart) {
1859 if (!startedUsers.contains(user)) {
1860 usersToRemove.add(user);
1861 }
1862 }
1863 mBackgroundUsersRestartedHere.removeAll(usersToRemove);
1864 }
Keun young Parkfb656372019-03-12 18:37:55 -07001865 return startedUsers;
1866 }
1867
1868 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -07001869 * Stops all background users that were active in system.
1870 *
1871 * @return whether stopping succeeds.
Keun young Parkfb656372019-03-12 18:37:55 -07001872 */
Eric Jeong1545f3b2019-09-16 13:56:52 -07001873 public boolean stopBackgroundUser(@UserIdInt int userId) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001874 if (userId == UserHandle.USER_SYSTEM) {
1875 return false;
1876 }
Anthony Hughfbb67762019-10-15 12:54:54 -07001877 if (userId == ActivityManager.getCurrentUser()) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001878 Slog.i(TAG, "stopBackgroundUser, already a FG user:" + userId);
Keun young Parkfb656372019-03-12 18:37:55 -07001879 return false;
1880 }
1881 try {
Keun young Parked9e6282019-09-19 17:38:26 -07001882 int r = mAm.stopUserWithDelayedLocking(userId, true, null);
Keun young Parkf3523cd2019-04-08 10:09:17 -07001883 if (r == ActivityManager.USER_OP_SUCCESS) {
Eric Jeongc91f9452019-08-30 15:04:21 -07001884 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001885 Integer user = userId;
1886 mBackgroundUsersRestartedHere.remove(user);
1887 }
1888 } else if (r == ActivityManager.USER_OP_IS_CURRENT) {
1889 return false;
1890 } else {
Eric Jeongf75d4132020-12-21 13:48:23 -08001891 Slog.i(TAG, "stopBackgroundUser failed, user:" + userId + " err:" + r);
Keun young Parkfb656372019-03-12 18:37:55 -07001892 return false;
1893 }
1894 } catch (RemoteException e) {
1895 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001896 Slog.w(TAG, "error while stopping user", e);
Keun young Parkfb656372019-03-12 18:37:55 -07001897 }
1898 return true;
1899 }
1900
1901 /**
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001902 * Notifies all registered {@link UserLifecycleListener} with the event passed as argument.
Pavel Maltsev17e81832019-04-04 14:38:41 -07001903 */
Mayank Gargccad8062020-08-30 15:05:10 -07001904 public void onUserLifecycleEvent(@UserLifecycleEventType int eventType,
felipeale8c5dce2020-04-15 11:27:06 -07001905 @UserIdInt int fromUserId, @UserIdInt int toUserId) {
1906 int userId = toUserId;
felipeal98900c82020-04-09 09:05:02 -07001907
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001908 // Handle special cases first...
felipeal98900c82020-04-09 09:05:02 -07001909 if (eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING) {
Mayank Garge5de0f92020-04-23 21:38:38 -07001910 onUserSwitching(fromUserId, toUserId);
felipeal98900c82020-04-09 09:05:02 -07001911 } else if (eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_UNLOCKED) {
1912 onUserUnlocked(userId);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001913 }
1914
felipeale8c5dce2020-04-15 11:27:06 -07001915 // ...then notify listeners.
Yan Zhue7921522020-04-16 15:59:25 -07001916 UserLifecycleEvent event = new UserLifecycleEvent(eventType, fromUserId, userId);
felipeale8c5dce2020-04-15 11:27:06 -07001917
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001918 mHandler.post(() -> {
1919 handleNotifyServiceUserLifecycleListeners(event);
1920 handleNotifyAppUserLifecycleListeners(event);
1921 });
felipeale8c5dce2020-04-15 11:27:06 -07001922 }
1923
Mayank Garg7a114c82020-04-08 21:25:06 -07001924 private void sendPostSwitchToHalLocked(@UserIdInt int userId) {
felipealf7368962020-04-16 12:55:19 -07001925 if (mUserIdForUserSwitchInProcess == UserHandle.USER_NULL
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001926 || mUserIdForUserSwitchInProcess != userId
1927 || mRequestIdForUserSwitchInProcess == 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001928 if (Log.isLoggable(TAG, Log.DEBUG)) {
1929 Slog.d(TAG, "No user switch request Id. No android post switch sent.");
Mayank Garg7a114c82020-04-08 21:25:06 -07001930 }
1931 return;
1932 }
felipealf7368962020-04-16 12:55:19 -07001933 postSwitchHalResponse(mRequestIdForUserSwitchInProcess, mUserIdForUserSwitchInProcess);
1934 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001935 mRequestIdForUserSwitchInProcess = 0;
Mayank Garg7a114c82020-04-08 21:25:06 -07001936 }
1937
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001938 private void handleNotifyAppUserLifecycleListeners(UserLifecycleEvent event) {
1939 int listenersSize = mAppLifecycleListeners.size();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001940 if (listenersSize == 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001941 if (Log.isLoggable(TAG, Log.DEBUG)) {
1942 Slog.d(TAG, "No app listener to be notified of " + event);
felipeal2a84d512020-04-06 18:52:15 -07001943 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001944 return;
1945 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001946 // Must use a different TimingsTraceLog because it's another thread
Eric Jeongf75d4132020-12-21 13:48:23 -08001947 if (Log.isLoggable(TAG, Log.DEBUG)) {
1948 Slog.d(TAG, "Notifying " + listenersSize + " app listeners of " + event);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001949 }
felipeal2a84d512020-04-06 18:52:15 -07001950 int userId = event.getUserId();
Eric Jeongf75d4132020-12-21 13:48:23 -08001951 TimingsTraceLog t = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
felipealde1e16d2020-06-03 13:20:48 -07001952 int eventType = event.getEventType();
1953 t.traceBegin("notify-app-listeners-user-" + userId + "-event-" + eventType);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001954 for (int i = 0; i < listenersSize; i++) {
1955 int uid = mAppLifecycleListeners.keyAt(i);
felipealde1e16d2020-06-03 13:20:48 -07001956
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001957 IResultReceiver listener = mAppLifecycleListeners.valueAt(i);
1958 Bundle data = new Bundle();
felipealde1e16d2020-06-03 13:20:48 -07001959 data.putInt(CarUserManager.BUNDLE_PARAM_ACTION, eventType);
Yan Zhue7921522020-04-16 15:59:25 -07001960
felipealde1e16d2020-06-03 13:20:48 -07001961 int fromUserId = event.getPreviousUserId();
1962 if (fromUserId != UserHandle.USER_NULL) {
1963 data.putInt(CarUserManager.BUNDLE_PARAM_PREVIOUS_USER_ID, fromUserId);
Yan Zhue7921522020-04-16 15:59:25 -07001964 }
1965
Eric Jeongf75d4132020-12-21 13:48:23 -08001966 if (Log.isLoggable(TAG, Log.DEBUG)) {
1967 Slog.d(TAG, "Notifying listener for uid " + uid);
felipeal2a84d512020-04-06 18:52:15 -07001968 }
felipealde1e16d2020-06-03 13:20:48 -07001969 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_NOTIFY_APP_LIFECYCLE_LISTENER,
1970 uid, eventType, fromUserId, userId);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001971 try {
felipealde1e16d2020-06-03 13:20:48 -07001972 t.traceBegin("notify-app-listener-uid-" + uid);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001973 listener.send(userId, data);
1974 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001975 Slog.e(TAG, "Error calling lifecycle listener", e);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001976 } finally {
1977 t.traceEnd();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001978 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001979 }
1980 t.traceEnd(); // notify-app-listeners-user-USERID-event-EVENT_TYPE
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001981 }
1982
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001983 private void handleNotifyServiceUserLifecycleListeners(UserLifecycleEvent event) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001984 TimingsTraceLog t = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001985 if (mUserLifecycleListeners.isEmpty()) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001986 Slog.w(TAG, "Not notifying internal UserLifecycleListeners");
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001987 return;
Eric Jeongf75d4132020-12-21 13:48:23 -08001988 } else if (Log.isLoggable(TAG, Log.DEBUG)) {
1989 Slog.d(TAG, "Notifying " + mUserLifecycleListeners.size()
1990 + " service listeners of " + event);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001991 }
felipeal2a84d512020-04-06 18:52:15 -07001992
felipealde1e16d2020-06-03 13:20:48 -07001993 int userId = event.getUserId();
1994 int eventType = event.getEventType();
1995 t.traceBegin("notify-listeners-user-" + userId + "-event-" + eventType);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001996 for (UserLifecycleListener listener : mUserLifecycleListeners) {
felipeal2a84d512020-04-06 18:52:15 -07001997 String listenerName = FunctionalUtils.getLambdaName(listener);
felipealde1e16d2020-06-03 13:20:48 -07001998 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_NOTIFY_INTERNAL_LIFECYCLE_LISTENER,
1999 listenerName, eventType, event.getPreviousUserId(), userId);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002000 try {
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002001 t.traceBegin("notify-listener-" + listenerName);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002002 listener.onEvent(event);
2003 } catch (RuntimeException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002004 Slog.e(TAG,
felipeal2a84d512020-04-06 18:52:15 -07002005 "Exception raised when invoking onEvent for " + listenerName, e);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002006 } finally {
2007 t.traceEnd();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002008 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002009 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002010 t.traceEnd(); // notify-listeners-user-USERID-event-EVENT_TYPE
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002011 }
2012
Mayank Garge5de0f92020-04-23 21:38:38 -07002013 private void onUserSwitching(@UserIdInt int fromUserId, @UserIdInt int toUserId) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002014 Slog.i(TAG, "onUserSwitching() callback for user " + toUserId);
2015 TimingsTraceLog t = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
Mayank Garge5de0f92020-04-23 21:38:38 -07002016 t.traceBegin("onUserSwitching-" + toUserId);
Felipe Leme5528ff72020-02-10 19:05:14 -08002017
Mayank Garge5de0f92020-04-23 21:38:38 -07002018 // Switch HAL users if user switch is not requested by CarUserService
2019 notifyHalLegacySwitch(fromUserId, toUserId);
2020
Mayank Garge90a4082020-09-30 12:57:34 -07002021 mInitialUserSetter.setLastActiveUser(toUserId);
felipealbf327652020-06-03 11:33:29 -07002022
Eric Jeongc91f9452019-08-30 15:04:21 -07002023 if (mLastPassengerId != UserHandle.USER_NULL) {
2024 stopPassengerInternal(mLastPassengerId, false);
2025 }
2026 if (mEnablePassengerSupport && isPassengerDisplayAvailable()) {
2027 setupPassengerUser();
Mayank Garge5de0f92020-04-23 21:38:38 -07002028 startFirstPassenger(toUserId);
Eric Jeongc91f9452019-08-30 15:04:21 -07002029 }
felipeal98900c82020-04-09 09:05:02 -07002030 t.traceEnd();
Pavel Maltsev17e81832019-04-04 14:38:41 -07002031 }
2032
Mayank Garge5de0f92020-04-23 21:38:38 -07002033 private void notifyHalLegacySwitch(@UserIdInt int fromUserId, @UserIdInt int toUserId) {
2034 synchronized (mLockUser) {
felipeal7d12ee22020-06-05 09:30:19 -07002035 if (mUserIdForUserSwitchInProcess != UserHandle.USER_NULL) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002036 if (Log.isLoggable(TAG, Log.DEBUG)) {
2037 Slog.d(TAG, "notifyHalLegacySwitch(" + fromUserId + ", " + toUserId
felipeal7d12ee22020-06-05 09:30:19 -07002038 + "): not needed, normal switch for " + mUserIdForUserSwitchInProcess);
2039 }
2040 return;
2041 }
Mayank Garge5de0f92020-04-23 21:38:38 -07002042 }
2043
Mayank Garg9ed099e2020-06-04 16:05:20 -07002044 if (!isUserHalSupported()) return;
2045
Mayank Garge5de0f92020-04-23 21:38:38 -07002046 // switch HAL user
felipeal7d12ee22020-06-05 09:30:19 -07002047 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager, fromUserId);
Mayank Gargeb37d092020-06-02 14:37:57 -07002048 SwitchUserRequest request = createUserSwitchRequest(toUserId, usersInfo);
2049 mHal.legacyUserSwitch(request);
Mayank Garge5de0f92020-04-23 21:38:38 -07002050 }
2051
Pavel Maltsev17e81832019-04-04 14:38:41 -07002052 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -07002053 * 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 -08002054 * run inside this call.
Eric Jeong1545f3b2019-09-16 13:56:52 -07002055 *
Keun-young Parkd462a912019-02-11 08:53:42 -08002056 * @param r Runnable to run.
2057 */
Eric Jeong1545f3b2019-09-16 13:56:52 -07002058 public void runOnUser0Unlock(@NonNull Runnable r) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00002059 Objects.requireNonNull(r, "runnable cannot be null");
Keun-young Parkd462a912019-02-11 08:53:42 -08002060 boolean runNow = false;
Eric Jeongc91f9452019-08-30 15:04:21 -07002061 synchronized (mLockUser) {
Keun-young Parkd462a912019-02-11 08:53:42 -08002062 if (mUser0Unlocked) {
2063 runNow = true;
2064 } else {
2065 mUser0UnlockTasks.add(r);
2066 }
2067 }
2068 if (runNow) {
2069 r.run();
2070 }
2071 }
2072
Keun young Parkf3523cd2019-04-08 10:09:17 -07002073 @VisibleForTesting
Eric Jeong1545f3b2019-09-16 13:56:52 -07002074 @NonNull
2075 ArrayList<Integer> getBackgroundUsersToRestart() {
2076 ArrayList<Integer> backgroundUsersToRestart = null;
Eric Jeongc91f9452019-08-30 15:04:21 -07002077 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07002078 backgroundUsersToRestart = new ArrayList<>(mBackgroundUsersToRestart);
2079 }
2080 return backgroundUsersToRestart;
2081 }
2082
Ying Zheng1ab32b62018-06-26 12:47:26 -07002083 private void setSystemUserRestrictions() {
Ying Zheng1ab32b62018-06-26 12:47:26 -07002084 // Disable Location service for system user.
2085 LocationManager locationManager =
2086 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
Anthony Hugh04ee04f2019-12-17 16:11:33 -08002087 locationManager.setLocationEnabledForUser(
2088 /* enabled= */ false, UserHandle.of(UserHandle.USER_SYSTEM));
Ying Zheng1ab32b62018-06-26 12:47:26 -07002089 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07002090
2091 /**
Anthony Hugh6fed1e92019-10-22 16:22:03 -07002092 * Assigns a default icon to a user according to the user's id.
2093 *
2094 * @param userInfo User whose avatar is set to default icon.
Anthony Hugh6fed1e92019-10-22 16:22:03 -07002095 */
Eric Jeongb2dc6ff2020-06-05 17:00:26 -07002096 private void assignDefaultIcon(UserInfo userInfo) {
Anthony Hugh6fed1e92019-10-22 16:22:03 -07002097 int idForIcon = userInfo.isGuest() ? UserHandle.USER_NULL : userInfo.id;
2098 Bitmap bitmap = UserIcons.convertToBitmap(
2099 UserIcons.getDefaultUserIcon(mContext.getResources(), idForIcon, false));
2100 mUserManager.setUserIcon(userInfo.id, bitmap);
Anthony Hugh6fed1e92019-10-22 16:22:03 -07002101 }
2102
Eric Jeong1545f3b2019-09-16 13:56:52 -07002103 private interface UserFilter {
2104 boolean isEligibleUser(UserInfo user);
2105 }
2106
2107 /** Returns all users who are matched by the given filter. */
2108 private List<UserInfo> getUsers(UserFilter filter) {
Colin Cross0df71ea2020-08-27 04:12:26 +00002109 List<UserInfo> users = mUserManager.getAliveUsers();
Eric Jeong1545f3b2019-09-16 13:56:52 -07002110
2111 for (Iterator<UserInfo> iterator = users.iterator(); iterator.hasNext(); ) {
2112 UserInfo user = iterator.next();
2113 if (!filter.isEligibleUser(user)) {
2114 iterator.remove();
2115 }
2116 }
2117 return users;
2118 }
2119
felipeal2d0483c2019-11-02 14:07:22 -07002120 private static void checkManageUsersOrDumpPermission(String message) {
Felipe Leme55236722020-10-16 16:54:32 -07002121 checkHasAtLeastOnePermissionGranted(message,
felipeal2d0483c2019-11-02 14:07:22 -07002122 android.Manifest.permission.MANAGE_USERS,
2123 android.Manifest.permission.DUMP);
2124 }
2125
Felipe Leme5528ff72020-02-10 19:05:14 -08002126 private void checkInteractAcrossUsersPermission(String message) {
Felipe Leme55236722020-10-16 16:54:32 -07002127 checkHasAtLeastOnePermissionGranted(message,
2128 android.Manifest.permission.INTERACT_ACROSS_USERS,
Felipe Leme5528ff72020-02-10 19:05:14 -08002129 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
2130 }
2131
Eric Jeongc91f9452019-08-30 15:04:21 -07002132 private int getNumberOfManagedProfiles(@UserIdInt int userId) {
Colin Cross0df71ea2020-08-27 04:12:26 +00002133 List<UserInfo> users = mUserManager.getAliveUsers();
Eric Jeongc91f9452019-08-30 15:04:21 -07002134 // Count all users that are managed profiles of the given user.
2135 int managedProfilesCount = 0;
2136 for (UserInfo user : users) {
2137 if (user.isManagedProfile() && user.profileGroupId == userId) {
2138 managedProfilesCount++;
2139 }
2140 }
2141 return managedProfilesCount;
2142 }
2143
2144 /**
2145 * Starts the first passenger of the given driver and assigns the passenger to the front
2146 * passenger zone.
2147 *
2148 * @param driverId User id of the driver.
2149 * @return whether it succeeds.
2150 */
2151 private boolean startFirstPassenger(@UserIdInt int driverId) {
2152 int zoneId = getAvailablePassengerZone();
2153 if (zoneId == OccupantZoneInfo.INVALID_ZONE_ID) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002154 Slog.w(TAG, "passenger occupant zone is not found");
Eric Jeongc91f9452019-08-30 15:04:21 -07002155 return false;
2156 }
2157 List<UserInfo> passengers = getPassengers(driverId);
2158 if (passengers.size() < 1) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002159 Slog.w(TAG, "passenger is not found");
Eric Jeongc91f9452019-08-30 15:04:21 -07002160 return false;
2161 }
2162 // Only one passenger is supported. If there are two or more passengers, the first passenger
2163 // is chosen.
2164 int passengerId = passengers.get(0).id;
2165 if (!startPassenger(passengerId, zoneId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002166 Slog.w(TAG, "cannot start passenger " + passengerId);
Eric Jeongc91f9452019-08-30 15:04:21 -07002167 return false;
2168 }
2169 return true;
2170 }
2171
2172 private int getAvailablePassengerZone() {
2173 int[] occupantTypes = new int[] {CarOccupantZoneManager.OCCUPANT_TYPE_FRONT_PASSENGER,
2174 CarOccupantZoneManager.OCCUPANT_TYPE_REAR_PASSENGER};
2175 for (int occupantType : occupantTypes) {
2176 int zoneId = getZoneId(occupantType);
2177 if (zoneId != OccupantZoneInfo.INVALID_ZONE_ID) {
2178 return zoneId;
2179 }
2180 }
2181 return OccupantZoneInfo.INVALID_ZONE_ID;
2182 }
2183
2184 /**
2185 * Creates a new passenger user when there is no passenger user.
2186 */
2187 private void setupPassengerUser() {
2188 int currentUser = ActivityManager.getCurrentUser();
2189 int profileCount = getNumberOfManagedProfiles(currentUser);
2190 if (profileCount > 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002191 Slog.w(TAG, "max profile of user" + currentUser
Eric Jeongc91f9452019-08-30 15:04:21 -07002192 + " is exceeded: current profile count is " + profileCount);
2193 return;
2194 }
2195 // TODO(b/140311342): Use resource string for the default passenger name.
2196 UserInfo passenger = createPassenger("Passenger", currentUser);
2197 if (passenger == null) {
2198 // Couldn't create user, most likely because there are too many.
Eric Jeongf75d4132020-12-21 13:48:23 -08002199 Slog.w(TAG, "cannot create a passenger user");
Eric Jeongc91f9452019-08-30 15:04:21 -07002200 return;
2201 }
2202 }
2203
2204 @NonNull
2205 private List<OccupantZoneInfo> getOccupantZones(@OccupantTypeEnum int occupantType) {
2206 ZoneUserBindingHelper helper = null;
2207 synchronized (mLockHelper) {
2208 if (mZoneUserBindingHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002209 Slog.w(TAG, "implementation is not delegated");
Eric Jeongc91f9452019-08-30 15:04:21 -07002210 return new ArrayList<OccupantZoneInfo>();
2211 }
2212 helper = mZoneUserBindingHelper;
2213 }
2214 return helper.getOccupantZones(occupantType);
2215 }
2216
2217 private boolean assignUserToOccupantZone(@UserIdInt int userId, int zoneId) {
2218 ZoneUserBindingHelper helper = null;
2219 synchronized (mLockHelper) {
2220 if (mZoneUserBindingHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002221 Slog.w(TAG, "implementation is not delegated");
Eric Jeongc91f9452019-08-30 15:04:21 -07002222 return false;
2223 }
2224 helper = mZoneUserBindingHelper;
2225 }
2226 return helper.assignUserToOccupantZone(userId, zoneId);
2227 }
2228
2229 private boolean unassignUserFromOccupantZone(@UserIdInt int userId) {
2230 ZoneUserBindingHelper helper = null;
2231 synchronized (mLockHelper) {
2232 if (mZoneUserBindingHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002233 Slog.w(TAG, "implementation is not delegated");
Eric Jeongc91f9452019-08-30 15:04:21 -07002234 return false;
2235 }
2236 helper = mZoneUserBindingHelper;
2237 }
2238 return helper.unassignUserFromOccupantZone(userId);
2239 }
2240
2241 private boolean isPassengerDisplayAvailable() {
2242 ZoneUserBindingHelper helper = null;
2243 synchronized (mLockHelper) {
2244 if (mZoneUserBindingHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002245 Slog.w(TAG, "implementation is not delegated");
Eric Jeongc91f9452019-08-30 15:04:21 -07002246 return false;
2247 }
2248 helper = mZoneUserBindingHelper;
2249 }
2250 return helper.isPassengerDisplayAvailable();
2251 }
2252
2253 /**
2254 * Gets the zone id of the given occupant type. If there are two or more zones, the first found
2255 * zone is returned.
2256 *
2257 * @param occupantType The type of an occupant.
2258 * @return The zone id of the given occupant type. {@link OccupantZoneInfo.INVALID_ZONE_ID},
2259 * if not found.
2260 */
2261 private int getZoneId(@OccupantTypeEnum int occupantType) {
2262 List<OccupantZoneInfo> zoneInfos = getOccupantZones(occupantType);
2263 return (zoneInfos.size() > 0) ? zoneInfos.get(0).zoneId : OccupantZoneInfo.INVALID_ZONE_ID;
2264 }
Mayank Garg9732d602020-08-09 21:02:40 -07002265
2266 /**
2267 * Manages the required number of pre-created users.
2268 */
2269 public void preCreateUsers() {
2270 mUserPreCreator.managePreCreatedUsers();
2271 }
Felipe Leme17799202020-09-03 12:55:53 -07002272
2273 // TODO(b/167698977): members below were copied from UserManagerService; it would be better to
2274 // move them to some internal android.os class instead.
2275
2276 private static final int ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION =
2277 UserInfo.FLAG_MANAGED_PROFILE
2278 | UserInfo.FLAG_PROFILE
2279 | UserInfo.FLAG_EPHEMERAL
2280 | UserInfo.FLAG_RESTRICTED
2281 | UserInfo.FLAG_GUEST
2282 | UserInfo.FLAG_DEMO
2283 | UserInfo.FLAG_FULL;
2284
2285 private static void checkManageUsersPermission(String message) {
2286 if (!hasManageUsersPermission()) {
2287 throw new SecurityException("You need " + MANAGE_USERS + " permission to: " + message);
2288 }
2289 }
2290
2291 private static void checkManageOrCreateUsersPermission(String message) {
2292 if (!hasManageOrCreateUsersPermission()) {
2293 throw new SecurityException(
2294 "You either need " + MANAGE_USERS + " or " + CREATE_USERS + " permission to: "
2295 + message);
2296 }
2297 }
2298
2299 private static void checkManageOrCreateUsersPermission(int creationFlags) {
2300 if ((creationFlags & ~ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION) == 0) {
2301 if (!hasManageOrCreateUsersPermission()) {
2302 throw new SecurityException("You either need " + MANAGE_USERS + " or "
2303 + CREATE_USERS + "permission to create a user with flags "
2304 + creationFlags);
2305 }
2306 } else if (!hasManageUsersPermission()) {
2307 throw new SecurityException("You need " + MANAGE_USERS + " permission to create a user"
2308 + " with flags " + creationFlags);
2309 }
2310 }
2311
2312 private static boolean hasManageUsersPermission() {
2313 final int callingUid = Binder.getCallingUid();
2314 return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
2315 || callingUid == Process.ROOT_UID
2316 || hasPermissionGranted(MANAGE_USERS, callingUid);
2317 }
2318
2319 private static boolean hasManageUsersOrPermission(String alternativePermission) {
2320 final int callingUid = Binder.getCallingUid();
2321 return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
2322 || callingUid == Process.ROOT_UID
2323 || hasPermissionGranted(MANAGE_USERS, callingUid)
2324 || hasPermissionGranted(alternativePermission, callingUid);
2325 }
2326
2327 private static boolean hasManageOrCreateUsersPermission() {
2328 return hasManageUsersOrPermission(CREATE_USERS);
2329 }
2330
2331 private static boolean hasPermissionGranted(String permission, int uid) {
2332 return ActivityManager.checkComponentPermission(permission, uid, /* owningUid= */ -1,
2333 /* exported= */ true) == PackageManager.PERMISSION_GRANTED;
2334 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002335}