blob: a00e0b95c2faec2d71601d86a73818ea4e35cdf3 [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;
Yan Zhu65a0acd2021-06-21 10:56:53 -070025import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.DEPRECATED_CODE;
Mayank Garg578db012021-06-14 22:17:00 -070026import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.DUMP_INFO;
Eric Jeong1545f3b2019-09-16 13:56:52 -070027
28import android.annotation.NonNull;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070029import android.annotation.Nullable;
Eric Jeong1545f3b2019-09-16 13:56:52 -070030import android.annotation.UserIdInt;
Keun young Parkfb656372019-03-12 18:37:55 -070031import android.app.ActivityManager;
Louis Chang3bf2f202020-08-18 13:04:28 +080032import android.app.ActivityTaskManager.RootTaskInfo;
Keun young Parkfb656372019-03-12 18:37:55 -070033import android.app.IActivityManager;
Eric Jeongc91f9452019-08-30 15:04:21 -070034import android.car.CarOccupantZoneManager;
35import android.car.CarOccupantZoneManager.OccupantTypeEnum;
36import android.car.CarOccupantZoneManager.OccupantZoneInfo;
Eric Jeong1545f3b2019-09-16 13:56:52 -070037import android.car.ICarUserService;
Felipe Leme5d5ab142020-10-27 13:49:10 -070038import android.car.drivingstate.CarUxRestrictions;
Felipe Leme56ef9ad2020-11-05 18:39:03 -080039import android.car.drivingstate.ICarUxRestrictionsChangeListener;
jovanak24470652018-09-11 17:51:57 -070040import android.car.settings.CarSettings;
Felipe Leme5528ff72020-02-10 19:05:14 -080041import android.car.user.CarUserManager;
Mayank Garg3f566582020-10-02 22:10:16 -070042import android.car.user.CarUserManager.UserIdentificationAssociationSetValue;
43import android.car.user.CarUserManager.UserIdentificationAssociationType;
Antonio Kantekc8114752020-03-05 21:37:39 -080044import android.car.user.CarUserManager.UserLifecycleEvent;
45import android.car.user.CarUserManager.UserLifecycleListener;
felipealdfdf8512020-06-01 09:35:45 -070046import android.car.user.UserCreationResult;
felipeal159a2a42020-05-08 10:32:11 -070047import android.car.user.UserIdentificationAssociationResponse;
Mayank Garga55c3092020-05-28 03:19:24 -070048import android.car.user.UserRemovalResult;
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -070049import android.car.user.UserStartResult;
bkchoid77d0bc2021-04-22 13:43:03 -070050import android.car.user.UserStopResult;
felipeale5bf0322020-04-16 15:10:57 -070051import android.car.user.UserSwitchResult;
felipeal19e3d732020-03-18 12:07:32 -070052import android.car.userlib.HalCallback;
53import android.car.userlib.UserHalHelper;
Mayank Garge90a4082020-09-30 12:57:34 -070054import android.car.userlib.UserHelper;
Mayank Garga480dd92020-05-14 03:14:57 -070055import android.content.ComponentName;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070056import android.content.Context;
Mayank Garga480dd92020-05-14 03:14:57 -070057import android.content.pm.PackageManager;
58import android.content.pm.PackageManager.NameNotFoundException;
Eric Jeong1545f3b2019-09-16 13:56:52 -070059import android.content.pm.UserInfo;
felipealdfdf8512020-06-01 09:35:45 -070060import android.content.pm.UserInfo.UserInfoFlag;
Felipe Leme315a53b2020-03-12 10:51:04 -070061import android.content.res.Resources;
Anthony Hugh6fed1e92019-10-22 16:22:03 -070062import android.graphics.Bitmap;
felipealdfdf8512020-06-01 09:35:45 -070063import android.hardware.automotive.vehicle.V2_0.CreateUserRequest;
64import android.hardware.automotive.vehicle.V2_0.CreateUserStatus;
Mayank Garg70732a82020-08-05 20:17:47 -070065import android.hardware.automotive.vehicle.V2_0.InitialUserInfoRequestType;
Felipe Lemec6e3c2a2020-02-19 16:53:57 -080066import android.hardware.automotive.vehicle.V2_0.InitialUserInfoResponseAction;
Mayank Garga55c3092020-05-28 03:19:24 -070067import android.hardware.automotive.vehicle.V2_0.RemoveUserRequest;
Mayank Gargeb37d092020-06-02 14:37:57 -070068import android.hardware.automotive.vehicle.V2_0.SwitchUserRequest;
Mayank Garg59f22192020-03-27 00:51:45 -070069import android.hardware.automotive.vehicle.V2_0.SwitchUserStatus;
felipeal5e3ede42020-04-23 18:04:07 -070070import android.hardware.automotive.vehicle.V2_0.UserIdentificationGetRequest;
71import android.hardware.automotive.vehicle.V2_0.UserIdentificationResponse;
felipeal159a2a42020-05-08 10:32:11 -070072import android.hardware.automotive.vehicle.V2_0.UserIdentificationSetAssociation;
73import android.hardware.automotive.vehicle.V2_0.UserIdentificationSetRequest;
Felipe Lemec6e3c2a2020-02-19 16:53:57 -080074import android.hardware.automotive.vehicle.V2_0.UsersInfo;
Ying Zheng1ab32b62018-06-26 12:47:26 -070075import android.location.LocationManager;
Eric Jeong1545f3b2019-09-16 13:56:52 -070076import android.os.Binder;
Felipe Leme5528ff72020-02-10 19:05:14 -080077import android.os.Bundle;
Antonio Kantek7236a5b2020-04-06 19:53:55 -070078import android.os.Handler;
79import android.os.HandlerThread;
Felipe Lemefaf67042021-07-08 11:24:00 -070080import android.os.IBinder;
Felipe Leme17799202020-09-03 12:55:53 -070081import android.os.Process;
Keun young Parkfb656372019-03-12 18:37:55 -070082import android.os.RemoteException;
Mayank Garg31e73042020-01-23 00:10:38 -080083import android.os.Trace;
Ying Zhengcf20f442018-06-22 16:54:51 -070084import android.os.UserHandle;
Ying Zheng8f90edb2018-06-13 12:42:31 -070085import android.os.UserManager;
jovanak24470652018-09-11 17:51:57 -070086import android.provider.Settings;
Felipe Lemee3cab982020-03-12 11:39:29 -070087import android.sysprop.CarProperties;
felipeal159a2a42020-05-08 10:32:11 -070088import android.text.TextUtils;
Felipe Lemefaf67042021-07-08 11:24:00 -070089import android.util.ArrayMap;
felipeal312416a2020-04-14 12:28:24 -070090import android.util.EventLog;
Felipe Leme176a5fd2021-01-20 15:48:33 -080091import android.util.IndentingPrintWriter;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070092import android.util.Log;
Eric Jeongf75d4132020-12-21 13:48:23 -080093import android.util.Slog;
Felipe Leme6b34fc32020-10-26 15:49:17 -070094import android.util.SparseBooleanArray;
Mayank Garg31e73042020-01-23 00:10:38 -080095import android.util.TimingsTraceLog;
Felipe Leme56ef9ad2020-11-05 18:39:03 -080096import android.view.Display;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070097
Mayank Garg72c71d22021-02-03 23:54:45 -080098import com.android.car.CarLog;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070099import com.android.car.CarServiceBase;
Keun young Parkb241d022020-04-20 20:31:34 -0700100import com.android.car.CarServiceUtils;
Felipe Leme5d5ab142020-10-27 13:49:10 -0700101import com.android.car.CarUxRestrictionsManagerService;
Eric Jeongc91f9452019-08-30 15:04:21 -0700102import com.android.car.R;
Felipe Leme58412202020-01-09 13:45:33 -0800103import com.android.car.hal.UserHalService;
Mayank Garg578db012021-06-14 22:17:00 -0700104import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport;
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800105import com.android.car.internal.ICarServiceHelper;
Mayank Gargf59f95b2020-10-01 14:55:11 -0700106import com.android.car.internal.common.CommonConstants.UserLifecycleEventType;
Mayank Garg801ea6a2020-09-29 15:43:49 -0700107import com.android.car.internal.common.EventLogTags;
108import com.android.car.internal.common.UserHelperLite;
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700109import com.android.car.power.CarPowerManagementService;
Mayank Garg665c20b2020-08-07 16:19:28 -0700110import com.android.car.user.InitialUserSetter.InitialUserInfo;
Keun-young Parkd462a912019-02-11 08:53:42 -0800111import com.android.internal.annotations.GuardedBy;
Keun young Parkf3523cd2019-04-08 10:09:17 -0700112import com.android.internal.annotations.VisibleForTesting;
felipeale5bf0322020-04-16 15:10:57 -0700113import com.android.internal.infra.AndroidFuture;
Felipe Leme5528ff72020-02-10 19:05:14 -0800114import com.android.internal.os.IResultReceiver;
felipeal5e3ede42020-04-23 18:04:07 -0700115import com.android.internal.util.ArrayUtils;
felipeal2a84d512020-04-06 18:52:15 -0700116import com.android.internal.util.FunctionalUtils;
Mayank Garge19c2922020-03-30 18:05:53 -0700117import com.android.internal.util.Preconditions;
Anthony Hugh6fed1e92019-10-22 16:22:03 -0700118import com.android.internal.util.UserIcons;
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -0700119import com.android.server.utils.Slogf;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700120
121import java.io.PrintWriter;
Keun-young Parkd462a912019-02-11 08:53:42 -0800122import java.util.ArrayList;
felipeal2d0483c2019-11-02 14:07:22 -0700123import java.util.Arrays;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700124import java.util.Iterator;
125import java.util.List;
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +0000126import java.util.Objects;
Pavel Maltsev17e81832019-04-04 14:38:41 -0700127import java.util.concurrent.CopyOnWriteArrayList;
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700128import java.util.concurrent.CountDownLatch;
129import java.util.concurrent.TimeUnit;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700130
131/**
132 * User service for cars. Manages users at boot time. Including:
133 *
134 * <ol>
Eric Jeong1545f3b2019-09-16 13:56:52 -0700135 * <li> Creates a user used as driver.
136 * <li> Creates a user used as passenger.
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700137 * <li> Creates a secondary admin user on first run.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700138 * <li> Switch drivers.
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700139 * <ol/>
140 */
Eric Jeong1545f3b2019-09-16 13:56:52 -0700141public final class CarUserService extends ICarUserService.Stub implements CarServiceBase {
Felipe Leme5528ff72020-02-10 19:05:14 -0800142
Mayank Garg72c71d22021-02-03 23:54:45 -0800143 private static final String TAG = CarLog.tagFor(CarUserService.class);
felipealf7368962020-04-16 12:55:19 -0700144
Felipe Lemeabbf2da2020-02-24 18:25:29 -0800145 /** {@code int} extra used to represent a user id in a {@link IResultReceiver} response. */
Mayank Garg8f932822020-09-17 16:09:12 -0700146 public static final String BUNDLE_USER_ID = "user.id";
Felipe Lemeabbf2da2020-02-24 18:25:29 -0800147 /** {@code int} extra used to represent user flags in a {@link IResultReceiver} response. */
Mayank Garg8f932822020-09-17 16:09:12 -0700148 public static final String BUNDLE_USER_FLAGS = "user.flags";
Felipe Lemeabbf2da2020-02-24 18:25:29 -0800149 /** {@code String} extra used to represent a user name in a {@link IResultReceiver} response. */
Mayank Garg8f932822020-09-17 16:09:12 -0700150 public static final String BUNDLE_USER_NAME = "user.name";
felipeala68ecef2020-05-19 12:46:08 -0700151 /**
152 * {@code int} extra used to represent the user locales in a {@link IResultReceiver} response.
153 */
Mayank Garg8f932822020-09-17 16:09:12 -0700154 public static final String BUNDLE_USER_LOCALES = "user.locales";
felipeala68ecef2020-05-19 12:46:08 -0700155 /**
156 * {@code int} extra used to represent the info action in a {@link IResultReceiver} response.
157 */
Mayank Garg8f932822020-09-17 16:09:12 -0700158 public static final String BUNDLE_INITIAL_INFO_ACTION = "initial_info.action";
Felipe Leme5528ff72020-02-10 19:05:14 -0800159
Mayank Garg9ed099e2020-06-04 16:05:20 -0700160 public static final String VEHICLE_HAL_NOT_SUPPORTED = "Vehicle Hal not supported.";
161
Mayank Garg02576972021-02-18 16:46:07 -0800162 public static final String HANDLER_THREAD_NAME = "UserService";
163
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700164 private final Context mContext;
Keun young Parkfb656372019-03-12 18:37:55 -0700165 private final IActivityManager mAm;
Anthony Hugh9932a252019-06-12 16:19:56 -0700166 private final UserManager mUserManager;
167 private final int mMaxRunningUsers;
Mayank Garg70732a82020-08-05 20:17:47 -0700168 private final InitialUserSetter mInitialUserSetter;
Eric Jeongc91f9452019-08-30 15:04:21 -0700169 private final boolean mEnablePassengerSupport;
Mayank Garg9732d602020-08-09 21:02:40 -0700170 private final UserPreCreator mUserPreCreator;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700171
Eric Jeongc91f9452019-08-30 15:04:21 -0700172 private final Object mLockUser = new Object();
173 @GuardedBy("mLockUser")
Keun-young Parkd462a912019-02-11 08:53:42 -0800174 private boolean mUser0Unlocked;
Eric Jeongc91f9452019-08-30 15:04:21 -0700175 @GuardedBy("mLockUser")
Keun-young Parkd462a912019-02-11 08:53:42 -0800176 private final ArrayList<Runnable> mUser0UnlockTasks = new ArrayList<>();
Eric Jeongc91f9452019-08-30 15:04:21 -0700177 // Only one passenger is supported.
178 @GuardedBy("mLockUser")
179 private @UserIdInt int mLastPassengerId;
Keun young Parkf3523cd2019-04-08 10:09:17 -0700180 /**
181 * Background users that will be restarted in garage mode. This list can include the
Mayank Garg31e73042020-01-23 00:10:38 -0800182 * current foreground user but the current foreground user should not be restarted.
Keun young Parkf3523cd2019-04-08 10:09:17 -0700183 */
Eric Jeongc91f9452019-08-30 15:04:21 -0700184 @GuardedBy("mLockUser")
Keun young Parkf3523cd2019-04-08 10:09:17 -0700185 private final ArrayList<Integer> mBackgroundUsersToRestart = new ArrayList<>();
186 /**
187 * Keep the list of background users started here. This is wholly for debugging purpose.
188 */
Eric Jeongc91f9452019-08-30 15:04:21 -0700189 @GuardedBy("mLockUser")
Keun young Parkf3523cd2019-04-08 10:09:17 -0700190 private final ArrayList<Integer> mBackgroundUsersRestartedHere = new ArrayList<>();
191
Felipe Leme58412202020-01-09 13:45:33 -0800192 private final UserHalService mHal;
193
Keun young Parkb241d022020-04-20 20:31:34 -0700194 private final HandlerThread mHandlerThread = CarServiceUtils.getHandlerThread(
Mayank Garg02576972021-02-18 16:46:07 -0800195 HANDLER_THREAD_NAME);
196 private final Handler mHandler;
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700197
Felipe Leme5528ff72020-02-10 19:05:14 -0800198 /**
Felipe Lemefaf67042021-07-08 11:24:00 -0700199 * Internal listeners to be notified on new user activities events.
200 *
201 * <p>This collection should be accessed and manipulated by {@code mHandlerThread} only.
Antonio Kantekc8114752020-03-05 21:37:39 -0800202 */
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700203 private final List<UserLifecycleListener> mUserLifecycleListeners = new ArrayList<>();
Antonio Kantekc8114752020-03-05 21:37:39 -0800204
205 /**
Felipe Lemefaf67042021-07-08 11:24:00 -0700206 * App listeners to be notified on new user activities events.
207 *
208 * <p>This collection should be accessed and manipulated by {@code mHandlerThread} only.
Felipe Leme5528ff72020-02-10 19:05:14 -0800209 */
Felipe Lemefaf67042021-07-08 11:24:00 -0700210 private final ArrayMap<IBinder, AppLifecycleListener> mAppLifecycleListeners =
211 new ArrayMap<>();
Felipe Leme5528ff72020-02-10 19:05:14 -0800212
Mayank Garg7a114c82020-04-08 21:25:06 -0700213 /**
214 * User Id for the user switch in process, if any.
215 */
216 @GuardedBy("mLockUser")
felipealf7368962020-04-16 12:55:19 -0700217 private int mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
Mayank Garg7a114c82020-04-08 21:25:06 -0700218 /**
219 * Request Id for the user switch in process, if any.
220 */
221 @GuardedBy("mLockUser")
felipealf7368962020-04-16 12:55:19 -0700222 private int mRequestIdForUserSwitchInProcess;
Felipe Lemee3cab982020-03-12 11:39:29 -0700223 private final int mHalTimeoutMs = CarProperties.user_hal_timeout().orElse(5_000);
224
Eric Jeongc91f9452019-08-30 15:04:21 -0700225 private final CopyOnWriteArrayList<PassengerCallback> mPassengerCallbacks =
226 new CopyOnWriteArrayList<>();
227
Mayank Garg7e1450b2020-08-07 18:15:15 -0700228 // TODO(b/163566866): Use mSwitchGuestUserBeforeSleep for new create guest request
229 private final boolean mSwitchGuestUserBeforeSleep;
230
felipeal61ce3732020-04-03 11:01:00 -0700231 @Nullable
232 @GuardedBy("mLockUser")
233 private UserInfo mInitialUser;
234
Mayank Garg587f1942020-05-06 01:41:34 -0700235 private IResultReceiver mUserSwitchUiReceiver;
236
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800237 private final CarUxRestrictionsManagerService mCarUxRestrictionService;
238
239 /**
240 * Whether some operations - like user switch - are restricted by driving safety constraints.
241 */
242 @GuardedBy("mLockUser")
243 private boolean mUxRestricted;
244
245 /**
Mayank Garg784a0862021-05-26 00:20:50 -0700246 * If {@code false}, garage mode operations (background users start at garage mode entry and
247 * background users stop at garage mode exit) will be skipped. Controlled using car shell
248 * command {@code adb shell set-start-bg-users-on-garage-mode [true|false]}
249 * Purpose: Garage mode testing and simulation
250 */
251 @GuardedBy("mLockUser")
252 private boolean mStartBackgroundUsersOnGarageMode = true;
253
254 /**
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800255 * Callback to notify {@code CarServiceHelper} about driving safety changes (through
256 * {@link ICarServiceHelper#setSafetyMode(boolean).
257 *
258 * <p>NOTE: in theory, that logic should belong to {@code CarDevicePolicyService}, but it's
259 * simpler to do it here (and that service already depends on this one).
260 */
261 @GuardedBy("mLockUser")
262 private ICarServiceHelper mICarServiceHelper;
263
264 private final ICarUxRestrictionsChangeListener mCarUxRestrictionsChangeListener =
265 new ICarUxRestrictionsChangeListener.Stub() {
266 @Override
267 public void onUxRestrictionsChanged(CarUxRestrictions restrictions) {
268 setUxRestrictions(restrictions);
269 }
270 };
Felipe Leme5d5ab142020-10-27 13:49:10 -0700271
Eric Jeongc91f9452019-08-30 15:04:21 -0700272 /** Interface for callbaks related to passenger activities. */
273 public interface PassengerCallback {
274 /** Called when passenger is started at a certain zone. */
275 void onPassengerStarted(@UserIdInt int passengerId, int zoneId);
276 /** Called when passenger is stopped. */
277 void onPassengerStopped(@UserIdInt int passengerId);
278 }
279
280 /** Interface for delegating zone-related implementation to CarOccupantZoneService. */
281 public interface ZoneUserBindingHelper {
282 /** Gets occupant zones corresponding to the occupant type. */
283 @NonNull
284 List<OccupantZoneInfo> getOccupantZones(@OccupantTypeEnum int occupantType);
285 /** Assigns the user to the occupant zone. */
286 boolean assignUserToOccupantZone(@UserIdInt int userId, int zoneId);
287 /** Makes the occupant zone unoccupied. */
288 boolean unassignUserFromOccupantZone(@UserIdInt int userId);
289 /** Returns whether there is a passenger display. */
290 boolean isPassengerDisplayAvailable();
291 }
292
293 private final Object mLockHelper = new Object();
294 @GuardedBy("mLockHelper")
295 private ZoneUserBindingHelper mZoneUserBindingHelper;
296
Felipe Leme6b34fc32020-10-26 15:49:17 -0700297 /** Map used to avoid calling UserHAL when a user was removed because HAL creation failed. */
298 @GuardedBy("mLockUser")
299 private final SparseBooleanArray mFailedToCreateUserIds = new SparseBooleanArray(1);
300
Felipe Leme58412202020-01-09 13:45:33 -0800301 public CarUserService(@NonNull Context context, @NonNull UserHalService hal,
Mayank Garge90a4082020-09-30 12:57:34 -0700302 @NonNull UserManager userManager,
Felipe Leme5d5ab142020-10-27 13:49:10 -0700303 @NonNull IActivityManager am, int maxRunningUsers,
304 @NonNull CarUxRestrictionsManagerService uxRestrictionService) {
Mayank Garge90a4082020-09-30 12:57:34 -0700305 this(context, hal, userManager, am, maxRunningUsers,
Mayank Garg02576972021-02-18 16:46:07 -0800306 /* initialUserSetter= */ null, /* userPreCreator= */ null, uxRestrictionService,
307 null);
Mayank Garg71661ea2020-04-29 01:25:03 -0700308 }
309
310 @VisibleForTesting
311 CarUserService(@NonNull Context context, @NonNull UserHalService hal,
Mayank Garge90a4082020-09-30 12:57:34 -0700312 @NonNull UserManager userManager,
Mayank Gargccad8062020-08-30 15:05:10 -0700313 @NonNull IActivityManager am, int maxRunningUsers,
Mayank Garg1bb1c382020-09-03 17:11:11 -0700314 @Nullable InitialUserSetter initialUserSetter,
Felipe Leme5d5ab142020-10-27 13:49:10 -0700315 @Nullable UserPreCreator userPreCreator,
Mayank Garg02576972021-02-18 16:46:07 -0800316 @NonNull CarUxRestrictionsManagerService uxRestrictionService,
317 @Nullable Handler handler) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800318 if (Log.isLoggable(TAG, Log.DEBUG)) {
Felipe Leme8725a2f2020-12-09 16:04:51 -0800319 Slog.d(TAG, "constructed for user " + context.getUserId());
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700320 }
321 mContext = context;
Felipe Leme58412202020-01-09 13:45:33 -0800322 mHal = hal;
Keun young Parkf3523cd2019-04-08 10:09:17 -0700323 mAm = am;
324 mMaxRunningUsers = maxRunningUsers;
Anthony Hugh9932a252019-06-12 16:19:56 -0700325 mUserManager = userManager;
Eric Jeongc91f9452019-08-30 15:04:21 -0700326 mLastPassengerId = UserHandle.USER_NULL;
Mayank Garg02576972021-02-18 16:46:07 -0800327 mHandler = handler == null ? new Handler(mHandlerThread.getLooper()) : handler;
Mayank Garg1bb1c382020-09-03 17:11:11 -0700328 mInitialUserSetter =
Felipe Lemecceb2992020-11-18 18:22:44 -0800329 initialUserSetter == null ? new InitialUserSetter(context, this,
330 (u) -> setInitialUser(u)) : initialUserSetter;
Mayank Garg1bb1c382020-09-03 17:11:11 -0700331 mUserPreCreator =
332 userPreCreator == null ? new UserPreCreator(mUserManager) : userPreCreator;
Mayank Garg7e1450b2020-08-07 18:15:15 -0700333 Resources resources = context.getResources();
334 mEnablePassengerSupport = resources.getBoolean(R.bool.enablePassengerSupport);
335 mSwitchGuestUserBeforeSleep = resources.getBoolean(
336 R.bool.config_switchGuestUserBeforeGoingSleep);
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800337 mCarUxRestrictionService = uxRestrictionService;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700338 }
339
340 @Override
341 public void init() {
Eric Jeongf75d4132020-12-21 13:48:23 -0800342 if (Log.isLoggable(TAG, Log.DEBUG)) {
343 Slog.d(TAG, "init()");
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700344 }
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800345 mCarUxRestrictionService.registerUxRestrictionsChangeListener(
346 mCarUxRestrictionsChangeListener, Display.DEFAULT_DISPLAY);
347
348 setUxRestrictions(mCarUxRestrictionService.getCurrentUxRestrictions());
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700349 }
350
351 @Override
352 public void release() {
Eric Jeongf75d4132020-12-21 13:48:23 -0800353 if (Log.isLoggable(TAG, Log.DEBUG)) {
354 Slog.d(TAG, "release()");
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700355 }
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800356 mCarUxRestrictionService
357 .unregisterUxRestrictionsChangeListener(mCarUxRestrictionsChangeListener);
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700358 }
359
360 @Override
Mayank Garg578db012021-06-14 22:17:00 -0700361 @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO)
Felipe Leme176a5fd2021-01-20 15:48:33 -0800362 public void dump(@NonNull IndentingPrintWriter writer) {
Felipe Leme55236722020-10-16 16:54:32 -0700363 checkHasDumpPermissionGranted("dump()");
364
Eric Jeong1545f3b2019-09-16 13:56:52 -0700365 writer.println("*CarUserService*");
Felipe Lemefaf67042021-07-08 11:24:00 -0700366 handleDumpListeners(writer);
Mayank Garg587f1942020-05-06 01:41:34 -0700367 writer.printf("User switch UI receiver %s\n", mUserSwitchUiReceiver);
Eric Jeongc91f9452019-08-30 15:04:21 -0700368 synchronized (mLockUser) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700369 writer.println("User0Unlocked: " + mUser0Unlocked);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700370 writer.println("BackgroundUsersToRestart: " + mBackgroundUsersToRestart);
371 writer.println("BackgroundUsersRestarted: " + mBackgroundUsersRestartedHere);
Felipe Leme6b34fc32020-10-26 15:49:17 -0700372 if (mFailedToCreateUserIds.size() > 0) {
373 writer.println("FailedToCreateUserIds: " + mFailedToCreateUserIds);
374 }
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800375 writer.printf("Is UX restricted: %b\n", mUxRestricted);
Mayank Garg784a0862021-05-26 00:20:50 -0700376 writer.printf("Start Background Users On Garage Mode=%s\n",
377 mStartBackgroundUsersOnGarageMode);
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700378 }
Mayank Garg02576972021-02-18 16:46:07 -0800379
380 writer.println("SwitchGuestUserBeforeSleep: " + mSwitchGuestUserBeforeSleep);
Mayank Garg02576972021-02-18 16:46:07 -0800381
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700382 writer.println("MaxRunningUsers: " + mMaxRunningUsers);
383 List<UserInfo> allDrivers = getAllDrivers();
384 int driversSize = allDrivers.size();
385 writer.println("NumberOfDrivers: " + driversSize);
Felipe Lemefaf67042021-07-08 11:24:00 -0700386 writer.increaseIndent();
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700387 for (int i = 0; i < driversSize; i++) {
388 int driverId = allDrivers.get(i).id;
Felipe Lemefaf67042021-07-08 11:24:00 -0700389 writer.printf("#%d: id=%d", i, driverId);
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700390 List<UserInfo> passengers = getPassengers(driverId);
391 int passengersSize = passengers.size();
392 writer.print(" NumberPassengers: " + passengersSize);
393 if (passengersSize > 0) {
394 writer.print(" [");
395 for (int j = 0; j < passengersSize; j++) {
396 writer.print(passengers.get(j).id);
397 if (j < passengersSize - 1) {
398 writer.print(" ");
felipeal2d0483c2019-11-02 14:07:22 -0700399 }
felipeal2d0483c2019-11-02 14:07:22 -0700400 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700401 writer.print("]");
felipeal2d0483c2019-11-02 14:07:22 -0700402 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700403 writer.println();
404 }
Felipe Lemefaf67042021-07-08 11:24:00 -0700405 writer.decreaseIndent();
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700406 writer.printf("EnablePassengerSupport: %s\n", mEnablePassengerSupport);
407 writer.printf("User HAL timeout: %dms\n", mHalTimeoutMs);
408 writer.printf("Initial user: %s\n", mInitialUser);
felipealbf327652020-06-03 11:33:29 -0700409
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700410 writer.println("Relevant overlayable properties");
411 Resources res = mContext.getResources();
Felipe Lemefaf67042021-07-08 11:24:00 -0700412 writer.increaseIndent();
413 writer.printf("owner_name=%s\n", res.getString(com.android.internal.R.string.owner_name));
414 writer.printf("default_guest_name=%s\n", res.getString(R.string.default_guest_name));
415 writer.decreaseIndent();
felipealf7368962020-04-16 12:55:19 -0700416 writer.printf("User switch in process=%d\n", mUserIdForUserSwitchInProcess);
Mayank Garg7a114c82020-04-08 21:25:06 -0700417 writer.printf("Request Id for the user switch in process=%d\n ",
418 mRequestIdForUserSwitchInProcess);
Mayank Garga480dd92020-05-14 03:14:57 -0700419 writer.printf("System UI package name=%s\n", getSystemUiPackageName());
felipeale8c5dce2020-04-15 11:27:06 -0700420
felipealbf327652020-06-03 11:33:29 -0700421 writer.println("Relevant Global settings");
Felipe Lemefaf67042021-07-08 11:24:00 -0700422 writer.increaseIndent();
423 dumpGlobalProperty(writer, CarSettings.Global.LAST_ACTIVE_USER_ID);
424 dumpGlobalProperty(writer, CarSettings.Global.LAST_ACTIVE_PERSISTENT_USER_ID);
425 writer.decreaseIndent();
felipealbf327652020-06-03 11:33:29 -0700426
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700427 mInitialUserSetter.dump(writer);
felipeale8c5dce2020-04-15 11:27:06 -0700428 }
429
Felipe Lemefaf67042021-07-08 11:24:00 -0700430 private void dumpGlobalProperty(IndentingPrintWriter writer, String property) {
felipealbf327652020-06-03 11:33:29 -0700431 String value = Settings.Global.getString(mContext.getContentResolver(), property);
Felipe Lemefaf67042021-07-08 11:24:00 -0700432 writer.printf("%s=%s\n", property, value);
felipealbf327652020-06-03 11:33:29 -0700433 }
434
Felipe Lemefaf67042021-07-08 11:24:00 -0700435 private void handleDumpListeners(IndentingPrintWriter writer) {
436 writer.increaseIndent();
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700437 CountDownLatch latch = new CountDownLatch(1);
438 mHandler.post(() -> {
felipealde1e16d2020-06-03 13:20:48 -0700439 handleDumpServiceLifecycleListeners(writer);
Felipe Lemefaf67042021-07-08 11:24:00 -0700440 handleDumpAppLifecycleListeners(writer);
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700441 latch.countDown();
442 });
443 int timeout = 5;
444 try {
445 if (!latch.await(timeout, TimeUnit.SECONDS)) {
446 writer.printf("Handler thread didn't respond in %ds when dumping listeners\n",
447 timeout);
448 }
449 } catch (InterruptedException e) {
450 Thread.currentThread().interrupt();
451 writer.println("Interrupted waiting for handler thread to dump app and user listeners");
452 }
Felipe Lemefaf67042021-07-08 11:24:00 -0700453 writer.decreaseIndent();
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700454 }
455
Felipe Lemefaf67042021-07-08 11:24:00 -0700456 private void handleDumpServiceLifecycleListeners(PrintWriter writer) {
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700457 if (mUserLifecycleListeners.isEmpty()) {
felipealde1e16d2020-06-03 13:20:48 -0700458 writer.println("No lifecycle listeners for internal services");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700459 return;
460 }
felipealde1e16d2020-06-03 13:20:48 -0700461 int size = mUserLifecycleListeners.size();
462 writer.printf("%d lifecycle listener%s for services\n", size, size == 1 ? "" : "s");
463 String indent = " ";
Felipe Lemefaf67042021-07-08 11:24:00 -0700464 for (int i = 0; i < size; i++) {
465 UserLifecycleListener listener = mUserLifecycleListeners.get(i);
felipealde1e16d2020-06-03 13:20:48 -0700466 writer.printf("%s%s\n", indent, FunctionalUtils.getLambdaName(listener));
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700467 }
468 }
469
Felipe Lemefaf67042021-07-08 11:24:00 -0700470 private void handleDumpAppLifecycleListeners(IndentingPrintWriter writer) {
felipealde1e16d2020-06-03 13:20:48 -0700471 int size = mAppLifecycleListeners.size();
472 if (size == 0) {
473 writer.println("No lifecycle listeners for apps");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700474 return;
475 }
Felipe Lemefaf67042021-07-08 11:24:00 -0700476 writer.printf("%d lifecycle listener%s for apps\n", size, size == 1 ? "" : "s");
477 writer.increaseIndent();
felipealde1e16d2020-06-03 13:20:48 -0700478 for (int i = 0; i < size; i++) {
Felipe Lemefaf67042021-07-08 11:24:00 -0700479 mAppLifecycleListeners.valueAt(i).dump(writer);
Keun-young Parkd462a912019-02-11 08:53:42 -0800480 }
Felipe Lemefaf67042021-07-08 11:24:00 -0700481 writer.decreaseIndent();
Eric Jeong1545f3b2019-09-16 13:56:52 -0700482 }
483
484 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700485 * @see ExperimentalCarUserManager.createDriver
Eric Jeong1545f3b2019-09-16 13:56:52 -0700486 */
487 @Override
Yan Zhu65a0acd2021-06-21 10:56:53 -0700488 @ExcludeFromCodeCoverageGeneratedReport(reason = DEPRECATED_CODE,
489 details = "TODO(b/172262561) remove annotation after refactoring")
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700490 public AndroidFuture<UserCreationResult> createDriver(@NonNull String name, boolean admin) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700491 checkManageUsersPermission("createDriver");
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +0000492 Objects.requireNonNull(name, "name cannot be null");
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700493
494 AndroidFuture<UserCreationResult> future = new AndroidFuture<UserCreationResult>() {
495 @Override
496 protected void onCompleted(UserCreationResult result, Throwable err) {
497 if (result == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800498 Slog.w(TAG, "createDriver(" + name + "," + admin + ") failed: " + err);
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700499 } else {
500 if (result.getStatus() == UserCreationResult.STATUS_SUCCESSFUL) {
501 assignDefaultIcon(result.getUser());
502 }
503 }
504 super.onCompleted(result, err);
505 };
506 };
507 int flags = 0;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700508 if (admin) {
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700509 if (!(mUserManager.isAdminUser() || mUserManager.isSystemUser())) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800510 Slog.e(TAG, "Only admin users and system user can create other admins.");
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700511 sendUserCreationResultFailure(future, UserCreationResult.STATUS_INVALID_REQUEST);
512 return future;
513 }
514 flags = UserInfo.FLAG_ADMIN;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700515 }
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700516 createUser(name, UserInfo.getDefaultUserType(flags), flags, mHalTimeoutMs, future);
517 return future;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700518 }
519
520 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700521 * @see ExperimentalCarUserManager.createPassenger
Eric Jeong1545f3b2019-09-16 13:56:52 -0700522 */
523 @Override
524 @Nullable
Yan Zhu65a0acd2021-06-21 10:56:53 -0700525 @ExcludeFromCodeCoverageGeneratedReport(reason = DEPRECATED_CODE,
526 details = "TODO(b/172262561) remove annotation after refactoring")
Eric Jeong1545f3b2019-09-16 13:56:52 -0700527 public UserInfo createPassenger(@NonNull String name, @UserIdInt int driverId) {
528 checkManageUsersPermission("createPassenger");
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +0000529 Objects.requireNonNull(name, "name cannot be null");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700530 UserInfo driver = mUserManager.getUserInfo(driverId);
531 if (driver == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800532 Slog.w(TAG, "the driver is invalid");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700533 return null;
534 }
535 if (driver.isGuest()) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800536 Slog.w(TAG, "a guest driver cannot create a passenger");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700537 return null;
538 }
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700539 // createPassenger doesn't use user HAL because user HAL doesn't support profile user yet.
Bookatz42fb1a62019-10-30 11:45:01 -0700540 UserInfo user = mUserManager.createProfileForUser(name,
541 UserManager.USER_TYPE_PROFILE_MANAGED, /* flags */ 0, driverId);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700542 if (user == null) {
543 // Couldn't create user, most likely because there are too many.
Eric Jeongf75d4132020-12-21 13:48:23 -0800544 Slog.w(TAG, "can't create a profile for user" + driverId);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700545 return null;
546 }
547 // Passenger user should be a non-admin user.
Mayank Garge90a4082020-09-30 12:57:34 -0700548 UserHelper.setDefaultNonAdminRestrictions(mContext, user, /* enable= */ true);
Anthony Hugh6fed1e92019-10-22 16:22:03 -0700549 assignDefaultIcon(user);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700550 return user;
551 }
552
553 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700554 * @see ExperimentalCarUserManager.switchDriver
Eric Jeong1545f3b2019-09-16 13:56:52 -0700555 */
556 @Override
Yan Zhu65a0acd2021-06-21 10:56:53 -0700557 @ExcludeFromCodeCoverageGeneratedReport(reason = DEPRECATED_CODE,
558 details = "TODO(b/172262561) remove annotation after refactoring")
Eric Jeong25666cf2020-05-14 15:16:27 -0700559 public void switchDriver(@UserIdInt int driverId, AndroidFuture<UserSwitchResult> receiver) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700560 checkManageUsersPermission("switchDriver");
Mayank Garg94f3eb92020-08-12 12:38:58 -0700561 if (UserHelperLite.isHeadlessSystemUser(driverId)) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700562 // System user doesn't associate with real person, can not be switched to.
Eric Jeongf75d4132020-12-21 13:48:23 -0800563 Slog.w(TAG, "switching to system user in headless system user mode is not allowed");
felipealdfdf8512020-06-01 09:35:45 -0700564 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_INVALID_REQUEST);
Eric Jeong25666cf2020-05-14 15:16:27 -0700565 return;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700566 }
567 int userSwitchable = mUserManager.getUserSwitchability();
568 if (userSwitchable != UserManager.SWITCHABILITY_STATUS_OK) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800569 Slog.w(TAG, "current process is not allowed to switch user");
felipealdfdf8512020-06-01 09:35:45 -0700570 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_INVALID_REQUEST);
Eric Jeong25666cf2020-05-14 15:16:27 -0700571 return;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700572 }
Eric Jeong25666cf2020-05-14 15:16:27 -0700573 switchUser(driverId, mHalTimeoutMs, receiver);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700574 }
575
576 /**
Eric Jeonge7916fc2019-12-20 14:03:34 -0800577 * Returns all drivers who can occupy the driving zone. Guest users are included in the list.
578 *
579 * @return the list of {@link UserInfo} who can be a driver on the device.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700580 */
581 @Override
582 @NonNull
583 public List<UserInfo> getAllDrivers() {
felipeal2d0483c2019-11-02 14:07:22 -0700584 checkManageUsersOrDumpPermission("getAllDrivers");
Mayank Garg94f3eb92020-08-12 12:38:58 -0700585 return getUsers((user) -> !UserHelperLite.isHeadlessSystemUser(user.id) && user.isEnabled()
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700586 && !user.isManagedProfile() && !user.isEphemeral());
Eric Jeong1545f3b2019-09-16 13:56:52 -0700587 }
588
589 /**
Eric Jeonge7916fc2019-12-20 14:03:34 -0800590 * Returns all passengers under the given driver.
591 *
592 * @param driverId User id of a driver.
593 * @return the list of {@link UserInfo} who is a passenger under the given driver.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700594 */
595 @Override
596 @NonNull
597 public List<UserInfo> getPassengers(@UserIdInt int driverId) {
felipeal2d0483c2019-11-02 14:07:22 -0700598 checkManageUsersOrDumpPermission("getPassengers");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700599 return getUsers((user) -> {
Mayank Garg94f3eb92020-08-12 12:38:58 -0700600 return !UserHelperLite.isHeadlessSystemUser(user.id) && user.isEnabled()
Eric Jeong40f8fa32020-05-12 12:23:33 -0700601 && user.isManagedProfile() && user.profileGroupId == driverId;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700602 });
603 }
604
605 /**
606 * @see CarUserManager.startPassenger
607 */
608 @Override
609 public boolean startPassenger(@UserIdInt int passengerId, int zoneId) {
610 checkManageUsersPermission("startPassenger");
Eric Jeongc91f9452019-08-30 15:04:21 -0700611 synchronized (mLockUser) {
612 try {
613 if (!mAm.startUserInBackgroundWithListener(passengerId, null)) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800614 Slog.w(TAG, "could not start passenger");
Eric Jeongc91f9452019-08-30 15:04:21 -0700615 return false;
616 }
617 } catch (RemoteException e) {
618 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -0800619 Slog.w(TAG, "error while starting passenger", e);
Eric Jeongc91f9452019-08-30 15:04:21 -0700620 return false;
621 }
622 if (!assignUserToOccupantZone(passengerId, zoneId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800623 Slog.w(TAG, "could not assign passenger to zone");
Eric Jeongc91f9452019-08-30 15:04:21 -0700624 return false;
625 }
626 mLastPassengerId = passengerId;
627 }
628 for (PassengerCallback callback : mPassengerCallbacks) {
629 callback.onPassengerStarted(passengerId, zoneId);
630 }
631 return true;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700632 }
633
634 /**
635 * @see CarUserManager.stopPassenger
636 */
637 @Override
638 public boolean stopPassenger(@UserIdInt int passengerId) {
639 checkManageUsersPermission("stopPassenger");
Eric Jeongc91f9452019-08-30 15:04:21 -0700640 return stopPassengerInternal(passengerId, true);
641 }
642
643 private boolean stopPassengerInternal(@UserIdInt int passengerId, boolean checkCurrentDriver) {
644 synchronized (mLockUser) {
645 UserInfo passenger = mUserManager.getUserInfo(passengerId);
646 if (passenger == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800647 Slog.w(TAG, "passenger " + passengerId + " doesn't exist");
Eric Jeongc91f9452019-08-30 15:04:21 -0700648 return false;
649 }
650 if (mLastPassengerId != passengerId) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800651 Slog.w(TAG, "passenger " + passengerId + " hasn't been started");
Eric Jeongc91f9452019-08-30 15:04:21 -0700652 return true;
653 }
654 if (checkCurrentDriver) {
655 int currentUser = ActivityManager.getCurrentUser();
656 if (passenger.profileGroupId != currentUser) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800657 Slog.w(TAG, "passenger " + passengerId
Eric Jeongc91f9452019-08-30 15:04:21 -0700658 + " is not a profile of the current user");
659 return false;
660 }
661 }
662 // Passenger is a profile, so cannot be stopped through activity manager.
663 // Instead, activities started by the passenger are stopped and the passenger is
664 // unassigned from the zone.
665 stopAllTasks(passengerId);
666 if (!unassignUserFromOccupantZone(passengerId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800667 Slog.w(TAG, "could not unassign user from occupant zone");
Eric Jeongc91f9452019-08-30 15:04:21 -0700668 return false;
669 }
670 mLastPassengerId = UserHandle.USER_NULL;
671 }
672 for (PassengerCallback callback : mPassengerCallbacks) {
673 callback.onPassengerStopped(passengerId);
674 }
675 return true;
676 }
677
678 private void stopAllTasks(@UserIdInt int userId) {
679 try {
Louis Chang3bf2f202020-08-18 13:04:28 +0800680 for (RootTaskInfo info : mAm.getAllRootTaskInfos()) {
681 for (int i = 0; i < info.childTaskIds.length; i++) {
682 if (info.childTaskUserIds[i] == userId) {
683 int taskId = info.childTaskIds[i];
Eric Jeongc91f9452019-08-30 15:04:21 -0700684 if (!mAm.removeTask(taskId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800685 Slog.w(TAG, "could not remove task " + taskId);
Eric Jeongc91f9452019-08-30 15:04:21 -0700686 }
687 }
688 }
689 }
690 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800691 Slog.e(TAG, "could not get stack info", e);
Eric Jeongc91f9452019-08-30 15:04:21 -0700692 }
Eric Jeong1545f3b2019-09-16 13:56:52 -0700693 }
694
Felipe Leme5528ff72020-02-10 19:05:14 -0800695 @Override
Felipe Lemefaf67042021-07-08 11:24:00 -0700696 public void setLifecycleListenerForApp(String packageName, IResultReceiver receiver) {
Felipe Leme5528ff72020-02-10 19:05:14 -0800697 int uid = Binder.getCallingUid();
Felipe Lemefaf67042021-07-08 11:24:00 -0700698 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SET_LIFECYCLE_LISTENER, uid, packageName);
699 checkInteractAcrossUsersPermission("setLifecycleListenerForApp-" + uid + "-" + packageName);
Felipe Leme5528ff72020-02-10 19:05:14 -0800700
Felipe Lemefaf67042021-07-08 11:24:00 -0700701 IBinder receiverBinder = receiver.asBinder();
702 AppLifecycleListener listener = new AppLifecycleListener(uid, packageName, receiver);
Felipe Leme5528ff72020-02-10 19:05:14 -0800703 try {
Felipe Lemefaf67042021-07-08 11:24:00 -0700704 receiverBinder.linkToDeath(() -> onListenerDeath(listener), 0);
Felipe Leme5528ff72020-02-10 19:05:14 -0800705 } catch (RemoteException e) {
Felipe Lemefaf67042021-07-08 11:24:00 -0700706 Slogf.wtf(TAG, "Cannot listen to death of %s", listener);
Felipe Leme5528ff72020-02-10 19:05:14 -0800707 }
Felipe Lemefaf67042021-07-08 11:24:00 -0700708 Slogf.d(TAG, "Adding %s (using binder %s)", listener, receiverBinder);
709
710 mHandler.post(() -> mAppLifecycleListeners.put(receiverBinder, listener));
Felipe Leme5528ff72020-02-10 19:05:14 -0800711 }
712
Felipe Lemefaf67042021-07-08 11:24:00 -0700713 private void onListenerDeath(AppLifecycleListener listener) {
714 Slogf.i(TAG, "Removing listener %s on binder death", listener);
715 mHandler.post(() -> mAppLifecycleListeners.remove(listener.receiver.asBinder()));
Felipe Leme5528ff72020-02-10 19:05:14 -0800716 }
717
718 @Override
Felipe Lemefaf67042021-07-08 11:24:00 -0700719 public void resetLifecycleListenerForApp(IResultReceiver receiver) {
Felipe Leme5528ff72020-02-10 19:05:14 -0800720 int uid = Binder.getCallingUid();
Felipe Lemefaf67042021-07-08 11:24:00 -0700721 checkInteractAcrossUsersPermission("resetLifecycleListenerForApp-" + uid);
722 IBinder receiverBinder = receiver.asBinder();
723 mHandler.post(() -> {
724 AppLifecycleListener listener = mAppLifecycleListeners.get(receiverBinder);
725 if (listener == null) {
726 Slogf.e(TAG, "resetLifecycleListenerForApp(uid=%d): no listener for receiver", uid);
727 return;
728 }
729 if (listener.uid != uid) {
730 Slogf.e(TAG, "resetLifecycleListenerForApp(): uid mismatch (called by %d) for "
731 + "listener %s", uid, listener);
732 }
733 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_RESET_LIFECYCLE_LISTENER, uid,
734 listener.packageName);
735 Slogf.d(TAG, "Removing %s (using binder %s)", listener, receiverBinder);
736 mAppLifecycleListeners.remove(receiverBinder);
737 });
Felipe Leme5528ff72020-02-10 19:05:14 -0800738 }
739
Felipe Lemee3cab982020-03-12 11:39:29 -0700740 /**
felipeal61ce3732020-04-03 11:01:00 -0700741 * Gets the initial foreground user after the device boots or resumes from suspension.
742 *
743 * <p>When the OEM supports the User HAL, the initial user won't be available until the HAL
744 * returns the initial value to {@code CarService} - if HAL takes too long or times out, this
745 * method returns {@code null}.
746 *
747 * <p>If the HAL eventually times out, {@code CarService} will fallback to its default behavior
748 * (like switching to the last active user), and this method will return the result of such
749 * operation.
750 *
751 * <p>Notice that if {@code CarService} crashes, subsequent calls to this method will return
752 * {@code null}.
753 *
754 * @hide
755 */
756 @Nullable
757 public UserInfo getInitialUser() {
758 checkInteractAcrossUsersPermission("getInitialUser");
759 synchronized (mLockUser) {
760 return mInitialUser;
761 }
762 }
763
felipeal61ce3732020-04-03 11:01:00 -0700764 /**
765 * Sets the initial foreground user after the device boots or resumes from suspension.
766 */
767 public void setInitialUser(@Nullable UserInfo user) {
felipeal312416a2020-04-14 12:28:24 -0700768 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SET_INITIAL_USER,
769 user == null ? UserHandle.USER_NULL : user.id);
felipeal61ce3732020-04-03 11:01:00 -0700770 synchronized (mLockUser) {
771 mInitialUser = user;
772 }
773 if (user == null) {
774 // This mean InitialUserSetter failed and could not fallback, so the initial user was
775 // not switched (and most likely is SYSTEM_USER).
776 // TODO(b/153104378): should we set it to ActivityManager.getCurrentUser() instead?
Eric Jeongf75d4132020-12-21 13:48:23 -0800777 Slog.wtf(TAG, "Initial user set to null");
felipeal61ce3732020-04-03 11:01:00 -0700778 }
779 }
780
Mayank Garg7e1450b2020-08-07 18:15:15 -0700781 private void initResumeReplaceGuest() {
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700782 int currentUserId = ActivityManager.getCurrentUser();
783 UserInfo currentUser = mUserManager.getUserInfo(currentUserId);
784
785 if (!mInitialUserSetter.canReplaceGuestUser(currentUser)) return; // Not a guest
786
787 InitialUserInfo info =
788 new InitialUserSetter.Builder(InitialUserSetter.TYPE_REPLACE_GUEST).build();
789
790 mInitialUserSetter.set(info);
791 }
792
793 /**
Mayank Garg0baf88a2020-08-30 21:57:36 -0700794 * Calls to switch user at the power suspend.
Mayank Garg7e1450b2020-08-07 18:15:15 -0700795 *
796 * <p><b>Note:</b> Should be used only by {@link CarPowerManagementService}
797 *
Mayank Garg7e1450b2020-08-07 18:15:15 -0700798 */
Mayank Garg0baf88a2020-08-30 21:57:36 -0700799 public void onSuspend() {
Eric Jeongf75d4132020-12-21 13:48:23 -0800800 if (Log.isLoggable(TAG, Log.DEBUG)) {
801 Slog.d(TAG, "onSuspend called.");
Mayank Garg7e1450b2020-08-07 18:15:15 -0700802 }
803
Mayank Garg0baf88a2020-08-30 21:57:36 -0700804 if (mSwitchGuestUserBeforeSleep) {
805 initResumeReplaceGuest();
Mayank Garg7e1450b2020-08-07 18:15:15 -0700806 }
Mayank Garg1bb1c382020-09-03 17:11:11 -0700807
Mayank Garga3b72d02021-03-14 23:05:51 -0700808 preCreateUsersInternal();
Mayank Garg7e1450b2020-08-07 18:15:15 -0700809 }
810
811 /**
Mayank Garg0baf88a2020-08-30 21:57:36 -0700812 * Calls to switch user at the power resume.
813 *
814 * <p>
815 * <b>Note:</b> Should be used only by {@link CarPowerManagementService}
816 *
817 */
818 public void onResume() {
Eric Jeongf75d4132020-12-21 13:48:23 -0800819 if (Log.isLoggable(TAG, Log.DEBUG)) {
820 Slog.d(TAG, "onResume called.");
Mayank Garg0baf88a2020-08-30 21:57:36 -0700821 }
822
Mayank Garg02576972021-02-18 16:46:07 -0800823 mHandler.post(() -> initBootUser(InitialUserInfoRequestType.RESUME));
Mayank Garg0baf88a2020-08-30 21:57:36 -0700824 }
825
826 /**
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700827 * Calls to start user at the android startup.
Mayank Garg70732a82020-08-05 20:17:47 -0700828 */
829 public void initBootUser() {
Mayank Garg02576972021-02-18 16:46:07 -0800830 mHandler.post(() -> initBootUser(getInitialUserInfoRequestType()));
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700831 }
832
Mayank Garg7e1450b2020-08-07 18:15:15 -0700833 private void initBootUser(int requestType) {
834 boolean replaceGuest =
835 requestType == InitialUserInfoRequestType.RESUME && !mSwitchGuestUserBeforeSleep;
Mayank Garg70732a82020-08-05 20:17:47 -0700836 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_REQ, requestType,
837 mHalTimeoutMs);
838 checkManageUsersPermission("startInitialUser");
839
840 if (!isUserHalSupported()) {
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700841 fallbackToDefaultInitialUserBehavior(/* userLocales= */ null, replaceGuest);
Mayank Gargfd1e0692021-05-25 13:33:48 -0700842 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_REQ_COMPLETE,
843 requestType);
Mayank Garg70732a82020-08-05 20:17:47 -0700844 return;
845 }
846
847 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
848 mHal.getInitialUserInfo(requestType, mHalTimeoutMs, usersInfo, (status, resp) -> {
849 if (resp != null) {
850 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_RESP,
851 status, resp.action, resp.userToSwitchOrCreate.userId,
852 resp.userToSwitchOrCreate.flags, resp.userNameToCreate, resp.userLocales);
853
854 String userLocales = resp.userLocales;
855 InitialUserInfo info;
856 switch (resp.action) {
857 case InitialUserInfoResponseAction.SWITCH:
858 int userId = resp.userToSwitchOrCreate.userId;
859 if (userId <= 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800860 Slog.w(TAG, "invalid (or missing) user id sent by HAL: " + userId);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700861 fallbackToDefaultInitialUserBehavior(userLocales, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700862 break;
863 }
864 info = new InitialUserSetter.Builder(InitialUserSetter.TYPE_SWITCH)
865 .setUserLocales(userLocales)
866 .setSwitchUserId(userId)
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700867 .setReplaceGuest(replaceGuest)
Mayank Garg70732a82020-08-05 20:17:47 -0700868 .build();
869 mInitialUserSetter.set(info);
870 break;
871
872 case InitialUserInfoResponseAction.CREATE:
873 int halFlags = resp.userToSwitchOrCreate.flags;
874 String userName = resp.userNameToCreate;
875 info = new InitialUserSetter.Builder(InitialUserSetter.TYPE_CREATE)
876 .setUserLocales(userLocales)
877 .setNewUserName(userName)
878 .setNewUserFlags(halFlags)
879 .build();
880 mInitialUserSetter.set(info);
881 break;
882
883 case InitialUserInfoResponseAction.DEFAULT:
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700884 fallbackToDefaultInitialUserBehavior(userLocales, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700885 break;
886 default:
Eric Jeongf75d4132020-12-21 13:48:23 -0800887 Slog.w(TAG, "invalid response action on " + resp);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700888 fallbackToDefaultInitialUserBehavior(/* user locale */ null, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700889 break;
890
891 }
892 } else {
893 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_RESP, status);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700894 fallbackToDefaultInitialUserBehavior(/* user locale */ null, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700895 }
Mayank Gargfd1e0692021-05-25 13:33:48 -0700896 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_REQ_COMPLETE,
897 requestType);
Mayank Garg70732a82020-08-05 20:17:47 -0700898 });
899 }
900
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700901 private void fallbackToDefaultInitialUserBehavior(String userLocales, boolean replaceGuest) {
Mayank Garg70732a82020-08-05 20:17:47 -0700902 InitialUserInfo info = new InitialUserSetter.Builder(
903 InitialUserSetter.TYPE_DEFAULT_BEHAVIOR)
904 .setUserLocales(userLocales)
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700905 .setReplaceGuest(replaceGuest)
Mayank Garg70732a82020-08-05 20:17:47 -0700906 .build();
907 mInitialUserSetter.set(info);
908 }
909
910 @VisibleForTesting
911 int getInitialUserInfoRequestType() {
Mayank Garge90a4082020-09-30 12:57:34 -0700912 if (!mInitialUserSetter.hasInitialUser()) {
Mayank Garg70732a82020-08-05 20:17:47 -0700913 return InitialUserInfoRequestType.FIRST_BOOT;
914 }
915 if (mContext.getPackageManager().isDeviceUpgrading()) {
916 return InitialUserInfoRequestType.FIRST_BOOT_AFTER_OTA;
917 }
918 return InitialUserInfoRequestType.COLD_BOOT;
919 }
920
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800921 /**
922 * Sets the {@link ICarServiceHelper} so it can receive UX restriction updates.
923 */
924 public void setCarServiceHelper(ICarServiceHelper helper) {
925 boolean restricted;
926 synchronized (mLockUser) {
927 mICarServiceHelper = helper;
928 restricted = mUxRestricted;
929 }
930 updateSafetyMode(helper, restricted);
931 }
932
933 private void updateSafetyMode(@Nullable ICarServiceHelper helper, boolean restricted) {
934 if (helper == null) return;
935
936 boolean isSafe = !restricted;
937 try {
938 helper.setSafetyMode(isSafe);
939 } catch (Exception e) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800940 Slog.e(TAG, "Exception calling helper.setDpmSafetyMode(" + isSafe + ")", e);
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800941 }
942 }
943
944 private void setUxRestrictions(@Nullable CarUxRestrictions restrictions) {
Felipe Leme5d5ab142020-10-27 13:49:10 -0700945 boolean restricted = restrictions != null
946 && (restrictions.getActiveRestrictions() & UX_RESTRICTIONS_NO_SETUP)
947 == UX_RESTRICTIONS_NO_SETUP;
Eric Jeongf75d4132020-12-21 13:48:23 -0800948 if (Log.isLoggable(TAG, Log.DEBUG)) {
949 Slog.d(TAG, "setUxRestrictions(" + restrictions + "): restricted=" + restricted);
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800950 } else {
Eric Jeongf75d4132020-12-21 13:48:23 -0800951 Slog.i(TAG, "Setting UX restricted to " + restricted);
Felipe Leme5d5ab142020-10-27 13:49:10 -0700952 }
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800953
954 ICarServiceHelper helper = null;
955
956 synchronized (mLockUser) {
957 mUxRestricted = restricted;
958 if (mICarServiceHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -0800959 Slog.e(TAG, "onUxRestrictionsChanged(): no mICarServiceHelper");
Felipe Leme56ef9ad2020-11-05 18:39:03 -0800960 }
961 helper = mICarServiceHelper;
962 }
963 updateSafetyMode(helper, restricted);
964 }
965
966 private boolean isUxRestricted() {
967 synchronized (mLockUser) {
968 return mUxRestricted;
969 }
Felipe Leme5d5ab142020-10-27 13:49:10 -0700970 }
971
Mayank Garg70732a82020-08-05 20:17:47 -0700972 /**
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700973 * Calls the {@link UserHalService} and {@link IActivityManager} for user switch.
974 *
975 * <p>
Mayank Gargb08f6772020-05-01 18:06:48 -0700976 * When everything works well, the workflow is:
977 * <ol>
978 * <li> {@link UserHalService} is called for HAL user switch with ANDROID_SWITCH request
979 * type, current user id, target user id, and a callback.
980 * <li> HAL called back with SUCCESS.
981 * <li> {@link IActivityManager} is called for Android user switch.
982 * <li> Receiver would receive {@code STATUS_SUCCESSFUL}.
983 * <li> Once user is unlocked, {@link UserHalService} is again called with ANDROID_POST_SWITCH
984 * request type, current user id, and target user id. In this case, the current and target
985 * user IDs would be same.
986 * <ol/>
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700987 *
988 * <p>
Mayank Gargb08f6772020-05-01 18:06:48 -0700989 * Corner cases:
990 * <ul>
991 * <li> If target user is already the current user, no user switch is performed and receiver
Mayank Gargef1b9332020-06-11 17:36:56 -0700992 * would receive {@code STATUS_OK_USER_ALREADY_IN_FOREGROUND} right away.
Mayank Gargb08f6772020-05-01 18:06:48 -0700993 * <li> If HAL user switch call fails, no Android user switch. Receiver would receive
994 * {@code STATUS_HAL_INTERNAL_FAILURE}.
995 * <li> If HAL user switch call is successful, but android user switch call fails,
996 * {@link UserHalService} is again called with request type POST_SWITCH, current user id, and
997 * target user id, but in this case the current and target user IDs would be different.
998 * <li> If another user switch request for the same target user is received while previous
999 * request is in process, receiver would receive
1000 * {@code STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO} for the new request right away.
1001 * <li> If a user switch request is received while another user switch request for different
1002 * target user is in process, the previous request would be abandoned and new request will be
1003 * processed. No POST_SWITCH would be sent for the previous request.
1004 * <ul/>
Mayank Garg59f22192020-03-27 00:51:45 -07001005 *
Mayank Garge19c2922020-03-30 18:05:53 -07001006 * @param targetUserId - target user Id
Mayank Garg59f22192020-03-27 00:51:45 -07001007 * @param timeoutMs - timeout for HAL to wait
1008 * @param receiver - receiver for the results
1009 */
Mayank Garge19c2922020-03-30 18:05:53 -07001010 @Override
1011 public void switchUser(@UserIdInt int targetUserId, int timeoutMs,
felipeale5bf0322020-04-16 15:10:57 -07001012 @NonNull AndroidFuture<UserSwitchResult> receiver) {
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001013 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_REQ, targetUserId, timeoutMs);
Felipe Leme17799202020-09-03 12:55:53 -07001014 checkManageOrCreateUsersPermission("switchUser");
Mayank Garge19c2922020-03-30 18:05:53 -07001015 Objects.requireNonNull(receiver);
1016 UserInfo targetUser = mUserManager.getUserInfo(targetUserId);
felipealf7368962020-04-16 12:55:19 -07001017 Preconditions.checkArgument(targetUser != null, "Target user doesn't exist");
Mayank Garga479cb32021-04-05 22:23:04 -07001018 if (mUserManager.getUserSwitchability() != UserManager.SWITCHABILITY_STATUS_OK) {
1019 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_NOT_SWITCHABLE);
1020 return;
1021 }
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001022 mHandler.post(() -> handleSwitchUser(targetUser, timeoutMs, receiver));
Mayank Garg02576972021-02-18 16:46:07 -08001023 }
Mayank Garg7a114c82020-04-08 21:25:06 -07001024
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001025 private void handleSwitchUser(@NonNull UserInfo targetUser, int timeoutMs,
Mayank Garg02576972021-02-18 16:46:07 -08001026 @NonNull AndroidFuture<UserSwitchResult> receiver) {
felipealf7368962020-04-16 12:55:19 -07001027 int currentUser = ActivityManager.getCurrentUser();
Mayank Garg02576972021-02-18 16:46:07 -08001028 int targetUserId = targetUser.id;
felipealf7368962020-04-16 12:55:19 -07001029 if (currentUser == targetUserId) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001030 if (Log.isLoggable(TAG, Log.DEBUG)) {
1031 Slog.d(TAG, "Current user is same as requested target user: " + targetUserId);
Mayank Garg0e239142020-04-14 19:16:31 -07001032 }
Mayank Gargef1b9332020-06-11 17:36:56 -07001033 int resultStatus = UserSwitchResult.STATUS_OK_USER_ALREADY_IN_FOREGROUND;
felipealdfdf8512020-06-01 09:35:45 -07001034 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg0e239142020-04-14 19:16:31 -07001035 return;
1036 }
1037
Felipe Leme5d5ab142020-10-27 13:49:10 -07001038 if (isUxRestricted()) {
1039 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_UX_RESTRICTION_FAILURE);
1040 return;
1041 }
1042
Mayank Garg9ed099e2020-06-04 16:05:20 -07001043 // If User Hal is not supported, just android user switch.
1044 if (!isUserHalSupported()) {
1045 try {
1046 if (mAm.switchUser(targetUserId)) {
1047 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_SUCCESSFUL);
1048 return;
1049 }
1050 } catch (RemoteException e) {
1051 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001052 Slog.w(TAG, "error while switching user " + targetUser.toFullString(), e);
Mayank Garg9ed099e2020-06-04 16:05:20 -07001053 }
1054 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_ANDROID_FAILURE);
1055 return;
1056 }
1057
Mayank Garg7a114c82020-04-08 21:25:06 -07001058 synchronized (mLockUser) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001059 if (Log.isLoggable(TAG, Log.DEBUG)) {
1060 Slog.d(TAG, "switchUser(" + targetUserId + "): currentuser=" + currentUser
felipealf7368962020-04-16 12:55:19 -07001061 + ", mUserIdForUserSwitchInProcess=" + mUserIdForUserSwitchInProcess);
1062 }
1063
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001064 // If there is another request for the same target user, return another request in
1065 // process, else {@link mUserIdForUserSwitchInProcess} is updated and {@link
1066 // mRequestIdForUserSwitchInProcess} is reset. It is possible that there may be another
1067 // user switch request in process for different target user, but that request is now
1068 // ignored.
felipealf7368962020-04-16 12:55:19 -07001069 if (mUserIdForUserSwitchInProcess == targetUserId) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001070 if (Log.isLoggable(TAG, Log.DEBUG)) {
1071 Slog.d(TAG,
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001072 "Another user switch request in process for the requested target user: "
1073 + targetUserId);
1074 }
1075
1076 int resultStatus = UserSwitchResult.STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO;
felipealdfdf8512020-06-01 09:35:45 -07001077 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg7a114c82020-04-08 21:25:06 -07001078 return;
Mayank Garg02576972021-02-18 16:46:07 -08001079 } else {
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001080 mUserIdForUserSwitchInProcess = targetUserId;
1081 mRequestIdForUserSwitchInProcess = 0;
1082 }
Mayank Garg7a114c82020-04-08 21:25:06 -07001083 }
1084
felipealdfdf8512020-06-01 09:35:45 -07001085 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
Mayank Gargeb37d092020-06-02 14:37:57 -07001086 SwitchUserRequest request = createUserSwitchRequest(targetUserId, usersInfo);
1087
Felipe Leme5d5ab142020-10-27 13:49:10 -07001088 mHal.switchUser(request, timeoutMs, (halCallbackStatus, resp) -> {
Eric Jeongf75d4132020-12-21 13:48:23 -08001089 if (Log.isLoggable(TAG, Log.DEBUG)) {
1090 Slog.d(TAG, "switch response: status="
Felipe Leme5d5ab142020-10-27 13:49:10 -07001091 + UserHalHelper.halCallbackStatusToString(halCallbackStatus)
1092 + ", resp=" + resp);
felipealf7368962020-04-16 12:55:19 -07001093 }
1094
felipeale5bf0322020-04-16 15:10:57 -07001095 int resultStatus = UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE;
felipealf7368962020-04-16 12:55:19 -07001096
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001097 synchronized (mLockUser) {
Felipe Leme5d5ab142020-10-27 13:49:10 -07001098 if (halCallbackStatus != HalCallback.STATUS_OK) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001099 Slog.w(TAG, "invalid callback status ("
Felipe Leme5d5ab142020-10-27 13:49:10 -07001100 + UserHalHelper.halCallbackStatusToString(halCallbackStatus)
1101 + ") for response " + resp);
felipealdfdf8512020-06-01 09:35:45 -07001102 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001103 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
1104 return;
1105 }
felipealf7368962020-04-16 12:55:19 -07001106
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001107 if (mUserIdForUserSwitchInProcess != targetUserId) {
1108 // Another user switch request received while HAL responded. No need to process
1109 // this request further
Eric Jeongf75d4132020-12-21 13:48:23 -08001110 if (Log.isLoggable(TAG, Log.DEBUG)) {
1111 Slog.d(TAG, "Another user switch received while HAL responsed. Request"
1112 + " abondoned for : " + targetUserId + ". Current user in process: "
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001113 + mUserIdForUserSwitchInProcess);
felipealf7368962020-04-16 12:55:19 -07001114 }
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001115 resultStatus =
1116 UserSwitchResult.STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST;
felipealdfdf8512020-06-01 09:35:45 -07001117 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001118 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
1119 return;
1120 }
1121
1122 switch (resp.status) {
1123 case SwitchUserStatus.SUCCESS:
1124 boolean switched;
1125 try {
1126 switched = mAm.switchUser(targetUserId);
1127 if (switched) {
Mayank Garg587f1942020-05-06 01:41:34 -07001128 sendUserSwitchUiCallback(targetUserId);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001129 resultStatus = UserSwitchResult.STATUS_SUCCESSFUL;
1130 mRequestIdForUserSwitchInProcess = resp.requestId;
1131 } else {
1132 resultStatus = UserSwitchResult.STATUS_ANDROID_FAILURE;
1133 postSwitchHalResponse(resp.requestId, targetUserId);
1134 }
1135 } catch (RemoteException e) {
1136 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001137 Slog.w(TAG,
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001138 "error while switching user " + targetUser.toFullString(), e);
1139 }
1140 break;
1141 case SwitchUserStatus.FAILURE:
1142 // HAL failed to switch user
1143 resultStatus = UserSwitchResult.STATUS_HAL_FAILURE;
1144 break;
felipealdfdf8512020-06-01 09:35:45 -07001145 default:
1146 // Shouldn't happen because UserHalService validates the status
Eric Jeongf75d4132020-12-21 13:48:23 -08001147 Slog.wtf(TAG, "Received invalid user switch status from HAL: " + resp);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001148 }
1149
1150 if (mRequestIdForUserSwitchInProcess == 0) {
1151 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
1152 }
Mayank Garg59f22192020-03-27 00:51:45 -07001153 }
Felipe Leme5d5ab142020-10-27 13:49:10 -07001154 sendUserSwitchResult(receiver, halCallbackStatus, resultStatus, resp.errorMessage);
Mayank Garg59f22192020-03-27 00:51:45 -07001155 });
1156 }
1157
Mayank Garga55c3092020-05-28 03:19:24 -07001158 @Override
Mayank Gargc9266482021-03-01 10:27:37 -08001159 public void removeUser(@UserIdInt int userId, AndroidFuture<UserRemovalResult> receiver) {
1160 removeUser(userId, /* hasCallerRestrictions= */ false, receiver);
Felipe Leme55236722020-10-16 16:54:32 -07001161 }
1162
1163 /**
1164 * Internal implementation of {@code removeUser()}, which is used by both
1165 * {@code ICarUserService} and {@code ICarDevicePolicyService}.
1166 *
1167 * @param userId user to be removed
1168 * @param hasCallerRestrictions when {@code true}, if the caller user is not an admin, it can
1169 * only remove itself.
Mayank Gargc9266482021-03-01 10:27:37 -08001170 * @param receiver to post results
Felipe Leme55236722020-10-16 16:54:32 -07001171 */
Mayank Gargc9266482021-03-01 10:27:37 -08001172 public void removeUser(@UserIdInt int userId, boolean hasCallerRestrictions,
1173 AndroidFuture<UserRemovalResult> receiver) {
Felipe Leme17799202020-09-03 12:55:53 -07001174 checkManageOrCreateUsersPermission("removeUser");
Felipe Leme55236722020-10-16 16:54:32 -07001175 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_REMOVE_USER_REQ, userId,
1176 hasCallerRestrictions ? 1 : 0);
Felipe Lemee5bb26b2020-10-26 15:49:17 -07001177
Felipe Lemee5bb26b2020-10-26 15:49:17 -07001178 if (hasCallerRestrictions) {
1179 // Restrictions: non-admin user can only remove itself, admins have no restrictions
1180 int callingUserId = Binder.getCallingUserHandle().getIdentifier();
1181 UserInfo callingUser = mUserManager.getUserInfo(callingUserId);
1182 if (!callingUser.isAdmin() && userId != callingUserId) {
1183 throw new SecurityException("Non-admin user " + callingUserId
1184 + " can only remove itself");
1185 }
1186 }
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001187 mHandler.post(() -> handleRemoveUser(userId, hasCallerRestrictions, receiver));
Mayank Gargc9266482021-03-01 10:27:37 -08001188 }
Felipe Lemee5bb26b2020-10-26 15:49:17 -07001189
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001190 private void handleRemoveUser(@UserIdInt int userId, boolean hasCallerRestrictions,
Mayank Gargc9266482021-03-01 10:27:37 -08001191 AndroidFuture<UserRemovalResult> receiver) {
1192 UserInfo userInfo = mUserManager.getUserInfo(userId);
1193 if (userInfo == null) {
1194 sendUserRemovalResult(userId, UserRemovalResult.STATUS_USER_DOES_NOT_EXIST, receiver);
1195 return;
1196 }
Mayank Garga55c3092020-05-28 03:19:24 -07001197 android.hardware.automotive.vehicle.V2_0.UserInfo halUser =
1198 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1199 halUser.userId = userInfo.id;
1200 halUser.flags = UserHalHelper.convertFlags(userInfo);
1201 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1202
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001203 // check if the user is last admin user.
1204 boolean isLastAdmin = false;
Mayank Garga55c3092020-05-28 03:19:24 -07001205 if (UserHalHelper.isAdmin(halUser.flags)) {
1206 int size = usersInfo.existingUsers.size();
1207 int totalAdminUsers = 0;
1208 for (int i = 0; i < size; i++) {
1209 if (UserHalHelper.isAdmin(usersInfo.existingUsers.get(i).flags)) {
1210 totalAdminUsers++;
1211 }
1212 }
1213 if (totalAdminUsers == 1) {
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001214 isLastAdmin = true;
Mayank Garga55c3092020-05-28 03:19:24 -07001215 }
1216 }
1217
1218 // First remove user from android and then remove from HAL because HAL remove user is one
1219 // way call.
Felipe Leme9a751912021-01-05 17:45:48 -08001220 // TODO(b/170887769): rename hasCallerRestrictions to fromCarDevicePolicyManager (or use an
1221 // int / enum to indicate if it's called from CarUserManager or CarDevicePolicyManager), as
1222 // it's counter-intuitive that it's "allowed even when disallowed" when it
1223 // "has caller restrictions"
1224 boolean evenWhenDisallowed = hasCallerRestrictions;
1225 int result = mUserManager.removeUserOrSetEphemeral(userId, evenWhenDisallowed);
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001226 if (result == UserManager.REMOVE_RESULT_ERROR) {
Mayank Gargc9266482021-03-01 10:27:37 -08001227 sendUserRemovalResult(userId, UserRemovalResult.STATUS_ANDROID_FAILURE, receiver);
1228 return;
Mayank Garga55c3092020-05-28 03:19:24 -07001229 }
1230
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001231 if (isLastAdmin) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001232 Slog.w(TAG,
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001233 "Last admin user successfully removed or set ephemeral. User Id: " + userId);
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001234 }
1235
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001236 switch (result) {
1237 case UserManager.REMOVE_RESULT_REMOVED:
1238 case UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED:
Mayank Gargc9266482021-03-01 10:27:37 -08001239 sendUserRemovalResult(userId,
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001240 isLastAdmin ? UserRemovalResult.STATUS_SUCCESSFUL_LAST_ADMIN_REMOVED
Mayank Gargc9266482021-03-01 10:27:37 -08001241 : UserRemovalResult.STATUS_SUCCESSFUL, receiver);
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001242 case UserManager.REMOVE_RESULT_SET_EPHEMERAL:
Mayank Gargc9266482021-03-01 10:27:37 -08001243 sendUserRemovalResult(userId,
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001244 isLastAdmin ? UserRemovalResult.STATUS_SUCCESSFUL_LAST_ADMIN_SET_EPHEMERAL
Mayank Gargc9266482021-03-01 10:27:37 -08001245 : UserRemovalResult.STATUS_SUCCESSFUL_SET_EPHEMERAL, receiver);
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001246 default:
Mayank Gargc9266482021-03-01 10:27:37 -08001247 sendUserRemovalResult(userId, UserRemovalResult.STATUS_ANDROID_FAILURE, receiver);
Jordan Jozwiakffcdca52020-10-15 15:22:01 -07001248 }
Mayank Garga55c3092020-05-28 03:19:24 -07001249 }
1250
Felipe Leme67d564c2020-11-13 15:35:34 -08001251 /**
1252 * Should be called by {@code ICarImpl} only.
1253 */
1254 public void onUserRemoved(@NonNull UserInfo user) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001255 if (Log.isLoggable(TAG, Log.DEBUG)) {
1256 Slog.d(TAG, "onUserRemoved: " + user.toFullString());
Felipe Leme67d564c2020-11-13 15:35:34 -08001257 }
1258 notifyHalUserRemoved(user);
1259 }
1260
1261 private void notifyHalUserRemoved(@NonNull UserInfo user) {
Felipe Leme6b34fc32020-10-26 15:49:17 -07001262 if (!isUserHalSupported()) return;
1263
Felipe Leme67d564c2020-11-13 15:35:34 -08001264 if (user == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001265 Slog.wtf(TAG, "notifyHalUserRemoved() called for null user");
Felipe Leme67d564c2020-11-13 15:35:34 -08001266 return;
1267 }
1268
1269 int userId = user.id;
1270
Felipe Leme6b34fc32020-10-26 15:49:17 -07001271 if (userId == UserHandle.USER_NULL) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001272 Slog.wtf(TAG, "notifyHalUserRemoved() called for UserHandle.USER_NULL");
Felipe Leme6b34fc32020-10-26 15:49:17 -07001273 return;
1274 }
1275
1276 synchronized (mLockUser) {
1277 if (mFailedToCreateUserIds.get(userId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001278 if (Log.isLoggable(TAG, Log.DEBUG)) {
1279 Slog.d(TAG, "notifyHalUserRemoved(): skipping " + userId);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001280 }
1281 mFailedToCreateUserIds.delete(userId);
1282 return;
1283 }
1284 }
1285
1286 android.hardware.automotive.vehicle.V2_0.UserInfo halUser =
1287 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1288 halUser.userId = userId;
Felipe Leme67d564c2020-11-13 15:35:34 -08001289 halUser.flags = UserHalHelper.convertFlags(user);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001290
1291 RemoveUserRequest request = new RemoveUserRequest();
1292 request.removedUserInfo = halUser;
1293 request.usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1294 mHal.removeUser(request);
1295 }
1296
Mayank Gargc9266482021-03-01 10:27:37 -08001297 private void sendUserRemovalResult(@UserIdInt int userId, @UserRemovalResult.Status int result,
1298 AndroidFuture<UserRemovalResult> receiver) {
Mayank Garga55c3092020-05-28 03:19:24 -07001299 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_REMOVE_USER_RESP, userId, result);
Mayank Gargc9266482021-03-01 10:27:37 -08001300 receiver.complete(new UserRemovalResult(result));
Mayank Garga55c3092020-05-28 03:19:24 -07001301 }
1302
Mayank Garg587f1942020-05-06 01:41:34 -07001303 private void sendUserSwitchUiCallback(@UserIdInt int targetUserId) {
1304 if (mUserSwitchUiReceiver == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001305 Slog.w(TAG, "No User switch UI receiver.");
Mayank Garg587f1942020-05-06 01:41:34 -07001306 return;
1307 }
1308
felipealdfdf8512020-06-01 09:35:45 -07001309 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_UI_REQ, targetUserId);
Mayank Garg587f1942020-05-06 01:41:34 -07001310 try {
Mayank Garg587f1942020-05-06 01:41:34 -07001311 mUserSwitchUiReceiver.send(targetUserId, null);
1312 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001313 Slog.e(TAG, "Error calling user switch UI receiver.", e);
Mayank Garg587f1942020-05-06 01:41:34 -07001314 }
1315 }
1316
Felipe Lemecceb2992020-11-18 18:22:44 -08001317 /**
1318 * Used to create the initial user, even when it's disallowed by {@code DevicePolicyManager}.
1319 */
1320 @Nullable
1321 UserInfo createUserEvenWhenDisallowed(@Nullable String name, @NonNull String userType,
1322 @UserInfoFlag int flags) {
1323 if (mICarServiceHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001324 Slog.wtf(TAG, "createUserEvenWhenDisallowed(): mICarServiceHelper not set yet",
Felipe Lemecceb2992020-11-18 18:22:44 -08001325 new Exception());
1326 return null;
1327 }
1328 try {
1329 return mICarServiceHelper.createUserEvenWhenDisallowed(name, userType, flags);
1330 } catch (RemoteException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001331 Slog.e(TAG, "createUserEvenWhenDisallowed(" + UserHelperLite.safeName(name) + ", "
Felipe Lemecceb2992020-11-18 18:22:44 -08001332 + userType + ", " + UserInfo.flagsToString(flags) + ") failed", e);
1333 return null;
1334 }
1335 }
1336
felipeal5e3ede42020-04-23 18:04:07 -07001337 @Override
felipealdfdf8512020-06-01 09:35:45 -07001338 public void createUser(@Nullable String name, @NonNull String userType, @UserInfoFlag int flags,
1339 int timeoutMs, @NonNull AndroidFuture<UserCreationResult> receiver) {
Felipe Leme8c888ab2020-11-02 17:39:52 -08001340 createUser(name, userType, flags, timeoutMs, receiver, /* hasCallerRestrictions= */ false);
1341 }
1342
1343 /**
1344 * Internal implementation of {@code createUser()}, which is used by both
1345 * {@code ICarUserService} and {@code ICarDevicePolicyService}.
1346 *
1347 * @param hasCallerRestrictions when {@code true}, if the caller user is not an admin, it can
1348 * only create admin users
1349 */
1350 public void createUser(@Nullable String name, @NonNull String userType, @UserInfoFlag int flags,
1351 int timeoutMs, @NonNull AndroidFuture<UserCreationResult> receiver,
1352 boolean hasCallerRestrictions) {
felipealdfdf8512020-06-01 09:35:45 -07001353 Objects.requireNonNull(userType, "user type cannot be null");
1354 Objects.requireNonNull(receiver, "receiver cannot be null");
Felipe Leme17799202020-09-03 12:55:53 -07001355 checkManageOrCreateUsersPermission(flags);
Mayank Garg94f3eb92020-08-12 12:38:58 -07001356 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_REQ,
Felipe Leme8c888ab2020-11-02 17:39:52 -08001357 UserHelperLite.safeName(name), userType, flags, timeoutMs,
1358 hasCallerRestrictions ? 1 : 0);
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001359 mHandler.post(() -> handleCreateUser(name, userType, flags, timeoutMs, receiver,
Mayank Garg02576972021-02-18 16:46:07 -08001360 hasCallerRestrictions));
Felipe Leme8c888ab2020-11-02 17:39:52 -08001361
Mayank Garg02576972021-02-18 16:46:07 -08001362 }
1363
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001364 private void handleCreateUser(@Nullable String name, @NonNull String userType,
Mayank Garg02576972021-02-18 16:46:07 -08001365 @UserInfoFlag int flags, int timeoutMs,
1366 @NonNull AndroidFuture<UserCreationResult> receiver,
1367 boolean hasCallerRestrictions) {
Felipe Leme8c888ab2020-11-02 17:39:52 -08001368 if (hasCallerRestrictions) {
1369 // Restrictions:
1370 // - type/flag can only be normal user, admin, or guest
1371 // - non-admin user can only create non-admin users
1372
1373 boolean validCombination;
1374 switch (userType) {
1375 case UserManager.USER_TYPE_FULL_SECONDARY:
1376 validCombination = flags == 0
1377 || (flags & UserInfo.FLAG_ADMIN) == UserInfo.FLAG_ADMIN;
1378 break;
1379 case UserManager.USER_TYPE_FULL_GUEST:
1380 validCombination = flags == 0;
1381 break;
1382 default:
1383 validCombination = false;
1384 }
1385 if (!validCombination) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001386 if (Log.isLoggable(TAG, Log.DEBUG)) {
1387 Slog.d(TAG, "Invalid combination of user type(" + userType
Felipe Leme71d296f2020-11-04 12:11:42 -08001388 + ") and flags (" + UserInfo.flagsToString(flags)
1389 + ") for caller with restrictions");
1390 }
1391 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_INVALID_REQUEST);
1392 return;
1393
Felipe Leme8c888ab2020-11-02 17:39:52 -08001394 }
1395
1396 int callingUserId = Binder.getCallingUserHandle().getIdentifier();
1397 UserInfo callingUser = mUserManager.getUserInfo(callingUserId);
1398 if (!callingUser.isAdmin() && (flags & UserInfo.FLAG_ADMIN) == UserInfo.FLAG_ADMIN) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001399 if (Log.isLoggable(TAG, Log.DEBUG)) {
1400 Slog.d(TAG, "Non-admin user " + callingUserId
Felipe Leme71d296f2020-11-04 12:11:42 -08001401 + " can only create non-admin users");
1402 }
1403 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_INVALID_REQUEST);
1404 return;
Felipe Leme8c888ab2020-11-02 17:39:52 -08001405 }
Felipe Leme71d296f2020-11-04 12:11:42 -08001406
Felipe Leme8c888ab2020-11-02 17:39:52 -08001407 }
felipealdfdf8512020-06-01 09:35:45 -07001408
1409 UserInfo newUser;
1410 try {
1411 newUser = mUserManager.createUser(name, userType, flags);
1412 if (newUser == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001413 Slog.w(TAG, "um.createUser() returned null for user of type " + userType
felipealdfdf8512020-06-01 09:35:45 -07001414 + " and flags " + UserInfo.flagsToString(flags));
1415 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_ANDROID_FAILURE);
1416 return;
1417 }
Eric Jeongf75d4132020-12-21 13:48:23 -08001418 if (Log.isLoggable(TAG, Log.DEBUG)) {
1419 Slog.d(TAG, "Created user: " + newUser.toFullString());
felipealdfdf8512020-06-01 09:35:45 -07001420 }
1421 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_USER_CREATED, newUser.id,
Mayank Garg94f3eb92020-08-12 12:38:58 -07001422 UserHelperLite.safeName(newUser.name), newUser.userType, newUser.flags);
felipealdfdf8512020-06-01 09:35:45 -07001423 } catch (RuntimeException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001424 Slog.e(TAG, "Error creating user of type " + userType + " and flags"
felipealdfdf8512020-06-01 09:35:45 -07001425 + UserInfo.flagsToString(flags), e);
1426 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_ANDROID_FAILURE);
1427 return;
1428 }
1429
Mayank Garg9ed099e2020-06-04 16:05:20 -07001430 if (!isUserHalSupported()) {
1431 sendUserCreationResult(receiver, UserCreationResult.STATUS_SUCCESSFUL, newUser, null);
1432 return;
1433 }
1434
felipealdfdf8512020-06-01 09:35:45 -07001435 CreateUserRequest request = new CreateUserRequest();
1436 request.usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1437 if (!TextUtils.isEmpty(name)) {
1438 request.newUserName = name;
1439 }
1440 request.newUserInfo.userId = newUser.id;
1441 request.newUserInfo.flags = UserHalHelper.convertFlags(newUser);
Eric Jeongf75d4132020-12-21 13:48:23 -08001442 if (Log.isLoggable(TAG, Log.DEBUG)) {
1443 Slog.d(TAG, "Create user request: " + request);
felipealdfdf8512020-06-01 09:35:45 -07001444 }
1445
1446 try {
1447 mHal.createUser(request, timeoutMs, (status, resp) -> {
1448 int resultStatus = UserCreationResult.STATUS_HAL_INTERNAL_FAILURE;
Eric Jeongf75d4132020-12-21 13:48:23 -08001449 if (Log.isLoggable(TAG, Log.DEBUG)) {
1450 Slog.d(TAG, "createUserResponse: status="
felipealdfdf8512020-06-01 09:35:45 -07001451 + UserHalHelper.halCallbackStatusToString(status) + ", resp=" + resp);
1452 }
1453 UserInfo user = null; // user returned in the result
1454 if (status != HalCallback.STATUS_OK) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001455 Slog.w(TAG, "invalid callback status ("
felipealdfdf8512020-06-01 09:35:45 -07001456 + UserHalHelper.halCallbackStatusToString(status) + ") for response "
1457 + resp);
1458 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_RESP, status,
1459 resultStatus, resp.errorMessage);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001460 removeCreatedUser(newUser, "HAL call failed with "
felipealdfdf8512020-06-01 09:35:45 -07001461 + UserHalHelper.halCallbackStatusToString(status));
1462 sendUserCreationResult(receiver, resultStatus, user, /* errorMsg= */ null);
1463 return;
1464 }
1465
1466 switch (resp.status) {
1467 case CreateUserStatus.SUCCESS:
1468 resultStatus = UserCreationResult.STATUS_SUCCESSFUL;
1469 user = newUser;
1470 break;
1471 case CreateUserStatus.FAILURE:
1472 // HAL failed to switch user
1473 resultStatus = UserCreationResult.STATUS_HAL_FAILURE;
1474 break;
1475 default:
1476 // Shouldn't happen because UserHalService validates the status
Eric Jeongf75d4132020-12-21 13:48:23 -08001477 Slog.wtf(TAG, "Received invalid user switch status from HAL: " + resp);
felipealdfdf8512020-06-01 09:35:45 -07001478 }
1479 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_RESP, status,
1480 resultStatus, resp.errorMessage);
1481 if (user == null) {
Felipe Leme6b34fc32020-10-26 15:49:17 -07001482 removeCreatedUser(newUser, "HAL returned "
felipealdfdf8512020-06-01 09:35:45 -07001483 + UserCreationResult.statusToString(resultStatus));
1484 }
1485 sendUserCreationResult(receiver, resultStatus, user, resp.errorMessage);
1486 });
1487 } catch (Exception e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001488 Slog.w(TAG, "mHal.createUser(" + request + ") failed", e);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001489 removeCreatedUser(newUser, "mHal.createUser() failed");
felipealdfdf8512020-06-01 09:35:45 -07001490 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_HAL_INTERNAL_FAILURE);
1491 }
1492 }
1493
Felipe Leme6b34fc32020-10-26 15:49:17 -07001494 private void removeCreatedUser(@NonNull UserInfo user, @NonNull String reason) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001495 Slog.i(TAG, "removing " + user.toFullString() + "; reason: " + reason);
Felipe Leme67d564c2020-11-13 15:35:34 -08001496
Felipe Leme6b34fc32020-10-26 15:49:17 -07001497 int userId = user.id;
1498 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_USER_REMOVED, userId, reason);
1499
1500 synchronized (mLockUser) {
1501 mFailedToCreateUserIds.put(userId, true);
1502 }
1503
felipealdfdf8512020-06-01 09:35:45 -07001504 try {
Felipe Leme6b34fc32020-10-26 15:49:17 -07001505 if (!mUserManager.removeUser(userId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001506 Slog.w(TAG, "Failed to remove user " + user.toFullString());
felipealdfdf8512020-06-01 09:35:45 -07001507 }
1508 } catch (Exception e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001509 Slog.e(TAG, "Failed to remove user " + user.toFullString(), e);
felipealdfdf8512020-06-01 09:35:45 -07001510 }
1511 }
1512
1513 @Override
Mayank Garg3f566582020-10-02 22:10:16 -07001514 public UserIdentificationAssociationResponse getUserIdentificationAssociation(
1515 @UserIdentificationAssociationType int[] types) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001516 if (!isUserHalUserAssociationSupported()) {
1517 return UserIdentificationAssociationResponse.forFailure(VEHICLE_HAL_NOT_SUPPORTED);
1518 }
1519
felipeal5e3ede42020-04-23 18:04:07 -07001520 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type");
Felipe Leme17799202020-09-03 12:55:53 -07001521 checkManageOrCreateUsersPermission("getUserIdentificationAssociation");
felipeal5e3ede42020-04-23 18:04:07 -07001522
1523 int uid = getCallingUid();
1524 int userId = UserHandle.getUserId(uid);
1525 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_GET_USER_AUTH_REQ, uid, userId);
1526
1527 UserIdentificationGetRequest request = new UserIdentificationGetRequest();
1528 request.userInfo.userId = userId;
1529 request.userInfo.flags = getHalUserInfoFlags(userId);
1530
1531 request.numberAssociationTypes = types.length;
1532 for (int i = 0; i < types.length; i++) {
1533 request.associationTypes.add(types[i]);
1534 }
1535
1536 UserIdentificationResponse halResponse = mHal.getUserAssociation(request);
1537 if (halResponse == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001538 Slog.w(TAG, "getUserIdentificationAssociation(): HAL returned null for "
felipeal5e3ede42020-04-23 18:04:07 -07001539 + Arrays.toString(types));
felipeal159a2a42020-05-08 10:32:11 -07001540 return UserIdentificationAssociationResponse.forFailure();
felipeal5e3ede42020-04-23 18:04:07 -07001541 }
1542
1543 int[] values = new int[halResponse.associations.size()];
1544 for (int i = 0; i < values.length; i++) {
1545 values[i] = halResponse.associations.get(i).value;
1546 }
1547 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_GET_USER_AUTH_RESP, values.length);
1548
felipeal159a2a42020-05-08 10:32:11 -07001549 return UserIdentificationAssociationResponse.forSuccess(values, halResponse.errorMessage);
1550 }
1551
1552 @Override
Mayank Garg3f566582020-10-02 22:10:16 -07001553 public void setUserIdentificationAssociation(int timeoutMs,
1554 @UserIdentificationAssociationType int[] types,
1555 @UserIdentificationAssociationSetValue int[] values,
felipeal159a2a42020-05-08 10:32:11 -07001556 AndroidFuture<UserIdentificationAssociationResponse> result) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001557 if (!isUserHalUserAssociationSupported()) {
1558 result.complete(
1559 UserIdentificationAssociationResponse.forFailure(VEHICLE_HAL_NOT_SUPPORTED));
1560 return;
1561 }
1562
felipeal159a2a42020-05-08 10:32:11 -07001563 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type");
1564 Preconditions.checkArgument(!ArrayUtils.isEmpty(values), "must have at least one value");
1565 if (types.length != values.length) {
1566 throw new IllegalArgumentException("types (" + Arrays.toString(types) + ") and values ("
1567 + Arrays.toString(values) + ") should have the same length");
1568 }
Felipe Leme17799202020-09-03 12:55:53 -07001569 checkManageOrCreateUsersPermission("setUserIdentificationAssociation");
felipeal159a2a42020-05-08 10:32:11 -07001570
1571 int uid = getCallingUid();
1572 int userId = UserHandle.getUserId(uid);
1573 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_REQ, uid, userId, types.length);
1574
1575 UserIdentificationSetRequest request = new UserIdentificationSetRequest();
1576 request.userInfo.userId = userId;
1577 request.userInfo.flags = getHalUserInfoFlags(userId);
1578
1579 request.numberAssociations = types.length;
1580 for (int i = 0; i < types.length; i++) {
1581 UserIdentificationSetAssociation association = new UserIdentificationSetAssociation();
1582 association.type = types[i];
1583 association.value = values[i];
1584 request.associations.add(association);
1585 }
1586
1587 mHal.setUserAssociation(timeoutMs, request, (status, resp) -> {
1588 if (status != HalCallback.STATUS_OK) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001589 Slog.w(TAG, "setUserIdentificationAssociation(): invalid callback status ("
felipeal159a2a42020-05-08 10:32:11 -07001590 + UserHalHelper.halCallbackStatusToString(status) + ") for response "
1591 + resp);
1592 if (resp == null || TextUtils.isEmpty(resp.errorMessage)) {
1593 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, 0);
1594 result.complete(UserIdentificationAssociationResponse.forFailure());
1595 return;
1596 }
1597 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, 0,
1598 resp.errorMessage);
1599 result.complete(
1600 UserIdentificationAssociationResponse.forFailure(resp.errorMessage));
1601 return;
1602 }
1603 int respSize = resp.associations.size();
1604 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, respSize,
1605 resp.errorMessage);
1606
1607 int[] responseTypes = new int[respSize];
1608 for (int i = 0; i < respSize; i++) {
1609 responseTypes[i] = resp.associations.get(i).value;
1610 }
1611 UserIdentificationAssociationResponse response = UserIdentificationAssociationResponse
1612 .forSuccess(responseTypes, resp.errorMessage);
Eric Jeongf75d4132020-12-21 13:48:23 -08001613 if (Log.isLoggable(TAG, Log.DEBUG)) {
1614 Slog.d(TAG, "setUserIdentificationAssociation(): resp= " + resp
felipeal159a2a42020-05-08 10:32:11 -07001615 + ", converted=" + response);
1616 }
1617 result.complete(response);
1618 });
felipeal5e3ede42020-04-23 18:04:07 -07001619 }
1620
1621 /**
1622 * Gets the User HAL flags for the given user.
1623 *
1624 * @throws IllegalArgumentException if the user does not exist.
1625 */
1626 private int getHalUserInfoFlags(@UserIdInt int userId) {
1627 UserInfo user = mUserManager.getUserInfo(userId);
1628 Preconditions.checkArgument(user != null, "no user for id %d", userId);
1629 return UserHalHelper.convertFlags(user);
1630 }
1631
Mayank Garg0e239142020-04-14 19:16:31 -07001632 private void sendResult(@NonNull IResultReceiver receiver, int resultCode,
1633 @Nullable Bundle resultData) {
1634 try {
1635 receiver.send(resultCode, resultData);
1636 } catch (RemoteException e) {
1637 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001638 Slog.w(TAG, "error while sending results", e);
Mayank Garg0e239142020-04-14 19:16:31 -07001639 }
1640 }
1641
felipealdfdf8512020-06-01 09:35:45 -07001642 private void sendUserSwitchResult(@NonNull AndroidFuture<UserSwitchResult> receiver,
Felipe Leme5d5ab142020-10-27 13:49:10 -07001643 @UserSwitchResult.Status int userSwitchStatus) {
1644 sendUserSwitchResult(receiver, HalCallback.STATUS_INVALID, userSwitchStatus,
1645 /* errorMessage= */ null);
felipeale5bf0322020-04-16 15:10:57 -07001646 }
1647
felipealdfdf8512020-06-01 09:35:45 -07001648 private void sendUserSwitchResult(@NonNull AndroidFuture<UserSwitchResult> receiver,
Felipe Leme5d5ab142020-10-27 13:49:10 -07001649 @HalCallback.HalCallbackStatus int halCallbackStatus,
1650 @UserSwitchResult.Status int userSwitchStatus, @Nullable String errorMessage) {
1651 if (errorMessage != null) {
1652 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_RESP, halCallbackStatus,
1653 userSwitchStatus, errorMessage);
1654 } else {
1655 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_RESP, halCallbackStatus,
1656 userSwitchStatus);
1657 }
1658 receiver.complete(new UserSwitchResult(userSwitchStatus, errorMessage));
felipeale5bf0322020-04-16 15:10:57 -07001659 }
1660
felipealdfdf8512020-06-01 09:35:45 -07001661 private void sendUserCreationResultFailure(@NonNull AndroidFuture<UserCreationResult> receiver,
1662 @UserCreationResult.Status int status) {
1663 sendUserCreationResult(receiver, status, /* user= */ null, /* errorMessage= */ null);
1664 }
1665
1666 private void sendUserCreationResult(@NonNull AndroidFuture<UserCreationResult> receiver,
1667 @UserCreationResult.Status int status, @NonNull UserInfo user,
1668 @Nullable String errorMessage) {
1669 if (TextUtils.isEmpty(errorMessage)) {
1670 errorMessage = null;
1671 }
1672 receiver.complete(new UserCreationResult(status, user, errorMessage));
1673 }
1674
Mayank Garg6307fe42020-04-15 23:09:03 -07001675 /**
1676 * Calls activity manager for user switch.
1677 *
1678 * <p><b>NOTE</b> This method is meant to be called just by UserHalService.
1679 *
1680 * @param requestId for the user switch request
1681 * @param targetUserId of the target user
1682 *
1683 * @hide
1684 */
1685 public void switchAndroidUserFromHal(int requestId, @UserIdInt int targetUserId) {
1686 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_FROM_HAL_REQ, requestId,
1687 targetUserId);
Eric Jeongf75d4132020-12-21 13:48:23 -08001688 Slog.i(TAG, "User hal requested a user switch. Target user id " + targetUserId);
Mayank Garg6307fe42020-04-15 23:09:03 -07001689
1690 try {
1691 boolean result = mAm.switchUser(targetUserId);
1692 if (result) {
1693 updateUserSwitchInProcess(requestId, targetUserId);
1694 } else {
1695 postSwitchHalResponse(requestId, targetUserId);
1696 }
1697 } catch (RemoteException e) {
1698 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001699 Slog.w(TAG, "error while switching user " + targetUserId, e);
Mayank Garg6307fe42020-04-15 23:09:03 -07001700 }
1701 }
1702
1703 private void updateUserSwitchInProcess(int requestId, @UserIdInt int targetUserId) {
1704 synchronized (mLockUser) {
1705 if (mUserIdForUserSwitchInProcess != UserHandle.USER_NULL) {
1706 // Some other user switch is in process.
Eric Jeongf75d4132020-12-21 13:48:23 -08001707 if (Log.isLoggable(TAG, Log.DEBUG)) {
1708 Slog.d(TAG, "User switch for user: " + mUserIdForUserSwitchInProcess
Mayank Garg6307fe42020-04-15 23:09:03 -07001709 + " is in process. Abandoning it as a new user switch is requested"
1710 + " for the target user: " + targetUserId);
1711 }
1712 }
1713 mUserIdForUserSwitchInProcess = targetUserId;
1714 mRequestIdForUserSwitchInProcess = requestId;
1715 }
1716 }
Mayank Garg9ed099e2020-06-04 16:05:20 -07001717
Mayank Garg7a114c82020-04-08 21:25:06 -07001718 private void postSwitchHalResponse(int requestId, @UserIdInt int targetUserId) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001719 if (!isUserHalSupported()) return;
1720
felipealdfdf8512020-06-01 09:35:45 -07001721 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
Mayank Gargeb37d092020-06-02 14:37:57 -07001722 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_POST_SWITCH_USER_REQ, requestId,
1723 targetUserId, usersInfo.currentUser.userId);
1724 SwitchUserRequest request = createUserSwitchRequest(targetUserId, usersInfo);
1725 request.requestId = requestId;
1726 mHal.postSwitchResponse(request);
1727 }
1728
1729 private SwitchUserRequest createUserSwitchRequest(@UserIdInt int targetUserId,
1730 @NonNull UsersInfo usersInfo) {
1731 UserInfo targetUser = mUserManager.getUserInfo(targetUserId);
Mayank Garg7a114c82020-04-08 21:25:06 -07001732 android.hardware.automotive.vehicle.V2_0.UserInfo halTargetUser =
1733 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1734 halTargetUser.userId = targetUser.id;
1735 halTargetUser.flags = UserHalHelper.convertFlags(targetUser);
Mayank Gargeb37d092020-06-02 14:37:57 -07001736 SwitchUserRequest request = new SwitchUserRequest();
1737 request.targetUser = halTargetUser;
1738 request.usersInfo = usersInfo;
1739 return request;
Mayank Garg7a114c82020-04-08 21:25:06 -07001740 }
1741
Mayank Garg59f22192020-03-27 00:51:45 -07001742 /**
Felipe Lemee3cab982020-03-12 11:39:29 -07001743 * Checks if the User HAL is supported.
1744 */
1745 public boolean isUserHalSupported() {
1746 return mHal.isSupported();
1747 }
1748
Mayank Garg587f1942020-05-06 01:41:34 -07001749 /**
Mayank Garg9ed099e2020-06-04 16:05:20 -07001750 * Checks if the User HAL user association is supported.
1751 */
1752 @Override
1753 public boolean isUserHalUserAssociationSupported() {
1754 return mHal.isUserAssociationSupported();
1755 }
1756
1757 /**
Mayank Garg587f1942020-05-06 01:41:34 -07001758 * Sets a callback which is invoked before user switch.
1759 *
1760 * <p>
1761 * This method should only be called by the Car System UI. The purpose of this call is to notify
1762 * Car System UI to show the user switch UI before the user switch.
1763 */
1764 @Override
1765 public void setUserSwitchUiCallback(@NonNull IResultReceiver receiver) {
Yan Zhu67a383e2020-05-11 20:46:24 -07001766 checkManageUsersPermission("setUserSwitchUiCallback");
Mayank Garga480dd92020-05-14 03:14:57 -07001767
1768 // Confirm that caller is system UI.
1769 String systemUiPackageName = getSystemUiPackageName();
1770 if (systemUiPackageName == null) {
1771 throw new IllegalStateException("System UI package not found.");
1772 }
1773
1774 try {
1775 int systemUiUid = mContext
1776 .createContextAsUser(UserHandle.SYSTEM, /* flags= */ 0).getPackageManager()
1777 .getPackageUid(systemUiPackageName, PackageManager.MATCH_SYSTEM_ONLY);
1778 int callerUid = Binder.getCallingUid();
1779 if (systemUiUid != callerUid) {
1780 throw new SecurityException("Invalid caller. Only" + systemUiPackageName
1781 + " is allowed to make this call");
1782 }
1783 } catch (NameNotFoundException e) {
1784 throw new IllegalStateException("Package " + systemUiPackageName + " not found.");
1785 }
1786
Mayank Garg587f1942020-05-06 01:41:34 -07001787 mUserSwitchUiReceiver = receiver;
1788 }
1789
Mayank Garga480dd92020-05-14 03:14:57 -07001790 // TODO(157082995): This information can be taken from
1791 // PackageManageInternalImpl.getSystemUiServiceComponent
1792 @Nullable
1793 private String getSystemUiPackageName() {
1794 try {
1795 ComponentName componentName = ComponentName.unflattenFromString(mContext.getResources()
1796 .getString(com.android.internal.R.string.config_systemUIServiceComponent));
1797 return componentName.getPackageName();
1798 } catch (RuntimeException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001799 Slog.w(TAG, "error while getting system UI package name.", e);
Mayank Garga480dd92020-05-14 03:14:57 -07001800 return null;
1801 }
1802 }
1803
Keun young Park13a7a822019-04-04 15:53:08 -07001804 private void updateDefaultUserRestriction() {
1805 // We want to set restrictions on system and guest users only once. These are persisted
1806 // onto disk, so it's sufficient to do it once + we minimize the number of disk writes.
1807 if (Settings.Global.getInt(mContext.getContentResolver(),
Eric Jeong1545f3b2019-09-16 13:56:52 -07001808 CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, /* default= */ 0) != 0) {
1809 return;
Keun young Park13a7a822019-04-04 15:53:08 -07001810 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07001811 // Only apply the system user restrictions if the system user is headless.
1812 if (UserManager.isHeadlessSystemUserMode()) {
1813 setSystemUserRestrictions();
1814 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07001815 Settings.Global.putInt(mContext.getContentResolver(),
1816 CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, 1);
Keun young Park13a7a822019-04-04 15:53:08 -07001817 }
1818
Eric Jeong1545f3b2019-09-16 13:56:52 -07001819 private boolean isPersistentUser(@UserIdInt int userId) {
Anthony Hugh9932a252019-06-12 16:19:56 -07001820 return !mUserManager.getUserInfo(userId).isEphemeral();
1821 }
1822
Antonio Kantekc8114752020-03-05 21:37:39 -08001823 /**
Antonio Kantekc8114752020-03-05 21:37:39 -08001824 * Adds a new {@link UserLifecycleListener} to listen to user activity events.
1825 */
1826 public void addUserLifecycleListener(@NonNull UserLifecycleListener listener) {
1827 Objects.requireNonNull(listener, "listener cannot be null");
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001828 mHandler.post(() -> mUserLifecycleListeners.add(listener));
Antonio Kantekc8114752020-03-05 21:37:39 -08001829 }
1830
1831 /**
1832 * Removes previously added {@link UserLifecycleListener}.
1833 */
1834 public void removeUserLifecycleListener(@NonNull UserLifecycleListener listener) {
1835 Objects.requireNonNull(listener, "listener cannot be null");
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001836 mHandler.post(() -> mUserLifecycleListeners.remove(listener));
Antonio Kantekc8114752020-03-05 21:37:39 -08001837 }
1838
Eric Jeongc91f9452019-08-30 15:04:21 -07001839 /** Adds callback to listen to passenger activity events. */
1840 public void addPassengerCallback(@NonNull PassengerCallback callback) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00001841 Objects.requireNonNull(callback, "callback cannot be null");
Eric Jeongc91f9452019-08-30 15:04:21 -07001842 mPassengerCallbacks.add(callback);
1843 }
1844
1845 /** Removes previously added callback to listen passenger events. */
1846 public void removePassengerCallback(@NonNull PassengerCallback callback) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00001847 Objects.requireNonNull(callback, "callback cannot be null");
Eric Jeongc91f9452019-08-30 15:04:21 -07001848 mPassengerCallbacks.remove(callback);
1849 }
1850
1851 /** Sets the implementation of ZoneUserBindingHelper. */
1852 public void setZoneUserBindingHelper(@NonNull ZoneUserBindingHelper helper) {
1853 synchronized (mLockHelper) {
1854 mZoneUserBindingHelper = helper;
1855 }
1856 }
1857
felipeal98900c82020-04-09 09:05:02 -07001858 private void onUserUnlocked(@UserIdInt int userId) {
Keun-young Parkd462a912019-02-11 08:53:42 -08001859 ArrayList<Runnable> tasks = null;
Eric Jeongc91f9452019-08-30 15:04:21 -07001860 synchronized (mLockUser) {
Mayank Garg7a114c82020-04-08 21:25:06 -07001861 sendPostSwitchToHalLocked(userId);
Eric Jeong1545f3b2019-09-16 13:56:52 -07001862 if (userId == UserHandle.USER_SYSTEM) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001863 if (!mUser0Unlocked) { // user 0, unlocked, do this only once
1864 updateDefaultUserRestriction();
1865 tasks = new ArrayList<>(mUser0UnlockTasks);
1866 mUser0UnlockTasks.clear();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001867 mUser0Unlocked = true;
Keun young Parkf3523cd2019-04-08 10:09:17 -07001868 }
1869 } else { // none user0
Eric Jeong1545f3b2019-09-16 13:56:52 -07001870 Integer user = userId;
1871 if (isPersistentUser(userId)) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001872 // current foreground user should stay in top priority.
Anthony Hughfbb67762019-10-15 12:54:54 -07001873 if (userId == ActivityManager.getCurrentUser()) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001874 mBackgroundUsersToRestart.remove(user);
1875 mBackgroundUsersToRestart.add(0, user);
1876 }
1877 // -1 for user 0
1878 if (mBackgroundUsersToRestart.size() > (mMaxRunningUsers - 1)) {
Eric Jeong1545f3b2019-09-16 13:56:52 -07001879 int userToDrop = mBackgroundUsersToRestart.get(
Keun young Parkf3523cd2019-04-08 10:09:17 -07001880 mBackgroundUsersToRestart.size() - 1);
Eric Jeongf75d4132020-12-21 13:48:23 -08001881 Slog.i(TAG, "New user unlocked:" + userId
Keun young Parkf3523cd2019-04-08 10:09:17 -07001882 + ", dropping least recently user from restart list:" + userToDrop);
1883 // Drop the least recently used user.
1884 mBackgroundUsersToRestart.remove(mBackgroundUsersToRestart.size() - 1);
1885 }
1886 }
Keun-young Parkd462a912019-02-11 08:53:42 -08001887 }
1888 }
1889 if (tasks != null && tasks.size() > 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -08001890 Slog.d(TAG, "User0 unlocked, run queued tasks:" + tasks.size());
Keun-young Parkd462a912019-02-11 08:53:42 -08001891 for (Runnable r : tasks) {
1892 r.run();
1893 }
1894 }
1895 }
1896
1897 /**
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001898 * Starts the specified user in the background.
1899 *
1900 * @param userId user to start in background
1901 * @param receiver to post results
1902 */
1903 public void startUserInBackground(@UserIdInt int userId,
1904 @NonNull AndroidFuture<UserStartResult> receiver) {
bkchoi5ab7aa32021-04-27 11:50:53 -07001905 checkManageOrCreateUsersPermission("startUserInBackground");
1906 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_START_USER_IN_BACKGROUND_REQ, userId);
1907
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001908 mHandler.post(() -> handleStartUserInBackground(userId, receiver));
1909 }
1910
1911 private void handleStartUserInBackground(@UserIdInt int userId,
1912 @NonNull AndroidFuture<UserStartResult> receiver) {
1913 // If the requested user is the current user, do nothing and return success.
1914 if (ActivityManager.getCurrentUser() == userId) {
bkchoi5ab7aa32021-04-27 11:50:53 -07001915 sendUserStartResult(
1916 userId, UserStartResult.STATUS_SUCCESSFUL_USER_IS_CURRENT_USER, receiver);
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001917 return;
1918 }
1919 // If requested user does not exist, return error.
1920 if (mUserManager.getUserInfo(userId) == null) {
1921 Slogf.w(TAG, "User %d does not exist", userId);
bkchoi5ab7aa32021-04-27 11:50:53 -07001922 sendUserStartResult(userId, UserStartResult.STATUS_USER_DOES_NOT_EXIST, receiver);
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001923 return;
1924 }
1925
1926 try {
1927 if (!mAm.startUserInBackground(userId)) {
1928 Slogf.w(TAG, "Failed to start user %d in background", userId);
bkchoi5ab7aa32021-04-27 11:50:53 -07001929 sendUserStartResult(userId, UserStartResult.STATUS_ANDROID_FAILURE, receiver);
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001930 return;
1931 }
1932 } catch (RemoteException e) {
1933 Slogf.w(TAG, e, "Failed to start user %d in background", userId);
1934 }
1935
1936 // TODO(b/181331178): We are not updating mBackgroundUsersToRestart or
1937 // mBackgroundUsersRestartedHere, which were only used for the garage mode. Consider
1938 // renaming them to make it more clear.
bkchoi5ab7aa32021-04-27 11:50:53 -07001939 sendUserStartResult(userId, UserStartResult.STATUS_SUCCESSFUL, receiver);
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001940 }
1941
bkchoi5ab7aa32021-04-27 11:50:53 -07001942 private void sendUserStartResult(@UserIdInt int userId, @UserStartResult.Status int result,
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001943 @NonNull AndroidFuture<UserStartResult> receiver) {
bkchoi5ab7aa32021-04-27 11:50:53 -07001944 EventLog.writeEvent(
1945 EventLogTags.CAR_USER_SVC_START_USER_IN_BACKGROUND_RESP, userId, result);
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07001946 receiver.complete(new UserStartResult(result));
1947 }
1948
1949 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -07001950 * Starts all background users that were active in system.
1951 *
Keun young Parkfb656372019-03-12 18:37:55 -07001952 * @return list of background users started successfully.
1953 */
Eric Jeong1545f3b2019-09-16 13:56:52 -07001954 @NonNull
Mayank Garg784a0862021-05-26 00:20:50 -07001955 public ArrayList<Integer> startAllBackgroundUsersInGarageMode() {
1956 synchronized (mLockUser) {
1957 if (!mStartBackgroundUsersOnGarageMode) {
1958 Slogf.i(TAG, "Background users are not started as mStartBackgroundUsersOnGarageMode"
1959 + " is false.");
1960 return new ArrayList<>();
1961 }
1962 }
1963
Keun young Parkfb656372019-03-12 18:37:55 -07001964 ArrayList<Integer> users;
Eric Jeongc91f9452019-08-30 15:04:21 -07001965 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001966 users = new ArrayList<>(mBackgroundUsersToRestart);
1967 mBackgroundUsersRestartedHere.clear();
1968 mBackgroundUsersRestartedHere.addAll(mBackgroundUsersToRestart);
Keun young Parkfb656372019-03-12 18:37:55 -07001969 }
1970 ArrayList<Integer> startedUsers = new ArrayList<>();
1971 for (Integer user : users) {
Anthony Hughfbb67762019-10-15 12:54:54 -07001972 if (user == ActivityManager.getCurrentUser()) {
Keun young Parkfb656372019-03-12 18:37:55 -07001973 continue;
1974 }
1975 try {
1976 if (mAm.startUserInBackground(user)) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001977 if (mUserManager.isUserUnlockingOrUnlocked(user)) {
1978 // already unlocked / unlocking. No need to unlock.
Keun young Parkfb656372019-03-12 18:37:55 -07001979 startedUsers.add(user);
Keun young Parkf3523cd2019-04-08 10:09:17 -07001980 } else if (mAm.unlockUser(user, null, null, null)) {
1981 startedUsers.add(user);
1982 } else { // started but cannot unlock
Eric Jeongf75d4132020-12-21 13:48:23 -08001983 Slog.w(TAG, "Background user started but cannot be unlocked:" + user);
Keun young Parkf3523cd2019-04-08 10:09:17 -07001984 if (mUserManager.isUserRunning(user)) {
1985 // add to started list so that it can be stopped later.
1986 startedUsers.add(user);
1987 }
Keun young Parkfb656372019-03-12 18:37:55 -07001988 }
1989 }
1990 } catch (RemoteException e) {
1991 // ignore
Eric Jeongf75d4132020-12-21 13:48:23 -08001992 Slog.w(TAG, "error while starting user in background", e);
Keun young Parkfb656372019-03-12 18:37:55 -07001993 }
1994 }
Keun young Parkf3523cd2019-04-08 10:09:17 -07001995 // Keep only users that were re-started in mBackgroundUsersRestartedHere
Eric Jeongc91f9452019-08-30 15:04:21 -07001996 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001997 ArrayList<Integer> usersToRemove = new ArrayList<>();
1998 for (Integer user : mBackgroundUsersToRestart) {
1999 if (!startedUsers.contains(user)) {
2000 usersToRemove.add(user);
2001 }
2002 }
2003 mBackgroundUsersRestartedHere.removeAll(usersToRemove);
2004 }
Keun young Parkfb656372019-03-12 18:37:55 -07002005 return startedUsers;
2006 }
2007
2008 /**
bkchoid77d0bc2021-04-22 13:43:03 -07002009 * Stops the specified background user.
2010 *
2011 * @param userId user to stop
2012 * @param receiver to post results
2013 */
2014 public void stopUser(@UserIdInt int userId, @NonNull AndroidFuture<UserStopResult> receiver) {
bkchoia8c7fb92021-04-28 10:58:57 -07002015 checkManageOrCreateUsersPermission("stopUser");
2016 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_STOP_USER_REQ, userId);
2017
bkchoid77d0bc2021-04-22 13:43:03 -07002018 mHandler.post(() -> handleStopUser(userId, receiver));
2019 }
2020
2021 private void handleStopUser(
2022 @UserIdInt int userId, @NonNull AndroidFuture<UserStopResult> receiver) {
2023 @UserStopResult.Status int userStopStatus = stopBackgroundUserInternal(userId);
bkchoia8c7fb92021-04-28 10:58:57 -07002024 sendUserStopResult(userId, userStopStatus, receiver);
bkchoid77d0bc2021-04-22 13:43:03 -07002025 }
2026
bkchoia8c7fb92021-04-28 10:58:57 -07002027 private void sendUserStopResult(@UserIdInt int userId, @UserStopResult.Status int result,
bkchoid77d0bc2021-04-22 13:43:03 -07002028 @NonNull AndroidFuture<UserStopResult> receiver) {
bkchoia8c7fb92021-04-28 10:58:57 -07002029 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_STOP_USER_RESP, userId, result);
bkchoid77d0bc2021-04-22 13:43:03 -07002030 receiver.complete(new UserStopResult(result));
2031 }
2032
2033 private @UserStopResult.Status int stopBackgroundUserInternal(@UserIdInt int userId) {
2034 try {
2035 int r = mAm.stopUserWithDelayedLocking(userId, true, null);
2036 switch(r) {
2037 case ActivityManager.USER_OP_SUCCESS:
2038 return UserStopResult.STATUS_SUCCESSFUL;
2039 case ActivityManager.USER_OP_ERROR_IS_SYSTEM:
2040 Slogf.w(TAG, "Cannot stop the system user: %d", userId);
2041 return UserStopResult.STATUS_FAILURE_SYSTEM_USER;
2042 case ActivityManager.USER_OP_IS_CURRENT:
2043 Slogf.w(TAG, "Cannot stop the current user: %d", userId);
2044 return UserStopResult.STATUS_FAILURE_CURRENT_USER;
2045 case ActivityManager.USER_OP_UNKNOWN_USER:
2046 Slogf.w(TAG, "Cannot stop the user that does not exist: %d", userId);
2047 return UserStopResult.STATUS_USER_DOES_NOT_EXIST;
2048 default:
2049 Slogf.w(TAG, "stopUser failed, user: %d, err: %d", userId, r);
2050 }
2051 } catch (RemoteException e) {
2052 // ignore the exception
2053 Slogf.w(TAG, e, "error while stopping user: %d", userId);
2054 }
2055 return UserStopResult.STATUS_ANDROID_FAILURE;
2056 }
2057
2058 /**
Mayank Garg784a0862021-05-26 00:20:50 -07002059 * Sets boolean to control background user operations during garage mode.
2060 */
2061 public void setStartBackgroundUsersOnGarageMode(boolean enable) {
2062 synchronized (mLockUser) {
2063 mStartBackgroundUsersOnGarageMode = enable;
2064 }
2065 }
2066
2067 /**
Bo-Kyung (BK) Choia6503f42021-04-19 14:34:00 -07002068 * Stops a background user.
Eric Jeong1545f3b2019-09-16 13:56:52 -07002069 *
2070 * @return whether stopping succeeds.
Keun young Parkfb656372019-03-12 18:37:55 -07002071 */
Mayank Garg784a0862021-05-26 00:20:50 -07002072 public boolean stopBackgroundUserInGagageMode(@UserIdInt int userId) {
2073 synchronized (mLockUser) {
2074 if (!mStartBackgroundUsersOnGarageMode) {
2075 Slogf.i(TAG, "Background users are not stopped as mStartBackgroundUsersOnGarageMode"
2076 + " is false.");
2077 return false;
2078 }
2079 }
2080
bkchoid77d0bc2021-04-22 13:43:03 -07002081 @UserStopResult.Status int userStopStatus = stopBackgroundUserInternal(userId);
2082 if (UserStopResult.isSuccess(userStopStatus)) {
2083 // Remove the stopped user from the mBackgroundUserRestartedHere list.
2084 synchronized (mLockUser) {
2085 mBackgroundUsersRestartedHere.remove(Integer.valueOf(userId));
Keun young Parkfb656372019-03-12 18:37:55 -07002086 }
bkchoid77d0bc2021-04-22 13:43:03 -07002087 return true;
Keun young Parkfb656372019-03-12 18:37:55 -07002088 }
bkchoid77d0bc2021-04-22 13:43:03 -07002089 return false;
Keun young Parkfb656372019-03-12 18:37:55 -07002090 }
2091
2092 /**
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002093 * Notifies all registered {@link UserLifecycleListener} with the event passed as argument.
Pavel Maltsev17e81832019-04-04 14:38:41 -07002094 */
Mayank Gargccad8062020-08-30 15:05:10 -07002095 public void onUserLifecycleEvent(@UserLifecycleEventType int eventType,
felipeale8c5dce2020-04-15 11:27:06 -07002096 @UserIdInt int fromUserId, @UserIdInt int toUserId) {
2097 int userId = toUserId;
felipeal98900c82020-04-09 09:05:02 -07002098
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002099 // Handle special cases first...
felipeal98900c82020-04-09 09:05:02 -07002100 if (eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING) {
Mayank Garge5de0f92020-04-23 21:38:38 -07002101 onUserSwitching(fromUserId, toUserId);
felipeal98900c82020-04-09 09:05:02 -07002102 } else if (eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_UNLOCKED) {
2103 onUserUnlocked(userId);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002104 }
2105
felipeale8c5dce2020-04-15 11:27:06 -07002106 // ...then notify listeners.
Yan Zhue7921522020-04-16 15:59:25 -07002107 UserLifecycleEvent event = new UserLifecycleEvent(eventType, fromUserId, userId);
felipeale8c5dce2020-04-15 11:27:06 -07002108
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002109 mHandler.post(() -> {
2110 handleNotifyServiceUserLifecycleListeners(event);
2111 handleNotifyAppUserLifecycleListeners(event);
2112 });
felipeale8c5dce2020-04-15 11:27:06 -07002113 }
2114
Mayank Garg7a114c82020-04-08 21:25:06 -07002115 private void sendPostSwitchToHalLocked(@UserIdInt int userId) {
felipealf7368962020-04-16 12:55:19 -07002116 if (mUserIdForUserSwitchInProcess == UserHandle.USER_NULL
Mayank Garg1f20dcd2020-04-22 17:46:01 -07002117 || mUserIdForUserSwitchInProcess != userId
2118 || mRequestIdForUserSwitchInProcess == 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002119 if (Log.isLoggable(TAG, Log.DEBUG)) {
2120 Slog.d(TAG, "No user switch request Id. No android post switch sent.");
Mayank Garg7a114c82020-04-08 21:25:06 -07002121 }
2122 return;
2123 }
felipealf7368962020-04-16 12:55:19 -07002124 postSwitchHalResponse(mRequestIdForUserSwitchInProcess, mUserIdForUserSwitchInProcess);
2125 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
Mayank Garg1f20dcd2020-04-22 17:46:01 -07002126 mRequestIdForUserSwitchInProcess = 0;
Mayank Garg7a114c82020-04-08 21:25:06 -07002127 }
2128
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002129 private void handleNotifyAppUserLifecycleListeners(UserLifecycleEvent event) {
2130 int listenersSize = mAppLifecycleListeners.size();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002131 if (listenersSize == 0) {
Felipe Lemefaf67042021-07-08 11:24:00 -07002132 Slogf.d(TAG, "No app listener to be notified of %s", event);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002133 return;
2134 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002135 // Must use a different TimingsTraceLog because it's another thread
Felipe Lemefaf67042021-07-08 11:24:00 -07002136 Slogf.d(TAG, "Notifying %d app listeners of %s", listenersSize, event);
felipeal2a84d512020-04-06 18:52:15 -07002137 int userId = event.getUserId();
Eric Jeongf75d4132020-12-21 13:48:23 -08002138 TimingsTraceLog t = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
felipealde1e16d2020-06-03 13:20:48 -07002139 int eventType = event.getEventType();
2140 t.traceBegin("notify-app-listeners-user-" + userId + "-event-" + eventType);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002141 for (int i = 0; i < listenersSize; i++) {
Felipe Lemefaf67042021-07-08 11:24:00 -07002142 AppLifecycleListener listener = mAppLifecycleListeners.valueAt(i);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002143 Bundle data = new Bundle();
felipealde1e16d2020-06-03 13:20:48 -07002144 data.putInt(CarUserManager.BUNDLE_PARAM_ACTION, eventType);
Yan Zhue7921522020-04-16 15:59:25 -07002145
felipealde1e16d2020-06-03 13:20:48 -07002146 int fromUserId = event.getPreviousUserId();
2147 if (fromUserId != UserHandle.USER_NULL) {
2148 data.putInt(CarUserManager.BUNDLE_PARAM_PREVIOUS_USER_ID, fromUserId);
Yan Zhue7921522020-04-16 15:59:25 -07002149 }
Felipe Lemefaf67042021-07-08 11:24:00 -07002150 Slogf.d(TAG, "Notifying listener %s", listener);
felipealde1e16d2020-06-03 13:20:48 -07002151 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_NOTIFY_APP_LIFECYCLE_LISTENER,
Felipe Lemefaf67042021-07-08 11:24:00 -07002152 listener.uid, listener.packageName, eventType, fromUserId, userId);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002153 try {
Felipe Lemefaf67042021-07-08 11:24:00 -07002154 t.traceBegin("notify-app-listener-" + listener.toShortString());
2155 listener.receiver.send(userId, data);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002156 } catch (RemoteException e) {
Felipe Lemefaf67042021-07-08 11:24:00 -07002157 Slogf.e(TAG, e, "Error calling lifecycle listener %s", listener);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002158 } finally {
2159 t.traceEnd();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002160 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002161 }
2162 t.traceEnd(); // notify-app-listeners-user-USERID-event-EVENT_TYPE
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002163 }
2164
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002165 private void handleNotifyServiceUserLifecycleListeners(UserLifecycleEvent event) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002166 TimingsTraceLog t = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002167 if (mUserLifecycleListeners.isEmpty()) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002168 Slog.w(TAG, "Not notifying internal UserLifecycleListeners");
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002169 return;
Eric Jeongf75d4132020-12-21 13:48:23 -08002170 } else if (Log.isLoggable(TAG, Log.DEBUG)) {
2171 Slog.d(TAG, "Notifying " + mUserLifecycleListeners.size()
2172 + " service listeners of " + event);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002173 }
felipeal2a84d512020-04-06 18:52:15 -07002174
felipealde1e16d2020-06-03 13:20:48 -07002175 int userId = event.getUserId();
2176 int eventType = event.getEventType();
2177 t.traceBegin("notify-listeners-user-" + userId + "-event-" + eventType);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002178 for (UserLifecycleListener listener : mUserLifecycleListeners) {
felipeal2a84d512020-04-06 18:52:15 -07002179 String listenerName = FunctionalUtils.getLambdaName(listener);
felipealde1e16d2020-06-03 13:20:48 -07002180 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_NOTIFY_INTERNAL_LIFECYCLE_LISTENER,
2181 listenerName, eventType, event.getPreviousUserId(), userId);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002182 try {
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002183 t.traceBegin("notify-listener-" + listenerName);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002184 listener.onEvent(event);
2185 } catch (RuntimeException e) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002186 Slog.e(TAG,
felipeal2a84d512020-04-06 18:52:15 -07002187 "Exception raised when invoking onEvent for " + listenerName, e);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002188 } finally {
2189 t.traceEnd();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002190 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002191 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07002192 t.traceEnd(); // notify-listeners-user-USERID-event-EVENT_TYPE
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002193 }
2194
Mayank Garge5de0f92020-04-23 21:38:38 -07002195 private void onUserSwitching(@UserIdInt int fromUserId, @UserIdInt int toUserId) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002196 Slog.i(TAG, "onUserSwitching() callback for user " + toUserId);
2197 TimingsTraceLog t = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
Mayank Garge5de0f92020-04-23 21:38:38 -07002198 t.traceBegin("onUserSwitching-" + toUserId);
Felipe Leme5528ff72020-02-10 19:05:14 -08002199
Mayank Garge5de0f92020-04-23 21:38:38 -07002200 // Switch HAL users if user switch is not requested by CarUserService
2201 notifyHalLegacySwitch(fromUserId, toUserId);
2202
Mayank Garge90a4082020-09-30 12:57:34 -07002203 mInitialUserSetter.setLastActiveUser(toUserId);
felipealbf327652020-06-03 11:33:29 -07002204
Eric Jeongc91f9452019-08-30 15:04:21 -07002205 if (mLastPassengerId != UserHandle.USER_NULL) {
2206 stopPassengerInternal(mLastPassengerId, false);
2207 }
2208 if (mEnablePassengerSupport && isPassengerDisplayAvailable()) {
2209 setupPassengerUser();
Mayank Garge5de0f92020-04-23 21:38:38 -07002210 startFirstPassenger(toUserId);
Eric Jeongc91f9452019-08-30 15:04:21 -07002211 }
felipeal98900c82020-04-09 09:05:02 -07002212 t.traceEnd();
Pavel Maltsev17e81832019-04-04 14:38:41 -07002213 }
2214
Mayank Garge5de0f92020-04-23 21:38:38 -07002215 private void notifyHalLegacySwitch(@UserIdInt int fromUserId, @UserIdInt int toUserId) {
2216 synchronized (mLockUser) {
felipeal7d12ee22020-06-05 09:30:19 -07002217 if (mUserIdForUserSwitchInProcess != UserHandle.USER_NULL) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002218 if (Log.isLoggable(TAG, Log.DEBUG)) {
2219 Slog.d(TAG, "notifyHalLegacySwitch(" + fromUserId + ", " + toUserId
felipeal7d12ee22020-06-05 09:30:19 -07002220 + "): not needed, normal switch for " + mUserIdForUserSwitchInProcess);
2221 }
2222 return;
2223 }
Mayank Garge5de0f92020-04-23 21:38:38 -07002224 }
2225
Mayank Garg9ed099e2020-06-04 16:05:20 -07002226 if (!isUserHalSupported()) return;
2227
Mayank Garge5de0f92020-04-23 21:38:38 -07002228 // switch HAL user
felipeal7d12ee22020-06-05 09:30:19 -07002229 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager, fromUserId);
Mayank Gargeb37d092020-06-02 14:37:57 -07002230 SwitchUserRequest request = createUserSwitchRequest(toUserId, usersInfo);
2231 mHal.legacyUserSwitch(request);
Mayank Garge5de0f92020-04-23 21:38:38 -07002232 }
2233
Pavel Maltsev17e81832019-04-04 14:38:41 -07002234 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -07002235 * 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 -08002236 * run inside this call.
Eric Jeong1545f3b2019-09-16 13:56:52 -07002237 *
Keun-young Parkd462a912019-02-11 08:53:42 -08002238 * @param r Runnable to run.
2239 */
Eric Jeong1545f3b2019-09-16 13:56:52 -07002240 public void runOnUser0Unlock(@NonNull Runnable r) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00002241 Objects.requireNonNull(r, "runnable cannot be null");
Keun-young Parkd462a912019-02-11 08:53:42 -08002242 boolean runNow = false;
Eric Jeongc91f9452019-08-30 15:04:21 -07002243 synchronized (mLockUser) {
Keun-young Parkd462a912019-02-11 08:53:42 -08002244 if (mUser0Unlocked) {
2245 runNow = true;
2246 } else {
2247 mUser0UnlockTasks.add(r);
2248 }
2249 }
2250 if (runNow) {
2251 r.run();
2252 }
2253 }
2254
Keun young Parkf3523cd2019-04-08 10:09:17 -07002255 @VisibleForTesting
Eric Jeong1545f3b2019-09-16 13:56:52 -07002256 @NonNull
2257 ArrayList<Integer> getBackgroundUsersToRestart() {
2258 ArrayList<Integer> backgroundUsersToRestart = null;
Eric Jeongc91f9452019-08-30 15:04:21 -07002259 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07002260 backgroundUsersToRestart = new ArrayList<>(mBackgroundUsersToRestart);
2261 }
2262 return backgroundUsersToRestart;
2263 }
2264
Ying Zheng1ab32b62018-06-26 12:47:26 -07002265 private void setSystemUserRestrictions() {
Ying Zheng1ab32b62018-06-26 12:47:26 -07002266 // Disable Location service for system user.
2267 LocationManager locationManager =
2268 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
Anthony Hugh04ee04f2019-12-17 16:11:33 -08002269 locationManager.setLocationEnabledForUser(
2270 /* enabled= */ false, UserHandle.of(UserHandle.USER_SYSTEM));
Ying Zheng1ab32b62018-06-26 12:47:26 -07002271 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07002272
2273 /**
Anthony Hugh6fed1e92019-10-22 16:22:03 -07002274 * Assigns a default icon to a user according to the user's id.
2275 *
2276 * @param userInfo User whose avatar is set to default icon.
Anthony Hugh6fed1e92019-10-22 16:22:03 -07002277 */
Eric Jeongb2dc6ff2020-06-05 17:00:26 -07002278 private void assignDefaultIcon(UserInfo userInfo) {
Anthony Hugh6fed1e92019-10-22 16:22:03 -07002279 int idForIcon = userInfo.isGuest() ? UserHandle.USER_NULL : userInfo.id;
2280 Bitmap bitmap = UserIcons.convertToBitmap(
2281 UserIcons.getDefaultUserIcon(mContext.getResources(), idForIcon, false));
2282 mUserManager.setUserIcon(userInfo.id, bitmap);
Anthony Hugh6fed1e92019-10-22 16:22:03 -07002283 }
2284
Eric Jeong1545f3b2019-09-16 13:56:52 -07002285 private interface UserFilter {
2286 boolean isEligibleUser(UserInfo user);
2287 }
2288
2289 /** Returns all users who are matched by the given filter. */
2290 private List<UserInfo> getUsers(UserFilter filter) {
Colin Cross0df71ea2020-08-27 04:12:26 +00002291 List<UserInfo> users = mUserManager.getAliveUsers();
Eric Jeong1545f3b2019-09-16 13:56:52 -07002292
2293 for (Iterator<UserInfo> iterator = users.iterator(); iterator.hasNext(); ) {
2294 UserInfo user = iterator.next();
2295 if (!filter.isEligibleUser(user)) {
2296 iterator.remove();
2297 }
2298 }
2299 return users;
2300 }
2301
felipeal2d0483c2019-11-02 14:07:22 -07002302 private static void checkManageUsersOrDumpPermission(String message) {
Felipe Leme55236722020-10-16 16:54:32 -07002303 checkHasAtLeastOnePermissionGranted(message,
felipeal2d0483c2019-11-02 14:07:22 -07002304 android.Manifest.permission.MANAGE_USERS,
2305 android.Manifest.permission.DUMP);
2306 }
2307
Felipe Leme5528ff72020-02-10 19:05:14 -08002308 private void checkInteractAcrossUsersPermission(String message) {
Felipe Leme55236722020-10-16 16:54:32 -07002309 checkHasAtLeastOnePermissionGranted(message,
2310 android.Manifest.permission.INTERACT_ACROSS_USERS,
Felipe Leme5528ff72020-02-10 19:05:14 -08002311 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
2312 }
2313
Eric Jeongc91f9452019-08-30 15:04:21 -07002314 private int getNumberOfManagedProfiles(@UserIdInt int userId) {
Colin Cross0df71ea2020-08-27 04:12:26 +00002315 List<UserInfo> users = mUserManager.getAliveUsers();
Eric Jeongc91f9452019-08-30 15:04:21 -07002316 // Count all users that are managed profiles of the given user.
2317 int managedProfilesCount = 0;
2318 for (UserInfo user : users) {
2319 if (user.isManagedProfile() && user.profileGroupId == userId) {
2320 managedProfilesCount++;
2321 }
2322 }
2323 return managedProfilesCount;
2324 }
2325
2326 /**
2327 * Starts the first passenger of the given driver and assigns the passenger to the front
2328 * passenger zone.
2329 *
2330 * @param driverId User id of the driver.
2331 * @return whether it succeeds.
2332 */
2333 private boolean startFirstPassenger(@UserIdInt int driverId) {
2334 int zoneId = getAvailablePassengerZone();
2335 if (zoneId == OccupantZoneInfo.INVALID_ZONE_ID) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002336 Slog.w(TAG, "passenger occupant zone is not found");
Eric Jeongc91f9452019-08-30 15:04:21 -07002337 return false;
2338 }
2339 List<UserInfo> passengers = getPassengers(driverId);
2340 if (passengers.size() < 1) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002341 Slog.w(TAG, "passenger is not found");
Eric Jeongc91f9452019-08-30 15:04:21 -07002342 return false;
2343 }
2344 // Only one passenger is supported. If there are two or more passengers, the first passenger
2345 // is chosen.
2346 int passengerId = passengers.get(0).id;
2347 if (!startPassenger(passengerId, zoneId)) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002348 Slog.w(TAG, "cannot start passenger " + passengerId);
Eric Jeongc91f9452019-08-30 15:04:21 -07002349 return false;
2350 }
2351 return true;
2352 }
2353
2354 private int getAvailablePassengerZone() {
2355 int[] occupantTypes = new int[] {CarOccupantZoneManager.OCCUPANT_TYPE_FRONT_PASSENGER,
2356 CarOccupantZoneManager.OCCUPANT_TYPE_REAR_PASSENGER};
2357 for (int occupantType : occupantTypes) {
2358 int zoneId = getZoneId(occupantType);
2359 if (zoneId != OccupantZoneInfo.INVALID_ZONE_ID) {
2360 return zoneId;
2361 }
2362 }
2363 return OccupantZoneInfo.INVALID_ZONE_ID;
2364 }
2365
2366 /**
2367 * Creates a new passenger user when there is no passenger user.
2368 */
2369 private void setupPassengerUser() {
2370 int currentUser = ActivityManager.getCurrentUser();
2371 int profileCount = getNumberOfManagedProfiles(currentUser);
2372 if (profileCount > 0) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002373 Slog.w(TAG, "max profile of user" + currentUser
Eric Jeongc91f9452019-08-30 15:04:21 -07002374 + " is exceeded: current profile count is " + profileCount);
2375 return;
2376 }
2377 // TODO(b/140311342): Use resource string for the default passenger name.
2378 UserInfo passenger = createPassenger("Passenger", currentUser);
2379 if (passenger == null) {
2380 // Couldn't create user, most likely because there are too many.
Eric Jeongf75d4132020-12-21 13:48:23 -08002381 Slog.w(TAG, "cannot create a passenger user");
Eric Jeongc91f9452019-08-30 15:04:21 -07002382 return;
2383 }
2384 }
2385
2386 @NonNull
2387 private List<OccupantZoneInfo> getOccupantZones(@OccupantTypeEnum int occupantType) {
2388 ZoneUserBindingHelper helper = null;
2389 synchronized (mLockHelper) {
2390 if (mZoneUserBindingHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002391 Slog.w(TAG, "implementation is not delegated");
Eric Jeongc91f9452019-08-30 15:04:21 -07002392 return new ArrayList<OccupantZoneInfo>();
2393 }
2394 helper = mZoneUserBindingHelper;
2395 }
2396 return helper.getOccupantZones(occupantType);
2397 }
2398
2399 private boolean assignUserToOccupantZone(@UserIdInt int userId, int zoneId) {
2400 ZoneUserBindingHelper helper = null;
2401 synchronized (mLockHelper) {
2402 if (mZoneUserBindingHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002403 Slog.w(TAG, "implementation is not delegated");
Eric Jeongc91f9452019-08-30 15:04:21 -07002404 return false;
2405 }
2406 helper = mZoneUserBindingHelper;
2407 }
2408 return helper.assignUserToOccupantZone(userId, zoneId);
2409 }
2410
2411 private boolean unassignUserFromOccupantZone(@UserIdInt int userId) {
2412 ZoneUserBindingHelper helper = null;
2413 synchronized (mLockHelper) {
2414 if (mZoneUserBindingHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002415 Slog.w(TAG, "implementation is not delegated");
Eric Jeongc91f9452019-08-30 15:04:21 -07002416 return false;
2417 }
2418 helper = mZoneUserBindingHelper;
2419 }
2420 return helper.unassignUserFromOccupantZone(userId);
2421 }
2422
2423 private boolean isPassengerDisplayAvailable() {
2424 ZoneUserBindingHelper helper = null;
2425 synchronized (mLockHelper) {
2426 if (mZoneUserBindingHelper == null) {
Eric Jeongf75d4132020-12-21 13:48:23 -08002427 Slog.w(TAG, "implementation is not delegated");
Eric Jeongc91f9452019-08-30 15:04:21 -07002428 return false;
2429 }
2430 helper = mZoneUserBindingHelper;
2431 }
2432 return helper.isPassengerDisplayAvailable();
2433 }
2434
2435 /**
2436 * Gets the zone id of the given occupant type. If there are two or more zones, the first found
2437 * zone is returned.
2438 *
2439 * @param occupantType The type of an occupant.
2440 * @return The zone id of the given occupant type. {@link OccupantZoneInfo.INVALID_ZONE_ID},
2441 * if not found.
2442 */
2443 private int getZoneId(@OccupantTypeEnum int occupantType) {
2444 List<OccupantZoneInfo> zoneInfos = getOccupantZones(occupantType);
2445 return (zoneInfos.size() > 0) ? zoneInfos.get(0).zoneId : OccupantZoneInfo.INVALID_ZONE_ID;
2446 }
Mayank Garg9732d602020-08-09 21:02:40 -07002447
2448 /**
2449 * Manages the required number of pre-created users.
2450 */
Mayank Garga3b72d02021-03-14 23:05:51 -07002451 @Override
2452 public void updatePreCreatedUsers() {
2453 checkManageOrCreateUsersPermission("preCreateUsers");
2454 preCreateUsersInternal();
Mayank Garg02576972021-02-18 16:46:07 -08002455 }
2456
Mayank Garga3b72d02021-03-14 23:05:51 -07002457 private void preCreateUsersInternal() {
2458 mHandler.post(() -> mUserPreCreator.managePreCreatedUsers());
Mayank Garg9732d602020-08-09 21:02:40 -07002459 }
Felipe Leme17799202020-09-03 12:55:53 -07002460
2461 // TODO(b/167698977): members below were copied from UserManagerService; it would be better to
2462 // move them to some internal android.os class instead.
2463
2464 private static final int ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION =
2465 UserInfo.FLAG_MANAGED_PROFILE
2466 | UserInfo.FLAG_PROFILE
2467 | UserInfo.FLAG_EPHEMERAL
2468 | UserInfo.FLAG_RESTRICTED
2469 | UserInfo.FLAG_GUEST
2470 | UserInfo.FLAG_DEMO
2471 | UserInfo.FLAG_FULL;
2472
2473 private static void checkManageUsersPermission(String message) {
2474 if (!hasManageUsersPermission()) {
2475 throw new SecurityException("You need " + MANAGE_USERS + " permission to: " + message);
2476 }
2477 }
2478
2479 private static void checkManageOrCreateUsersPermission(String message) {
2480 if (!hasManageOrCreateUsersPermission()) {
2481 throw new SecurityException(
2482 "You either need " + MANAGE_USERS + " or " + CREATE_USERS + " permission to: "
2483 + message);
2484 }
2485 }
2486
2487 private static void checkManageOrCreateUsersPermission(int creationFlags) {
2488 if ((creationFlags & ~ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION) == 0) {
2489 if (!hasManageOrCreateUsersPermission()) {
2490 throw new SecurityException("You either need " + MANAGE_USERS + " or "
2491 + CREATE_USERS + "permission to create a user with flags "
2492 + creationFlags);
2493 }
2494 } else if (!hasManageUsersPermission()) {
2495 throw new SecurityException("You need " + MANAGE_USERS + " permission to create a user"
2496 + " with flags " + creationFlags);
2497 }
2498 }
2499
2500 private static boolean hasManageUsersPermission() {
2501 final int callingUid = Binder.getCallingUid();
2502 return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
2503 || callingUid == Process.ROOT_UID
2504 || hasPermissionGranted(MANAGE_USERS, callingUid);
2505 }
2506
2507 private static boolean hasManageUsersOrPermission(String alternativePermission) {
2508 final int callingUid = Binder.getCallingUid();
2509 return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
2510 || callingUid == Process.ROOT_UID
2511 || hasPermissionGranted(MANAGE_USERS, callingUid)
2512 || hasPermissionGranted(alternativePermission, callingUid);
2513 }
2514
2515 private static boolean hasManageOrCreateUsersPermission() {
2516 return hasManageUsersOrPermission(CREATE_USERS);
2517 }
2518
2519 private static boolean hasPermissionGranted(String permission, int uid) {
2520 return ActivityManager.checkComponentPermission(permission, uid, /* owningUid= */ -1,
2521 /* exported= */ true) == PackageManager.PERMISSION_GRANTED;
2522 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002523}