blob: 15c8e6fd93035dc96e7e29af5c5e0dceb5fd6440 [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
Eric Jeong1545f3b2019-09-16 13:56:52 -070023import static com.android.car.CarLog.TAG_USER;
Felipe Leme55236722020-10-16 16:54:32 -070024import static com.android.car.PermissionHelper.checkHasAtLeastOnePermissionGranted;
25import static com.android.car.PermissionHelper.checkHasDumpPermissionGranted;
Eric Jeong1545f3b2019-09-16 13:56:52 -070026
27import android.annotation.NonNull;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070028import android.annotation.Nullable;
Eric Jeong1545f3b2019-09-16 13:56:52 -070029import android.annotation.UserIdInt;
Keun young Parkfb656372019-03-12 18:37:55 -070030import android.app.ActivityManager;
Louis Chang3bf2f202020-08-18 13:04:28 +080031import android.app.ActivityTaskManager.RootTaskInfo;
Keun young Parkfb656372019-03-12 18:37:55 -070032import android.app.IActivityManager;
Eric Jeongc91f9452019-08-30 15:04:21 -070033import android.car.CarOccupantZoneManager;
34import android.car.CarOccupantZoneManager.OccupantTypeEnum;
35import android.car.CarOccupantZoneManager.OccupantZoneInfo;
Eric Jeong1545f3b2019-09-16 13:56:52 -070036import android.car.ICarUserService;
Felipe Leme5d5ab142020-10-27 13:49:10 -070037import android.car.drivingstate.CarUxRestrictions;
jovanak24470652018-09-11 17:51:57 -070038import android.car.settings.CarSettings;
Felipe Leme5528ff72020-02-10 19:05:14 -080039import android.car.user.CarUserManager;
Antonio Kantekc8114752020-03-05 21:37:39 -080040import android.car.user.CarUserManager.UserLifecycleEvent;
41import android.car.user.CarUserManager.UserLifecycleListener;
felipealdfdf8512020-06-01 09:35:45 -070042import android.car.user.UserCreationResult;
felipeal159a2a42020-05-08 10:32:11 -070043import android.car.user.UserIdentificationAssociationResponse;
Mayank Garga55c3092020-05-28 03:19:24 -070044import android.car.user.UserRemovalResult;
felipeale5bf0322020-04-16 15:10:57 -070045import android.car.user.UserSwitchResult;
felipeal19e3d732020-03-18 12:07:32 -070046import android.car.userlib.HalCallback;
47import android.car.userlib.UserHalHelper;
Mayank Garge90a4082020-09-30 12:57:34 -070048import android.car.userlib.UserHelper;
Felipe Leme6b34fc32020-10-26 15:49:17 -070049import android.content.BroadcastReceiver;
Mayank Garga480dd92020-05-14 03:14:57 -070050import android.content.ComponentName;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070051import android.content.Context;
Felipe Leme6b34fc32020-10-26 15:49:17 -070052import android.content.Intent;
53import android.content.IntentFilter;
Mayank Garga480dd92020-05-14 03:14:57 -070054import android.content.pm.PackageManager;
55import android.content.pm.PackageManager.NameNotFoundException;
Eric Jeong1545f3b2019-09-16 13:56:52 -070056import android.content.pm.UserInfo;
felipealdfdf8512020-06-01 09:35:45 -070057import android.content.pm.UserInfo.UserInfoFlag;
Felipe Leme315a53b2020-03-12 10:51:04 -070058import android.content.res.Resources;
Anthony Hugh6fed1e92019-10-22 16:22:03 -070059import android.graphics.Bitmap;
felipealdfdf8512020-06-01 09:35:45 -070060import android.hardware.automotive.vehicle.V2_0.CreateUserRequest;
61import android.hardware.automotive.vehicle.V2_0.CreateUserStatus;
Mayank Garg70732a82020-08-05 20:17:47 -070062import android.hardware.automotive.vehicle.V2_0.InitialUserInfoRequestType;
Felipe Lemec6e3c2a2020-02-19 16:53:57 -080063import android.hardware.automotive.vehicle.V2_0.InitialUserInfoResponseAction;
Mayank Garga55c3092020-05-28 03:19:24 -070064import android.hardware.automotive.vehicle.V2_0.RemoveUserRequest;
Mayank Gargeb37d092020-06-02 14:37:57 -070065import android.hardware.automotive.vehicle.V2_0.SwitchUserRequest;
Mayank Garg59f22192020-03-27 00:51:45 -070066import android.hardware.automotive.vehicle.V2_0.SwitchUserStatus;
felipeal5e3ede42020-04-23 18:04:07 -070067import android.hardware.automotive.vehicle.V2_0.UserIdentificationGetRequest;
68import android.hardware.automotive.vehicle.V2_0.UserIdentificationResponse;
felipeal159a2a42020-05-08 10:32:11 -070069import android.hardware.automotive.vehicle.V2_0.UserIdentificationSetAssociation;
70import android.hardware.automotive.vehicle.V2_0.UserIdentificationSetRequest;
Felipe Lemec6e3c2a2020-02-19 16:53:57 -080071import android.hardware.automotive.vehicle.V2_0.UsersInfo;
Ying Zheng1ab32b62018-06-26 12:47:26 -070072import android.location.LocationManager;
Eric Jeong1545f3b2019-09-16 13:56:52 -070073import android.os.Binder;
Felipe Leme5528ff72020-02-10 19:05:14 -080074import android.os.Bundle;
Antonio Kantek7236a5b2020-04-06 19:53:55 -070075import android.os.Handler;
76import android.os.HandlerThread;
Felipe Leme17799202020-09-03 12:55:53 -070077import android.os.Process;
Keun young Parkfb656372019-03-12 18:37:55 -070078import android.os.RemoteException;
Mayank Garg31e73042020-01-23 00:10:38 -080079import android.os.Trace;
Ying Zhengcf20f442018-06-22 16:54:51 -070080import android.os.UserHandle;
Ying Zheng8f90edb2018-06-13 12:42:31 -070081import android.os.UserManager;
jovanak24470652018-09-11 17:51:57 -070082import android.provider.Settings;
Felipe Lemee3cab982020-03-12 11:39:29 -070083import android.sysprop.CarProperties;
felipeal159a2a42020-05-08 10:32:11 -070084import android.text.TextUtils;
felipeal312416a2020-04-14 12:28:24 -070085import android.util.EventLog;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070086import android.util.Log;
Felipe Leme5528ff72020-02-10 19:05:14 -080087import android.util.SparseArray;
Felipe Leme6b34fc32020-10-26 15:49:17 -070088import android.util.SparseBooleanArray;
Mayank Garg31e73042020-01-23 00:10:38 -080089import android.util.TimingsTraceLog;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070090
91import com.android.car.CarServiceBase;
Keun young Parkb241d022020-04-20 20:31:34 -070092import com.android.car.CarServiceUtils;
Felipe Leme5d5ab142020-10-27 13:49:10 -070093import com.android.car.CarUxRestrictionsManagerService;
Eric Jeongc91f9452019-08-30 15:04:21 -070094import com.android.car.R;
Felipe Leme58412202020-01-09 13:45:33 -080095import com.android.car.hal.UserHalService;
Mayank Gargf59f95b2020-10-01 14:55:11 -070096import com.android.car.internal.common.CommonConstants.UserLifecycleEventType;
Mayank Garg801ea6a2020-09-29 15:43:49 -070097import com.android.car.internal.common.EventLogTags;
98import com.android.car.internal.common.UserHelperLite;
Mayank Garg4bdfbf72020-08-06 13:27:43 -070099import com.android.car.power.CarPowerManagementService;
Mayank Garg665c20b2020-08-07 16:19:28 -0700100import com.android.car.user.InitialUserSetter.InitialUserInfo;
Keun-young Parkd462a912019-02-11 08:53:42 -0800101import com.android.internal.annotations.GuardedBy;
Keun young Parkf3523cd2019-04-08 10:09:17 -0700102import com.android.internal.annotations.VisibleForTesting;
felipeale5bf0322020-04-16 15:10:57 -0700103import com.android.internal.infra.AndroidFuture;
Felipe Leme5528ff72020-02-10 19:05:14 -0800104import com.android.internal.os.IResultReceiver;
felipeal5e3ede42020-04-23 18:04:07 -0700105import com.android.internal.util.ArrayUtils;
felipeal2a84d512020-04-06 18:52:15 -0700106import com.android.internal.util.FunctionalUtils;
Mayank Garge19c2922020-03-30 18:05:53 -0700107import com.android.internal.util.Preconditions;
Anthony Hugh6fed1e92019-10-22 16:22:03 -0700108import com.android.internal.util.UserIcons;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700109
110import java.io.PrintWriter;
Keun-young Parkd462a912019-02-11 08:53:42 -0800111import java.util.ArrayList;
felipeal2d0483c2019-11-02 14:07:22 -0700112import java.util.Arrays;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700113import java.util.Iterator;
114import java.util.List;
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +0000115import java.util.Objects;
Pavel Maltsev17e81832019-04-04 14:38:41 -0700116import java.util.concurrent.CopyOnWriteArrayList;
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700117import java.util.concurrent.CountDownLatch;
118import java.util.concurrent.TimeUnit;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700119
120/**
121 * User service for cars. Manages users at boot time. Including:
122 *
123 * <ol>
Eric Jeong1545f3b2019-09-16 13:56:52 -0700124 * <li> Creates a user used as driver.
125 * <li> Creates a user used as passenger.
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700126 * <li> Creates a secondary admin user on first run.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700127 * <li> Switch drivers.
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700128 * <ol/>
129 */
Eric Jeong1545f3b2019-09-16 13:56:52 -0700130public final class CarUserService extends ICarUserService.Stub implements CarServiceBase {
Felipe Leme5528ff72020-02-10 19:05:14 -0800131
felipealf7368962020-04-16 12:55:19 -0700132 private static final String TAG = TAG_USER;
133
Felipe Lemeabbf2da2020-02-24 18:25:29 -0800134 /** {@code int} extra used to represent a user id in a {@link IResultReceiver} response. */
Mayank Garg8f932822020-09-17 16:09:12 -0700135 public static final String BUNDLE_USER_ID = "user.id";
Felipe Lemeabbf2da2020-02-24 18:25:29 -0800136 /** {@code int} extra used to represent user flags in a {@link IResultReceiver} response. */
Mayank Garg8f932822020-09-17 16:09:12 -0700137 public static final String BUNDLE_USER_FLAGS = "user.flags";
Felipe Lemeabbf2da2020-02-24 18:25:29 -0800138 /** {@code String} extra used to represent a user name in a {@link IResultReceiver} response. */
Mayank Garg8f932822020-09-17 16:09:12 -0700139 public static final String BUNDLE_USER_NAME = "user.name";
felipeala68ecef2020-05-19 12:46:08 -0700140 /**
141 * {@code int} extra used to represent the user locales in a {@link IResultReceiver} response.
142 */
Mayank Garg8f932822020-09-17 16:09:12 -0700143 public static final String BUNDLE_USER_LOCALES = "user.locales";
felipeala68ecef2020-05-19 12:46:08 -0700144 /**
145 * {@code int} extra used to represent the info action in a {@link IResultReceiver} response.
146 */
Mayank Garg8f932822020-09-17 16:09:12 -0700147 public static final String BUNDLE_INITIAL_INFO_ACTION = "initial_info.action";
Felipe Leme5528ff72020-02-10 19:05:14 -0800148
Mayank Garg9ed099e2020-06-04 16:05:20 -0700149 public static final String VEHICLE_HAL_NOT_SUPPORTED = "Vehicle Hal not supported.";
150
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700151 private final Context mContext;
Keun young Parkfb656372019-03-12 18:37:55 -0700152 private final IActivityManager mAm;
Anthony Hugh9932a252019-06-12 16:19:56 -0700153 private final UserManager mUserManager;
154 private final int mMaxRunningUsers;
Mayank Garg70732a82020-08-05 20:17:47 -0700155 private final InitialUserSetter mInitialUserSetter;
Eric Jeongc91f9452019-08-30 15:04:21 -0700156 private final boolean mEnablePassengerSupport;
Mayank Garg9732d602020-08-09 21:02:40 -0700157 private final UserPreCreator mUserPreCreator;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700158
Eric Jeongc91f9452019-08-30 15:04:21 -0700159 private final Object mLockUser = new Object();
160 @GuardedBy("mLockUser")
Keun-young Parkd462a912019-02-11 08:53:42 -0800161 private boolean mUser0Unlocked;
Eric Jeongc91f9452019-08-30 15:04:21 -0700162 @GuardedBy("mLockUser")
Keun-young Parkd462a912019-02-11 08:53:42 -0800163 private final ArrayList<Runnable> mUser0UnlockTasks = new ArrayList<>();
Eric Jeongc91f9452019-08-30 15:04:21 -0700164 // Only one passenger is supported.
165 @GuardedBy("mLockUser")
166 private @UserIdInt int mLastPassengerId;
Keun young Parkf3523cd2019-04-08 10:09:17 -0700167 /**
168 * Background users that will be restarted in garage mode. This list can include the
Mayank Garg31e73042020-01-23 00:10:38 -0800169 * current foreground user but the current foreground user should not be restarted.
Keun young Parkf3523cd2019-04-08 10:09:17 -0700170 */
Eric Jeongc91f9452019-08-30 15:04:21 -0700171 @GuardedBy("mLockUser")
Keun young Parkf3523cd2019-04-08 10:09:17 -0700172 private final ArrayList<Integer> mBackgroundUsersToRestart = new ArrayList<>();
173 /**
174 * Keep the list of background users started here. This is wholly for debugging purpose.
175 */
Eric Jeongc91f9452019-08-30 15:04:21 -0700176 @GuardedBy("mLockUser")
Keun young Parkf3523cd2019-04-08 10:09:17 -0700177 private final ArrayList<Integer> mBackgroundUsersRestartedHere = new ArrayList<>();
178
Felipe Leme58412202020-01-09 13:45:33 -0800179 private final UserHalService mHal;
180
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700181 // HandlerThread and Handler used when notifying app listeners (mAppLifecycleListeners).
Keun young Parkb241d022020-04-20 20:31:34 -0700182 private final HandlerThread mHandlerThread = CarServiceUtils.getHandlerThread(
183 getClass().getSimpleName());
184 private final Handler mHandler = new Handler(mHandlerThread.getLooper());
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700185
Felipe Leme5528ff72020-02-10 19:05:14 -0800186 /**
Antonio Kantekc8114752020-03-05 21:37:39 -0800187 * List of listeners to be notified on new user activities events.
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700188 * This collection should be accessed and manipulated by mHandlerThread only.
Antonio Kantekc8114752020-03-05 21:37:39 -0800189 */
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700190 private final List<UserLifecycleListener> mUserLifecycleListeners = new ArrayList<>();
Antonio Kantekc8114752020-03-05 21:37:39 -0800191
192 /**
Felipe Leme5528ff72020-02-10 19:05:14 -0800193 * List of lifecycle listeners by uid.
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700194 * This collection should be accessed and manipulated by mHandlerThread only.
Felipe Leme5528ff72020-02-10 19:05:14 -0800195 */
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700196 private final SparseArray<IResultReceiver> mAppLifecycleListeners = new SparseArray<>();
Felipe Leme5528ff72020-02-10 19:05:14 -0800197
Mayank Garg7a114c82020-04-08 21:25:06 -0700198 /**
199 * User Id for the user switch in process, if any.
200 */
201 @GuardedBy("mLockUser")
felipealf7368962020-04-16 12:55:19 -0700202 private int mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
Mayank Garg7a114c82020-04-08 21:25:06 -0700203 /**
204 * Request Id for the user switch in process, if any.
205 */
206 @GuardedBy("mLockUser")
felipealf7368962020-04-16 12:55:19 -0700207 private int mRequestIdForUserSwitchInProcess;
Felipe Lemee3cab982020-03-12 11:39:29 -0700208 private final int mHalTimeoutMs = CarProperties.user_hal_timeout().orElse(5_000);
209
Eric Jeongc91f9452019-08-30 15:04:21 -0700210 private final CopyOnWriteArrayList<PassengerCallback> mPassengerCallbacks =
211 new CopyOnWriteArrayList<>();
212
Mayank Garg7e1450b2020-08-07 18:15:15 -0700213 // TODO(b/163566866): Use mSwitchGuestUserBeforeSleep for new create guest request
214 private final boolean mSwitchGuestUserBeforeSleep;
215
felipeal61ce3732020-04-03 11:01:00 -0700216 @Nullable
217 @GuardedBy("mLockUser")
218 private UserInfo mInitialUser;
219
Mayank Garg587f1942020-05-06 01:41:34 -0700220 private IResultReceiver mUserSwitchUiReceiver;
221
Felipe Leme5d5ab142020-10-27 13:49:10 -0700222 private final CarUxRestrictionsManagerService mUxRestrictionService;
223
Eric Jeongc91f9452019-08-30 15:04:21 -0700224 /** Interface for callbaks related to passenger activities. */
225 public interface PassengerCallback {
226 /** Called when passenger is started at a certain zone. */
227 void onPassengerStarted(@UserIdInt int passengerId, int zoneId);
228 /** Called when passenger is stopped. */
229 void onPassengerStopped(@UserIdInt int passengerId);
230 }
231
232 /** Interface for delegating zone-related implementation to CarOccupantZoneService. */
233 public interface ZoneUserBindingHelper {
234 /** Gets occupant zones corresponding to the occupant type. */
235 @NonNull
236 List<OccupantZoneInfo> getOccupantZones(@OccupantTypeEnum int occupantType);
237 /** Assigns the user to the occupant zone. */
238 boolean assignUserToOccupantZone(@UserIdInt int userId, int zoneId);
239 /** Makes the occupant zone unoccupied. */
240 boolean unassignUserFromOccupantZone(@UserIdInt int userId);
241 /** Returns whether there is a passenger display. */
242 boolean isPassengerDisplayAvailable();
243 }
244
245 private final Object mLockHelper = new Object();
246 @GuardedBy("mLockHelper")
247 private ZoneUserBindingHelper mZoneUserBindingHelper;
248
Felipe Leme6b34fc32020-10-26 15:49:17 -0700249 private final BroadcastReceiver mUserLifecycleReceiver = new BroadcastReceiver() {
250 @Override
251 public void onReceive(Context context, Intent intent) {
252 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
253 Log.d(TAG_USER, "onReceive: " + intent);
254 }
255 switch(intent.getAction()) {
256 case Intent.ACTION_USER_REMOVED:
257 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
258 notifyHalUserRemoved(userId);
259 break;
260 default:
261 Log.w(TAG, "received unexpected intent: " + intent);
262 }
263 }
264 };
265
266 /** Map used to avoid calling UserHAL when a user was removed because HAL creation failed. */
267 @GuardedBy("mLockUser")
268 private final SparseBooleanArray mFailedToCreateUserIds = new SparseBooleanArray(1);
269
Felipe Leme58412202020-01-09 13:45:33 -0800270 public CarUserService(@NonNull Context context, @NonNull UserHalService hal,
Mayank Garge90a4082020-09-30 12:57:34 -0700271 @NonNull UserManager userManager,
Felipe Leme5d5ab142020-10-27 13:49:10 -0700272 @NonNull IActivityManager am, int maxRunningUsers,
273 @NonNull CarUxRestrictionsManagerService uxRestrictionService) {
Mayank Garge90a4082020-09-30 12:57:34 -0700274 this(context, hal, userManager, am, maxRunningUsers,
Felipe Leme5d5ab142020-10-27 13:49:10 -0700275 /* initialUserSetter= */ null, /* userPreCreator= */ null, uxRestrictionService);
Mayank Garg71661ea2020-04-29 01:25:03 -0700276 }
277
278 @VisibleForTesting
279 CarUserService(@NonNull Context context, @NonNull UserHalService hal,
Mayank Garge90a4082020-09-30 12:57:34 -0700280 @NonNull UserManager userManager,
Mayank Gargccad8062020-08-30 15:05:10 -0700281 @NonNull IActivityManager am, int maxRunningUsers,
Mayank Garg1bb1c382020-09-03 17:11:11 -0700282 @Nullable InitialUserSetter initialUserSetter,
Felipe Leme5d5ab142020-10-27 13:49:10 -0700283 @Nullable UserPreCreator userPreCreator,
284 @NonNull CarUxRestrictionsManagerService uxRestrictionService) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700285 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
286 Log.d(TAG_USER, "constructed");
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700287 }
288 mContext = context;
Felipe Leme58412202020-01-09 13:45:33 -0800289 mHal = hal;
Keun young Parkf3523cd2019-04-08 10:09:17 -0700290 mAm = am;
291 mMaxRunningUsers = maxRunningUsers;
Anthony Hugh9932a252019-06-12 16:19:56 -0700292 mUserManager = userManager;
Eric Jeongc91f9452019-08-30 15:04:21 -0700293 mLastPassengerId = UserHandle.USER_NULL;
Mayank Garg1bb1c382020-09-03 17:11:11 -0700294 mInitialUserSetter =
295 initialUserSetter == null ? new InitialUserSetter(context, (u) -> setInitialUser(u))
296 : initialUserSetter;
297 mUserPreCreator =
298 userPreCreator == null ? new UserPreCreator(mUserManager) : userPreCreator;
Mayank Garg7e1450b2020-08-07 18:15:15 -0700299 Resources resources = context.getResources();
300 mEnablePassengerSupport = resources.getBoolean(R.bool.enablePassengerSupport);
301 mSwitchGuestUserBeforeSleep = resources.getBoolean(
302 R.bool.config_switchGuestUserBeforeGoingSleep);
Felipe Leme5d5ab142020-10-27 13:49:10 -0700303 mUxRestrictionService = uxRestrictionService;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700304 }
305
306 @Override
307 public void init() {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700308 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
309 Log.d(TAG_USER, "init");
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700310 }
Felipe Leme6b34fc32020-10-26 15:49:17 -0700311 mContext.registerReceiver(mUserLifecycleReceiver,
312 new IntentFilter(Intent.ACTION_USER_REMOVED));
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700313 }
314
315 @Override
316 public void release() {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700317 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
318 Log.d(TAG_USER, "release");
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700319 }
Felipe Leme6b34fc32020-10-26 15:49:17 -0700320 mContext.unregisterReceiver(mUserLifecycleReceiver);
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700321 }
322
323 @Override
Eric Jeong1545f3b2019-09-16 13:56:52 -0700324 public void dump(@NonNull PrintWriter writer) {
Felipe Leme55236722020-10-16 16:54:32 -0700325 checkHasDumpPermissionGranted("dump()");
326
Eric Jeong1545f3b2019-09-16 13:56:52 -0700327 writer.println("*CarUserService*");
Felipe Leme5528ff72020-02-10 19:05:14 -0800328 String indent = " ";
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700329 handleDumpListeners(writer, indent);
Mayank Garg587f1942020-05-06 01:41:34 -0700330 writer.printf("User switch UI receiver %s\n", mUserSwitchUiReceiver);
Eric Jeongc91f9452019-08-30 15:04:21 -0700331 synchronized (mLockUser) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700332 writer.println("User0Unlocked: " + mUser0Unlocked);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700333 writer.println("BackgroundUsersToRestart: " + mBackgroundUsersToRestart);
334 writer.println("BackgroundUsersRestarted: " + mBackgroundUsersRestartedHere);
Felipe Leme6b34fc32020-10-26 15:49:17 -0700335 if (mFailedToCreateUserIds.size() > 0) {
336 writer.println("FailedToCreateUserIds: " + mFailedToCreateUserIds);
337 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700338 }
339 writer.println("MaxRunningUsers: " + mMaxRunningUsers);
340 List<UserInfo> allDrivers = getAllDrivers();
341 int driversSize = allDrivers.size();
342 writer.println("NumberOfDrivers: " + driversSize);
343 for (int i = 0; i < driversSize; i++) {
344 int driverId = allDrivers.get(i).id;
345 writer.print(indent + "#" + i + ": id=" + driverId);
346 List<UserInfo> passengers = getPassengers(driverId);
347 int passengersSize = passengers.size();
348 writer.print(" NumberPassengers: " + passengersSize);
349 if (passengersSize > 0) {
350 writer.print(" [");
351 for (int j = 0; j < passengersSize; j++) {
352 writer.print(passengers.get(j).id);
353 if (j < passengersSize - 1) {
354 writer.print(" ");
felipeal2d0483c2019-11-02 14:07:22 -0700355 }
felipeal2d0483c2019-11-02 14:07:22 -0700356 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700357 writer.print("]");
felipeal2d0483c2019-11-02 14:07:22 -0700358 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700359 writer.println();
360 }
361 writer.printf("EnablePassengerSupport: %s\n", mEnablePassengerSupport);
362 writer.printf("User HAL timeout: %dms\n", mHalTimeoutMs);
363 writer.printf("Initial user: %s\n", mInitialUser);
felipealbf327652020-06-03 11:33:29 -0700364
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700365 writer.println("Relevant overlayable properties");
366 Resources res = mContext.getResources();
367 writer.printf("%sowner_name=%s\n", indent,
368 res.getString(com.android.internal.R.string.owner_name));
369 writer.printf("%sdefault_guest_name=%s\n", indent,
370 res.getString(R.string.default_guest_name));
felipealf7368962020-04-16 12:55:19 -0700371 writer.printf("User switch in process=%d\n", mUserIdForUserSwitchInProcess);
Mayank Garg7a114c82020-04-08 21:25:06 -0700372 writer.printf("Request Id for the user switch in process=%d\n ",
373 mRequestIdForUserSwitchInProcess);
Mayank Garga480dd92020-05-14 03:14:57 -0700374 writer.printf("System UI package name=%s\n", getSystemUiPackageName());
Felipe Leme5d5ab142020-10-27 13:49:10 -0700375 writer.printf("Is UX restricted: %b\n", isUxRestricted());
felipeale8c5dce2020-04-15 11:27:06 -0700376
felipealbf327652020-06-03 11:33:29 -0700377 writer.println("Relevant Global settings");
378 dumpGlobalProperty(writer, indent, CarSettings.Global.LAST_ACTIVE_USER_ID);
379 dumpGlobalProperty(writer, indent, CarSettings.Global.LAST_ACTIVE_PERSISTENT_USER_ID);
380
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700381 mInitialUserSetter.dump(writer);
felipeale8c5dce2020-04-15 11:27:06 -0700382 }
383
felipealbf327652020-06-03 11:33:29 -0700384 private void dumpGlobalProperty(PrintWriter writer, String indent, String property) {
385 String value = Settings.Global.getString(mContext.getContentResolver(), property);
386 writer.printf("%s%s=%s\n", indent, property, value);
387 }
388
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700389 private void handleDumpListeners(@NonNull PrintWriter writer, String indent) {
390 CountDownLatch latch = new CountDownLatch(1);
391 mHandler.post(() -> {
felipealde1e16d2020-06-03 13:20:48 -0700392 handleDumpServiceLifecycleListeners(writer);
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700393 handleDumpAppLifecycleListeners(writer, indent);
394 latch.countDown();
395 });
396 int timeout = 5;
397 try {
398 if (!latch.await(timeout, TimeUnit.SECONDS)) {
399 writer.printf("Handler thread didn't respond in %ds when dumping listeners\n",
400 timeout);
401 }
402 } catch (InterruptedException e) {
403 Thread.currentThread().interrupt();
404 writer.println("Interrupted waiting for handler thread to dump app and user listeners");
405 }
406 }
407
felipealde1e16d2020-06-03 13:20:48 -0700408 private void handleDumpServiceLifecycleListeners(@NonNull PrintWriter writer) {
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700409 if (mUserLifecycleListeners.isEmpty()) {
felipealde1e16d2020-06-03 13:20:48 -0700410 writer.println("No lifecycle listeners for internal services");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700411 return;
412 }
felipealde1e16d2020-06-03 13:20:48 -0700413 int size = mUserLifecycleListeners.size();
414 writer.printf("%d lifecycle listener%s for services\n", size, size == 1 ? "" : "s");
415 String indent = " ";
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700416 for (UserLifecycleListener listener : mUserLifecycleListeners) {
felipealde1e16d2020-06-03 13:20:48 -0700417 writer.printf("%s%s\n", indent, FunctionalUtils.getLambdaName(listener));
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700418 }
419 }
420
421 private void handleDumpAppLifecycleListeners(@NonNull PrintWriter writer, String indent) {
felipealde1e16d2020-06-03 13:20:48 -0700422 int size = mAppLifecycleListeners.size();
423 if (size == 0) {
424 writer.println("No lifecycle listeners for apps");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700425 return;
426 }
felipealde1e16d2020-06-03 13:20:48 -0700427 writer.printf("%d lifecycle listener%s for apps \n", size, size == 1 ? "" : "s");
428 for (int i = 0; i < size; i++) {
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700429 int uid = mAppLifecycleListeners.keyAt(i);
430 IResultReceiver listener = mAppLifecycleListeners.valueAt(i);
Felipe Lemeea4b5322020-10-26 15:33:36 -0700431 writer.printf("%suid: %d listener: %s\n", indent, uid,
432 FunctionalUtils.getLambdaName(listener));
Keun-young Parkd462a912019-02-11 08:53:42 -0800433 }
Eric Jeong1545f3b2019-09-16 13:56:52 -0700434 }
435
436 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700437 * @see ExperimentalCarUserManager.createDriver
Eric Jeong1545f3b2019-09-16 13:56:52 -0700438 */
439 @Override
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700440 public AndroidFuture<UserCreationResult> createDriver(@NonNull String name, boolean admin) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700441 checkManageUsersPermission("createDriver");
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +0000442 Objects.requireNonNull(name, "name cannot be null");
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700443
444 AndroidFuture<UserCreationResult> future = new AndroidFuture<UserCreationResult>() {
445 @Override
446 protected void onCompleted(UserCreationResult result, Throwable err) {
447 if (result == null) {
448 Log.w(TAG, "createDriver(" + name + "," + admin + ") failed: " + err);
449 } else {
450 if (result.getStatus() == UserCreationResult.STATUS_SUCCESSFUL) {
451 assignDefaultIcon(result.getUser());
452 }
453 }
454 super.onCompleted(result, err);
455 };
456 };
457 int flags = 0;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700458 if (admin) {
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700459 if (!(mUserManager.isAdminUser() || mUserManager.isSystemUser())) {
460 Log.e(TAG_USER, "Only admin users and system user can create other admins.");
461 sendUserCreationResultFailure(future, UserCreationResult.STATUS_INVALID_REQUEST);
462 return future;
463 }
464 flags = UserInfo.FLAG_ADMIN;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700465 }
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700466 createUser(name, UserInfo.getDefaultUserType(flags), flags, mHalTimeoutMs, future);
467 return future;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700468 }
469
470 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700471 * @see ExperimentalCarUserManager.createPassenger
Eric Jeong1545f3b2019-09-16 13:56:52 -0700472 */
473 @Override
474 @Nullable
475 public UserInfo createPassenger(@NonNull String name, @UserIdInt int driverId) {
476 checkManageUsersPermission("createPassenger");
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +0000477 Objects.requireNonNull(name, "name cannot be null");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700478 UserInfo driver = mUserManager.getUserInfo(driverId);
479 if (driver == null) {
480 Log.w(TAG_USER, "the driver is invalid");
481 return null;
482 }
483 if (driver.isGuest()) {
484 Log.w(TAG_USER, "a guest driver cannot create a passenger");
485 return null;
486 }
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700487 // createPassenger doesn't use user HAL because user HAL doesn't support profile user yet.
Bookatz42fb1a62019-10-30 11:45:01 -0700488 UserInfo user = mUserManager.createProfileForUser(name,
489 UserManager.USER_TYPE_PROFILE_MANAGED, /* flags */ 0, driverId);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700490 if (user == null) {
491 // Couldn't create user, most likely because there are too many.
492 Log.w(TAG_USER, "can't create a profile for user" + driverId);
493 return null;
494 }
495 // Passenger user should be a non-admin user.
Mayank Garge90a4082020-09-30 12:57:34 -0700496 UserHelper.setDefaultNonAdminRestrictions(mContext, user, /* enable= */ true);
Anthony Hugh6fed1e92019-10-22 16:22:03 -0700497 assignDefaultIcon(user);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700498 return user;
499 }
500
501 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700502 * @see ExperimentalCarUserManager.switchDriver
Eric Jeong1545f3b2019-09-16 13:56:52 -0700503 */
504 @Override
Eric Jeong25666cf2020-05-14 15:16:27 -0700505 public void switchDriver(@UserIdInt int driverId, AndroidFuture<UserSwitchResult> receiver) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700506 checkManageUsersPermission("switchDriver");
Mayank Garg94f3eb92020-08-12 12:38:58 -0700507 if (UserHelperLite.isHeadlessSystemUser(driverId)) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700508 // System user doesn't associate with real person, can not be switched to.
509 Log.w(TAG_USER, "switching to system user in headless system user mode is not allowed");
felipealdfdf8512020-06-01 09:35:45 -0700510 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_INVALID_REQUEST);
Eric Jeong25666cf2020-05-14 15:16:27 -0700511 return;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700512 }
513 int userSwitchable = mUserManager.getUserSwitchability();
514 if (userSwitchable != UserManager.SWITCHABILITY_STATUS_OK) {
515 Log.w(TAG_USER, "current process is not allowed to switch user");
felipealdfdf8512020-06-01 09:35:45 -0700516 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_INVALID_REQUEST);
Eric Jeong25666cf2020-05-14 15:16:27 -0700517 return;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700518 }
Eric Jeong25666cf2020-05-14 15:16:27 -0700519 switchUser(driverId, mHalTimeoutMs, receiver);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700520 }
521
522 /**
Eric Jeonge7916fc2019-12-20 14:03:34 -0800523 * Returns all drivers who can occupy the driving zone. Guest users are included in the list.
524 *
525 * @return the list of {@link UserInfo} who can be a driver on the device.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700526 */
527 @Override
528 @NonNull
529 public List<UserInfo> getAllDrivers() {
felipeal2d0483c2019-11-02 14:07:22 -0700530 checkManageUsersOrDumpPermission("getAllDrivers");
Mayank Garg94f3eb92020-08-12 12:38:58 -0700531 return getUsers((user) -> !UserHelperLite.isHeadlessSystemUser(user.id) && user.isEnabled()
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700532 && !user.isManagedProfile() && !user.isEphemeral());
Eric Jeong1545f3b2019-09-16 13:56:52 -0700533 }
534
535 /**
Eric Jeonge7916fc2019-12-20 14:03:34 -0800536 * Returns all passengers under the given driver.
537 *
538 * @param driverId User id of a driver.
539 * @return the list of {@link UserInfo} who is a passenger under the given driver.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700540 */
541 @Override
542 @NonNull
543 public List<UserInfo> getPassengers(@UserIdInt int driverId) {
felipeal2d0483c2019-11-02 14:07:22 -0700544 checkManageUsersOrDumpPermission("getPassengers");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700545 return getUsers((user) -> {
Mayank Garg94f3eb92020-08-12 12:38:58 -0700546 return !UserHelperLite.isHeadlessSystemUser(user.id) && user.isEnabled()
Eric Jeong40f8fa32020-05-12 12:23:33 -0700547 && user.isManagedProfile() && user.profileGroupId == driverId;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700548 });
549 }
550
551 /**
552 * @see CarUserManager.startPassenger
553 */
554 @Override
555 public boolean startPassenger(@UserIdInt int passengerId, int zoneId) {
556 checkManageUsersPermission("startPassenger");
Eric Jeongc91f9452019-08-30 15:04:21 -0700557 synchronized (mLockUser) {
558 try {
559 if (!mAm.startUserInBackgroundWithListener(passengerId, null)) {
560 Log.w(TAG_USER, "could not start passenger");
561 return false;
562 }
563 } catch (RemoteException e) {
564 // ignore
565 Log.w(TAG_USER, "error while starting passenger", e);
566 return false;
567 }
568 if (!assignUserToOccupantZone(passengerId, zoneId)) {
569 Log.w(TAG_USER, "could not assign passenger to zone");
570 return false;
571 }
572 mLastPassengerId = passengerId;
573 }
574 for (PassengerCallback callback : mPassengerCallbacks) {
575 callback.onPassengerStarted(passengerId, zoneId);
576 }
577 return true;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700578 }
579
580 /**
581 * @see CarUserManager.stopPassenger
582 */
583 @Override
584 public boolean stopPassenger(@UserIdInt int passengerId) {
585 checkManageUsersPermission("stopPassenger");
Eric Jeongc91f9452019-08-30 15:04:21 -0700586 return stopPassengerInternal(passengerId, true);
587 }
588
589 private boolean stopPassengerInternal(@UserIdInt int passengerId, boolean checkCurrentDriver) {
590 synchronized (mLockUser) {
591 UserInfo passenger = mUserManager.getUserInfo(passengerId);
592 if (passenger == null) {
593 Log.w(TAG_USER, "passenger " + passengerId + " doesn't exist");
594 return false;
595 }
596 if (mLastPassengerId != passengerId) {
597 Log.w(TAG_USER, "passenger " + passengerId + " hasn't been started");
598 return true;
599 }
600 if (checkCurrentDriver) {
601 int currentUser = ActivityManager.getCurrentUser();
602 if (passenger.profileGroupId != currentUser) {
603 Log.w(TAG_USER, "passenger " + passengerId
604 + " is not a profile of the current user");
605 return false;
606 }
607 }
608 // Passenger is a profile, so cannot be stopped through activity manager.
609 // Instead, activities started by the passenger are stopped and the passenger is
610 // unassigned from the zone.
611 stopAllTasks(passengerId);
612 if (!unassignUserFromOccupantZone(passengerId)) {
613 Log.w(TAG_USER, "could not unassign user from occupant zone");
614 return false;
615 }
616 mLastPassengerId = UserHandle.USER_NULL;
617 }
618 for (PassengerCallback callback : mPassengerCallbacks) {
619 callback.onPassengerStopped(passengerId);
620 }
621 return true;
622 }
623
624 private void stopAllTasks(@UserIdInt int userId) {
625 try {
Louis Chang3bf2f202020-08-18 13:04:28 +0800626 for (RootTaskInfo info : mAm.getAllRootTaskInfos()) {
627 for (int i = 0; i < info.childTaskIds.length; i++) {
628 if (info.childTaskUserIds[i] == userId) {
629 int taskId = info.childTaskIds[i];
Eric Jeongc91f9452019-08-30 15:04:21 -0700630 if (!mAm.removeTask(taskId)) {
631 Log.w(TAG_USER, "could not remove task " + taskId);
632 }
633 }
634 }
635 }
636 } catch (RemoteException e) {
637 Log.e(TAG_USER, "could not get stack info", e);
638 }
Eric Jeong1545f3b2019-09-16 13:56:52 -0700639 }
640
Felipe Leme5528ff72020-02-10 19:05:14 -0800641 @Override
642 public void setLifecycleListenerForUid(IResultReceiver listener) {
643 int uid = Binder.getCallingUid();
felipeal312416a2020-04-14 12:28:24 -0700644 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SET_LIFECYCLE_LISTENER, uid);
Felipe Leme5528ff72020-02-10 19:05:14 -0800645 checkInteractAcrossUsersPermission("setLifecycleListenerForUid" + uid);
646
647 try {
648 listener.asBinder().linkToDeath(() -> onListenerDeath(uid), 0);
649 } catch (RemoteException e) {
650 Log.wtf(TAG_USER, "Cannot listen to death of " + uid);
651 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700652 mHandler.post(() -> mAppLifecycleListeners.append(uid, listener));
Felipe Leme5528ff72020-02-10 19:05:14 -0800653 }
654
655 private void onListenerDeath(int uid) {
656 Log.i(TAG_USER, "Removing listeners for uid " + uid + " on binder death");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700657 mHandler.post(() -> mAppLifecycleListeners.remove(uid));
Felipe Leme5528ff72020-02-10 19:05:14 -0800658 }
659
660 @Override
661 public void resetLifecycleListenerForUid() {
662 int uid = Binder.getCallingUid();
felipeal312416a2020-04-14 12:28:24 -0700663 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_RESET_LIFECYCLE_LISTENER, uid);
Felipe Leme5528ff72020-02-10 19:05:14 -0800664 checkInteractAcrossUsersPermission("resetLifecycleListenerForUid-" + uid);
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700665 mHandler.post(() -> mAppLifecycleListeners.remove(uid));
Felipe Leme5528ff72020-02-10 19:05:14 -0800666 }
667
Felipe Lemee3cab982020-03-12 11:39:29 -0700668 /**
felipeal61ce3732020-04-03 11:01:00 -0700669 * Gets the initial foreground user after the device boots or resumes from suspension.
670 *
671 * <p>When the OEM supports the User HAL, the initial user won't be available until the HAL
672 * returns the initial value to {@code CarService} - if HAL takes too long or times out, this
673 * method returns {@code null}.
674 *
675 * <p>If the HAL eventually times out, {@code CarService} will fallback to its default behavior
676 * (like switching to the last active user), and this method will return the result of such
677 * operation.
678 *
679 * <p>Notice that if {@code CarService} crashes, subsequent calls to this method will return
680 * {@code null}.
681 *
682 * @hide
683 */
684 @Nullable
685 public UserInfo getInitialUser() {
686 checkInteractAcrossUsersPermission("getInitialUser");
687 synchronized (mLockUser) {
688 return mInitialUser;
689 }
690 }
691
felipeal61ce3732020-04-03 11:01:00 -0700692 /**
693 * Sets the initial foreground user after the device boots or resumes from suspension.
694 */
695 public void setInitialUser(@Nullable UserInfo user) {
felipeal312416a2020-04-14 12:28:24 -0700696 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SET_INITIAL_USER,
697 user == null ? UserHandle.USER_NULL : user.id);
felipeal61ce3732020-04-03 11:01:00 -0700698 synchronized (mLockUser) {
699 mInitialUser = user;
700 }
701 if (user == null) {
702 // This mean InitialUserSetter failed and could not fallback, so the initial user was
703 // not switched (and most likely is SYSTEM_USER).
704 // TODO(b/153104378): should we set it to ActivityManager.getCurrentUser() instead?
705 Log.wtf(TAG_USER, "Initial user set to null");
706 }
707 }
708
Mayank Garg7e1450b2020-08-07 18:15:15 -0700709 private void initResumeReplaceGuest() {
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700710 int currentUserId = ActivityManager.getCurrentUser();
711 UserInfo currentUser = mUserManager.getUserInfo(currentUserId);
712
713 if (!mInitialUserSetter.canReplaceGuestUser(currentUser)) return; // Not a guest
714
715 InitialUserInfo info =
716 new InitialUserSetter.Builder(InitialUserSetter.TYPE_REPLACE_GUEST).build();
717
718 mInitialUserSetter.set(info);
719 }
720
721 /**
Mayank Garg0baf88a2020-08-30 21:57:36 -0700722 * Calls to switch user at the power suspend.
Mayank Garg7e1450b2020-08-07 18:15:15 -0700723 *
724 * <p><b>Note:</b> Should be used only by {@link CarPowerManagementService}
725 *
Mayank Garg7e1450b2020-08-07 18:15:15 -0700726 */
Mayank Garg0baf88a2020-08-30 21:57:36 -0700727 public void onSuspend() {
Mayank Garg7e1450b2020-08-07 18:15:15 -0700728 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
Mayank Garg0baf88a2020-08-30 21:57:36 -0700729 Log.d(TAG_USER, "onSuspend called.");
Mayank Garg7e1450b2020-08-07 18:15:15 -0700730 }
731
Mayank Garg0baf88a2020-08-30 21:57:36 -0700732 if (mSwitchGuestUserBeforeSleep) {
733 initResumeReplaceGuest();
Mayank Garg7e1450b2020-08-07 18:15:15 -0700734 }
Mayank Garg1bb1c382020-09-03 17:11:11 -0700735
736 preCreateUsers();
Mayank Garg7e1450b2020-08-07 18:15:15 -0700737 }
738
739 /**
Mayank Garg0baf88a2020-08-30 21:57:36 -0700740 * Calls to switch user at the power resume.
741 *
742 * <p>
743 * <b>Note:</b> Should be used only by {@link CarPowerManagementService}
744 *
745 */
746 public void onResume() {
747 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
748 Log.d(TAG_USER, "onResume called.");
749 }
750
751 initBootUser(InitialUserInfoRequestType.RESUME);
752 }
753
754 /**
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700755 * Calls to start user at the android startup.
Mayank Garg70732a82020-08-05 20:17:47 -0700756 */
757 public void initBootUser() {
758 int requestType = getInitialUserInfoRequestType();
Mayank Garg7e1450b2020-08-07 18:15:15 -0700759 initBootUser(requestType);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700760 }
761
Mayank Garg7e1450b2020-08-07 18:15:15 -0700762 private void initBootUser(int requestType) {
763 boolean replaceGuest =
764 requestType == InitialUserInfoRequestType.RESUME && !mSwitchGuestUserBeforeSleep;
Mayank Garg70732a82020-08-05 20:17:47 -0700765 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_REQ, requestType,
766 mHalTimeoutMs);
767 checkManageUsersPermission("startInitialUser");
768
769 if (!isUserHalSupported()) {
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700770 fallbackToDefaultInitialUserBehavior(/* userLocales= */ null, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700771 return;
772 }
773
774 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
775 mHal.getInitialUserInfo(requestType, mHalTimeoutMs, usersInfo, (status, resp) -> {
776 if (resp != null) {
777 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_RESP,
778 status, resp.action, resp.userToSwitchOrCreate.userId,
779 resp.userToSwitchOrCreate.flags, resp.userNameToCreate, resp.userLocales);
780
781 String userLocales = resp.userLocales;
782 InitialUserInfo info;
783 switch (resp.action) {
784 case InitialUserInfoResponseAction.SWITCH:
785 int userId = resp.userToSwitchOrCreate.userId;
786 if (userId <= 0) {
787 Log.w(TAG, "invalid (or missing) user id sent by HAL: " + userId);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700788 fallbackToDefaultInitialUserBehavior(userLocales, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700789 break;
790 }
791 info = new InitialUserSetter.Builder(InitialUserSetter.TYPE_SWITCH)
792 .setUserLocales(userLocales)
793 .setSwitchUserId(userId)
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700794 .setReplaceGuest(replaceGuest)
Mayank Garg70732a82020-08-05 20:17:47 -0700795 .build();
796 mInitialUserSetter.set(info);
797 break;
798
799 case InitialUserInfoResponseAction.CREATE:
800 int halFlags = resp.userToSwitchOrCreate.flags;
801 String userName = resp.userNameToCreate;
802 info = new InitialUserSetter.Builder(InitialUserSetter.TYPE_CREATE)
803 .setUserLocales(userLocales)
804 .setNewUserName(userName)
805 .setNewUserFlags(halFlags)
806 .build();
807 mInitialUserSetter.set(info);
808 break;
809
810 case InitialUserInfoResponseAction.DEFAULT:
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700811 fallbackToDefaultInitialUserBehavior(userLocales, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700812 break;
813 default:
814 Log.w(TAG_USER, "invalid response action on " + resp);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700815 fallbackToDefaultInitialUserBehavior(/* user locale */ null, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700816 break;
817
818 }
819 } else {
820 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_RESP, status);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700821 fallbackToDefaultInitialUserBehavior(/* user locale */ null, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700822 }
823 });
824 }
825
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700826 private void fallbackToDefaultInitialUserBehavior(String userLocales, boolean replaceGuest) {
Mayank Garg70732a82020-08-05 20:17:47 -0700827 InitialUserInfo info = new InitialUserSetter.Builder(
828 InitialUserSetter.TYPE_DEFAULT_BEHAVIOR)
829 .setUserLocales(userLocales)
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700830 .setReplaceGuest(replaceGuest)
Mayank Garg70732a82020-08-05 20:17:47 -0700831 .build();
832 mInitialUserSetter.set(info);
833 }
834
835 @VisibleForTesting
836 int getInitialUserInfoRequestType() {
Mayank Garge90a4082020-09-30 12:57:34 -0700837 if (!mInitialUserSetter.hasInitialUser()) {
Mayank Garg70732a82020-08-05 20:17:47 -0700838 return InitialUserInfoRequestType.FIRST_BOOT;
839 }
840 if (mContext.getPackageManager().isDeviceUpgrading()) {
841 return InitialUserInfoRequestType.FIRST_BOOT_AFTER_OTA;
842 }
843 return InitialUserInfoRequestType.COLD_BOOT;
844 }
845
Felipe Leme5d5ab142020-10-27 13:49:10 -0700846 private boolean isUxRestricted() {
847 CarUxRestrictions restrictions = mUxRestrictionService.getCurrentUxRestrictions();
848 boolean restricted = restrictions != null
849 && (restrictions.getActiveRestrictions() & UX_RESTRICTIONS_NO_SETUP)
850 == UX_RESTRICTIONS_NO_SETUP;
851 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
852 Log.d(TAG_USER, "isUxRestricted(): restrictions=" + restrictions
853 + ", restricted=" + restricted);
854 }
855 return restricted;
856 }
857
Mayank Garg70732a82020-08-05 20:17:47 -0700858 /**
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700859 * Calls the {@link UserHalService} and {@link IActivityManager} for user switch.
860 *
861 * <p>
Mayank Gargb08f6772020-05-01 18:06:48 -0700862 * When everything works well, the workflow is:
863 * <ol>
864 * <li> {@link UserHalService} is called for HAL user switch with ANDROID_SWITCH request
865 * type, current user id, target user id, and a callback.
866 * <li> HAL called back with SUCCESS.
867 * <li> {@link IActivityManager} is called for Android user switch.
868 * <li> Receiver would receive {@code STATUS_SUCCESSFUL}.
869 * <li> Once user is unlocked, {@link UserHalService} is again called with ANDROID_POST_SWITCH
870 * request type, current user id, and target user id. In this case, the current and target
871 * user IDs would be same.
872 * <ol/>
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700873 *
874 * <p>
Mayank Gargb08f6772020-05-01 18:06:48 -0700875 * Corner cases:
876 * <ul>
877 * <li> If target user is already the current user, no user switch is performed and receiver
Mayank Gargef1b9332020-06-11 17:36:56 -0700878 * would receive {@code STATUS_OK_USER_ALREADY_IN_FOREGROUND} right away.
Mayank Gargb08f6772020-05-01 18:06:48 -0700879 * <li> If HAL user switch call fails, no Android user switch. Receiver would receive
880 * {@code STATUS_HAL_INTERNAL_FAILURE}.
881 * <li> If HAL user switch call is successful, but android user switch call fails,
882 * {@link UserHalService} is again called with request type POST_SWITCH, current user id, and
883 * target user id, but in this case the current and target user IDs would be different.
884 * <li> If another user switch request for the same target user is received while previous
885 * request is in process, receiver would receive
886 * {@code STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO} for the new request right away.
887 * <li> If a user switch request is received while another user switch request for different
888 * target user is in process, the previous request would be abandoned and new request will be
889 * processed. No POST_SWITCH would be sent for the previous request.
890 * <ul/>
Mayank Garg59f22192020-03-27 00:51:45 -0700891 *
Mayank Garge19c2922020-03-30 18:05:53 -0700892 * @param targetUserId - target user Id
Mayank Garg59f22192020-03-27 00:51:45 -0700893 * @param timeoutMs - timeout for HAL to wait
894 * @param receiver - receiver for the results
895 */
Mayank Garge19c2922020-03-30 18:05:53 -0700896 @Override
897 public void switchUser(@UserIdInt int targetUserId, int timeoutMs,
felipeale5bf0322020-04-16 15:10:57 -0700898 @NonNull AndroidFuture<UserSwitchResult> receiver) {
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700899 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_REQ, targetUserId, timeoutMs);
Felipe Leme17799202020-09-03 12:55:53 -0700900 checkManageOrCreateUsersPermission("switchUser");
Mayank Garge19c2922020-03-30 18:05:53 -0700901 Objects.requireNonNull(receiver);
902 UserInfo targetUser = mUserManager.getUserInfo(targetUserId);
felipealf7368962020-04-16 12:55:19 -0700903 Preconditions.checkArgument(targetUser != null, "Target user doesn't exist");
Mayank Garg7a114c82020-04-08 21:25:06 -0700904
felipealf7368962020-04-16 12:55:19 -0700905 int currentUser = ActivityManager.getCurrentUser();
906 if (currentUser == targetUserId) {
Mayank Garg0e239142020-04-14 19:16:31 -0700907 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
908 Log.d(TAG_USER, "Current user is same as requested target user: " + targetUserId);
909 }
Mayank Gargef1b9332020-06-11 17:36:56 -0700910 int resultStatus = UserSwitchResult.STATUS_OK_USER_ALREADY_IN_FOREGROUND;
felipealdfdf8512020-06-01 09:35:45 -0700911 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg0e239142020-04-14 19:16:31 -0700912 return;
913 }
914
Felipe Leme5d5ab142020-10-27 13:49:10 -0700915 if (isUxRestricted()) {
916 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_UX_RESTRICTION_FAILURE);
917 return;
918 }
919
Mayank Garg9ed099e2020-06-04 16:05:20 -0700920 // If User Hal is not supported, just android user switch.
921 if (!isUserHalSupported()) {
922 try {
923 if (mAm.switchUser(targetUserId)) {
924 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_SUCCESSFUL);
925 return;
926 }
927 } catch (RemoteException e) {
928 // ignore
929 Log.w(TAG_USER,
930 "error while switching user " + targetUser.toFullString(), e);
931 }
932 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_ANDROID_FAILURE);
933 return;
934 }
935
Mayank Garg7a114c82020-04-08 21:25:06 -0700936 synchronized (mLockUser) {
felipealf7368962020-04-16 12:55:19 -0700937 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
938 Log.d(TAG_USER, "switchUser(" + targetUserId + "): currentuser=" + currentUser
939 + ", mUserIdForUserSwitchInProcess=" + mUserIdForUserSwitchInProcess);
940 }
941
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700942 // If there is another request for the same target user, return another request in
943 // process, else {@link mUserIdForUserSwitchInProcess} is updated and {@link
944 // mRequestIdForUserSwitchInProcess} is reset. It is possible that there may be another
945 // user switch request in process for different target user, but that request is now
946 // ignored.
felipealf7368962020-04-16 12:55:19 -0700947 if (mUserIdForUserSwitchInProcess == targetUserId) {
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700948 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
949 Log.d(TAG_USER,
950 "Another user switch request in process for the requested target user: "
951 + targetUserId);
952 }
953
954 int resultStatus = UserSwitchResult.STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO;
felipealdfdf8512020-06-01 09:35:45 -0700955 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg7a114c82020-04-08 21:25:06 -0700956 return;
957 }
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700958 else {
959 mUserIdForUserSwitchInProcess = targetUserId;
960 mRequestIdForUserSwitchInProcess = 0;
961 }
Mayank Garg7a114c82020-04-08 21:25:06 -0700962 }
963
felipealdfdf8512020-06-01 09:35:45 -0700964 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
Mayank Gargeb37d092020-06-02 14:37:57 -0700965 SwitchUserRequest request = createUserSwitchRequest(targetUserId, usersInfo);
966
Felipe Leme5d5ab142020-10-27 13:49:10 -0700967 mHal.switchUser(request, timeoutMs, (halCallbackStatus, resp) -> {
felipealf7368962020-04-16 12:55:19 -0700968 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
969 Log.d(TAG, "switch response: status="
Felipe Leme5d5ab142020-10-27 13:49:10 -0700970 + UserHalHelper.halCallbackStatusToString(halCallbackStatus)
971 + ", resp=" + resp);
felipealf7368962020-04-16 12:55:19 -0700972 }
973
felipeale5bf0322020-04-16 15:10:57 -0700974 int resultStatus = UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE;
felipealf7368962020-04-16 12:55:19 -0700975
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700976 synchronized (mLockUser) {
Felipe Leme5d5ab142020-10-27 13:49:10 -0700977 if (halCallbackStatus != HalCallback.STATUS_OK) {
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700978 Log.w(TAG, "invalid callback status ("
Felipe Leme5d5ab142020-10-27 13:49:10 -0700979 + UserHalHelper.halCallbackStatusToString(halCallbackStatus)
980 + ") for response " + resp);
felipealdfdf8512020-06-01 09:35:45 -0700981 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700982 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
983 return;
984 }
felipealf7368962020-04-16 12:55:19 -0700985
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700986 if (mUserIdForUserSwitchInProcess != targetUserId) {
987 // Another user switch request received while HAL responded. No need to process
988 // this request further
989 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
990 Log.d(TAG_USER, "Another user switch received while HAL responsed. Request "
991 + "abondoned for : " + targetUserId + ". Current user in process: "
992 + mUserIdForUserSwitchInProcess);
felipealf7368962020-04-16 12:55:19 -0700993 }
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700994 resultStatus =
995 UserSwitchResult.STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST;
felipealdfdf8512020-06-01 09:35:45 -0700996 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700997 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
998 return;
999 }
1000
1001 switch (resp.status) {
1002 case SwitchUserStatus.SUCCESS:
1003 boolean switched;
1004 try {
1005 switched = mAm.switchUser(targetUserId);
1006 if (switched) {
Mayank Garg587f1942020-05-06 01:41:34 -07001007 sendUserSwitchUiCallback(targetUserId);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001008 resultStatus = UserSwitchResult.STATUS_SUCCESSFUL;
1009 mRequestIdForUserSwitchInProcess = resp.requestId;
1010 } else {
1011 resultStatus = UserSwitchResult.STATUS_ANDROID_FAILURE;
1012 postSwitchHalResponse(resp.requestId, targetUserId);
1013 }
1014 } catch (RemoteException e) {
1015 // ignore
1016 Log.w(TAG_USER,
1017 "error while switching user " + targetUser.toFullString(), e);
1018 }
1019 break;
1020 case SwitchUserStatus.FAILURE:
1021 // HAL failed to switch user
1022 resultStatus = UserSwitchResult.STATUS_HAL_FAILURE;
1023 break;
felipealdfdf8512020-06-01 09:35:45 -07001024 default:
1025 // Shouldn't happen because UserHalService validates the status
1026 Log.wtf(TAG, "Received invalid user switch status from HAL: " + resp);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001027 }
1028
1029 if (mRequestIdForUserSwitchInProcess == 0) {
1030 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
1031 }
Mayank Garg59f22192020-03-27 00:51:45 -07001032 }
Felipe Leme5d5ab142020-10-27 13:49:10 -07001033 sendUserSwitchResult(receiver, halCallbackStatus, resultStatus, resp.errorMessage);
Mayank Garg59f22192020-03-27 00:51:45 -07001034 });
1035 }
1036
Mayank Garga55c3092020-05-28 03:19:24 -07001037 @Override
Felipe Leme55236722020-10-16 16:54:32 -07001038 public UserRemovalResult removeUser(@UserIdInt int userId) {
1039 return removeUser(userId, /* hasCallerRestrictions= */ false);
1040 }
1041
1042 /**
1043 * Internal implementation of {@code removeUser()}, which is used by both
1044 * {@code ICarUserService} and {@code ICarDevicePolicyService}.
1045 *
1046 * @param userId user to be removed
1047 * @param hasCallerRestrictions when {@code true}, if the caller user is not an admin, it can
1048 * only remove itself.
1049 *
1050 * @return result of the operation.
1051 */
Felipe Lemee5bb26b2020-10-26 15:49:17 -07001052 public UserRemovalResult removeUser(@UserIdInt int userId, boolean hasCallerRestrictions) {
Felipe Leme17799202020-09-03 12:55:53 -07001053 checkManageOrCreateUsersPermission("removeUser");
Felipe Leme55236722020-10-16 16:54:32 -07001054 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_REMOVE_USER_REQ, userId,
1055 hasCallerRestrictions ? 1 : 0);
Felipe Lemee5bb26b2020-10-26 15:49:17 -07001056
Mayank Garga55c3092020-05-28 03:19:24 -07001057 // If the requested user is the current user, return error.
1058 if (ActivityManager.getCurrentUser() == userId) {
1059 return logAndGetResults(userId,
1060 UserRemovalResult.STATUS_TARGET_USER_IS_CURRENT_USER);
1061 }
1062
1063 // If requested user is the only admin user, return error.
1064 UserInfo userInfo = mUserManager.getUserInfo(userId);
1065 if (userInfo == null) {
1066 return logAndGetResults(userId, UserRemovalResult.STATUS_USER_DOES_NOT_EXIST);
1067 }
1068
Felipe Lemee5bb26b2020-10-26 15:49:17 -07001069 if (hasCallerRestrictions) {
1070 // Restrictions: non-admin user can only remove itself, admins have no restrictions
1071 int callingUserId = Binder.getCallingUserHandle().getIdentifier();
1072 UserInfo callingUser = mUserManager.getUserInfo(callingUserId);
1073 if (!callingUser.isAdmin() && userId != callingUserId) {
1074 throw new SecurityException("Non-admin user " + callingUserId
1075 + " can only remove itself");
1076 }
1077 }
1078
Mayank Garga55c3092020-05-28 03:19:24 -07001079 android.hardware.automotive.vehicle.V2_0.UserInfo halUser =
1080 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1081 halUser.userId = userInfo.id;
1082 halUser.flags = UserHalHelper.convertFlags(userInfo);
1083 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1084
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001085 // check if the user is last admin user.
1086 boolean isLastAdmin = false;
Mayank Garga55c3092020-05-28 03:19:24 -07001087 if (UserHalHelper.isAdmin(halUser.flags)) {
1088 int size = usersInfo.existingUsers.size();
1089 int totalAdminUsers = 0;
1090 for (int i = 0; i < size; i++) {
1091 if (UserHalHelper.isAdmin(usersInfo.existingUsers.get(i).flags)) {
1092 totalAdminUsers++;
1093 }
1094 }
1095 if (totalAdminUsers == 1) {
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001096 isLastAdmin = true;
Mayank Garga55c3092020-05-28 03:19:24 -07001097 }
1098 }
1099
1100 // First remove user from android and then remove from HAL because HAL remove user is one
1101 // way call.
1102 if (!mUserManager.removeUser(userId)) {
1103 return logAndGetResults(userId, UserRemovalResult.STATUS_ANDROID_FAILURE);
1104 }
1105
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001106 if (isLastAdmin) {
1107 Log.w(TAG_USER, "Last admin user successfully removed. User Id: " + userId);
1108 }
1109
1110 return logAndGetResults(userId,
1111 isLastAdmin ? UserRemovalResult.STATUS_SUCCESSFUL_LAST_ADMIN_REMOVED
1112 : UserRemovalResult.STATUS_SUCCESSFUL);
Mayank Garga55c3092020-05-28 03:19:24 -07001113 }
1114
Felipe Leme6b34fc32020-10-26 15:49:17 -07001115 private void notifyHalUserRemoved(@UserIdInt int userId) {
1116 if (!isUserHalSupported()) return;
1117
1118 if (userId == UserHandle.USER_NULL) {
1119 Log.wtf(TAG, "notifyHalUserRemoved() Called for UserHandle.USER_NULL");
1120 return;
1121 }
1122
1123 synchronized (mLockUser) {
1124 if (mFailedToCreateUserIds.get(userId)) {
1125 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1126 Log.d(TAG, "notifyHalUserRemoved(): skipping " + userId);
1127 }
1128 mFailedToCreateUserIds.delete(userId);
1129 return;
1130 }
1131 }
1132
1133 android.hardware.automotive.vehicle.V2_0.UserInfo halUser =
1134 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1135 halUser.userId = userId;
1136 // TODO(b/155913815): per the REMOVE_USER API, the userFlags should be set as well, but it's
1137 // gone. We'll need to either update the documentation, or if that's not possible (as it's
1138 // breaking the contract), either change the intent to contain the flags, or keep track of
1139 // the flags internally.
1140
1141 RemoveUserRequest request = new RemoveUserRequest();
1142 request.removedUserInfo = halUser;
1143 request.usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1144 mHal.removeUser(request);
1145 }
1146
Mayank Garga55c3092020-05-28 03:19:24 -07001147 private UserRemovalResult logAndGetResults(@UserIdInt int userId,
1148 @UserRemovalResult.Status int result) {
1149 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_REMOVE_USER_RESP, userId, result);
1150 return new UserRemovalResult(result);
1151 }
1152
Mayank Garg587f1942020-05-06 01:41:34 -07001153 private void sendUserSwitchUiCallback(@UserIdInt int targetUserId) {
1154 if (mUserSwitchUiReceiver == null) {
1155 Log.w(TAG_USER, "No User switch UI receiver.");
1156 return;
1157 }
1158
felipealdfdf8512020-06-01 09:35:45 -07001159 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_UI_REQ, targetUserId);
Mayank Garg587f1942020-05-06 01:41:34 -07001160 try {
Mayank Garg587f1942020-05-06 01:41:34 -07001161 mUserSwitchUiReceiver.send(targetUserId, null);
1162 } catch (RemoteException e) {
1163 Log.e(TAG_USER, "Error calling user switch UI receiver.", e);
1164 }
1165 }
1166
felipeal5e3ede42020-04-23 18:04:07 -07001167 @Override
felipealdfdf8512020-06-01 09:35:45 -07001168 public void createUser(@Nullable String name, @NonNull String userType, @UserInfoFlag int flags,
1169 int timeoutMs, @NonNull AndroidFuture<UserCreationResult> receiver) {
Felipe Leme8c888ab2020-11-02 17:39:52 -08001170 createUser(name, userType, flags, timeoutMs, receiver, /* hasCallerRestrictions= */ false);
1171 }
1172
1173 /**
1174 * Internal implementation of {@code createUser()}, which is used by both
1175 * {@code ICarUserService} and {@code ICarDevicePolicyService}.
1176 *
1177 * @param hasCallerRestrictions when {@code true}, if the caller user is not an admin, it can
1178 * only create admin users
1179 */
1180 public void createUser(@Nullable String name, @NonNull String userType, @UserInfoFlag int flags,
1181 int timeoutMs, @NonNull AndroidFuture<UserCreationResult> receiver,
1182 boolean hasCallerRestrictions) {
felipealdfdf8512020-06-01 09:35:45 -07001183 Objects.requireNonNull(userType, "user type cannot be null");
1184 Objects.requireNonNull(receiver, "receiver cannot be null");
Felipe Leme17799202020-09-03 12:55:53 -07001185 checkManageOrCreateUsersPermission(flags);
1186
Mayank Garg94f3eb92020-08-12 12:38:58 -07001187 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_REQ,
Felipe Leme8c888ab2020-11-02 17:39:52 -08001188 UserHelperLite.safeName(name), userType, flags, timeoutMs,
1189 hasCallerRestrictions ? 1 : 0);
1190
1191 if (hasCallerRestrictions) {
1192 // Restrictions:
1193 // - type/flag can only be normal user, admin, or guest
1194 // - non-admin user can only create non-admin users
1195
1196 boolean validCombination;
1197 switch (userType) {
1198 case UserManager.USER_TYPE_FULL_SECONDARY:
1199 validCombination = flags == 0
1200 || (flags & UserInfo.FLAG_ADMIN) == UserInfo.FLAG_ADMIN;
1201 break;
1202 case UserManager.USER_TYPE_FULL_GUEST:
1203 validCombination = flags == 0;
1204 break;
1205 default:
1206 validCombination = false;
1207 }
1208 if (!validCombination) {
Felipe Leme71d296f2020-11-04 12:11:42 -08001209 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1210 Log.d(TAG, "Invalid combination of user type(" + userType
1211 + ") and flags (" + UserInfo.flagsToString(flags)
1212 + ") for caller with restrictions");
1213 }
1214 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_INVALID_REQUEST);
1215 return;
1216
Felipe Leme8c888ab2020-11-02 17:39:52 -08001217 }
1218
1219 int callingUserId = Binder.getCallingUserHandle().getIdentifier();
1220 UserInfo callingUser = mUserManager.getUserInfo(callingUserId);
1221 if (!callingUser.isAdmin() && (flags & UserInfo.FLAG_ADMIN) == UserInfo.FLAG_ADMIN) {
Felipe Leme71d296f2020-11-04 12:11:42 -08001222 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1223 Log.d(TAG, "Non-admin user " + callingUserId
1224 + " can only create non-admin users");
1225 }
1226 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_INVALID_REQUEST);
1227 return;
Felipe Leme8c888ab2020-11-02 17:39:52 -08001228 }
Felipe Leme71d296f2020-11-04 12:11:42 -08001229
Felipe Leme8c888ab2020-11-02 17:39:52 -08001230 }
felipealdfdf8512020-06-01 09:35:45 -07001231
1232 UserInfo newUser;
1233 try {
1234 newUser = mUserManager.createUser(name, userType, flags);
1235 if (newUser == null) {
1236 Log.w(TAG, "um.createUser() returned null for user of type " + userType
1237 + " and flags " + UserInfo.flagsToString(flags));
1238 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_ANDROID_FAILURE);
1239 return;
1240 }
1241 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1242 Log.d(TAG, "Created user: " + newUser.toFullString());
1243 }
1244 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_USER_CREATED, newUser.id,
Mayank Garg94f3eb92020-08-12 12:38:58 -07001245 UserHelperLite.safeName(newUser.name), newUser.userType, newUser.flags);
felipealdfdf8512020-06-01 09:35:45 -07001246 } catch (RuntimeException e) {
1247 Log.e(TAG_USER, "Error creating user of type " + userType + " and flags"
1248 + UserInfo.flagsToString(flags), e);
1249 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_ANDROID_FAILURE);
1250 return;
1251 }
1252
Mayank Garg9ed099e2020-06-04 16:05:20 -07001253 if (!isUserHalSupported()) {
1254 sendUserCreationResult(receiver, UserCreationResult.STATUS_SUCCESSFUL, newUser, null);
1255 return;
1256 }
1257
felipealdfdf8512020-06-01 09:35:45 -07001258 CreateUserRequest request = new CreateUserRequest();
1259 request.usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1260 if (!TextUtils.isEmpty(name)) {
1261 request.newUserName = name;
1262 }
1263 request.newUserInfo.userId = newUser.id;
1264 request.newUserInfo.flags = UserHalHelper.convertFlags(newUser);
1265 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1266 Log.d(TAG, "Create user request: " + request);
1267 }
1268
1269 try {
1270 mHal.createUser(request, timeoutMs, (status, resp) -> {
1271 int resultStatus = UserCreationResult.STATUS_HAL_INTERNAL_FAILURE;
1272 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1273 Log.d(TAG, "createUserResponse: status="
1274 + UserHalHelper.halCallbackStatusToString(status) + ", resp=" + resp);
1275 }
1276 UserInfo user = null; // user returned in the result
1277 if (status != HalCallback.STATUS_OK) {
1278 Log.w(TAG, "invalid callback status ("
1279 + UserHalHelper.halCallbackStatusToString(status) + ") for response "
1280 + resp);
1281 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_RESP, status,
1282 resultStatus, resp.errorMessage);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001283 removeCreatedUser(newUser, "HAL call failed with "
felipealdfdf8512020-06-01 09:35:45 -07001284 + UserHalHelper.halCallbackStatusToString(status));
1285 sendUserCreationResult(receiver, resultStatus, user, /* errorMsg= */ null);
1286 return;
1287 }
1288
1289 switch (resp.status) {
1290 case CreateUserStatus.SUCCESS:
1291 resultStatus = UserCreationResult.STATUS_SUCCESSFUL;
1292 user = newUser;
1293 break;
1294 case CreateUserStatus.FAILURE:
1295 // HAL failed to switch user
1296 resultStatus = UserCreationResult.STATUS_HAL_FAILURE;
1297 break;
1298 default:
1299 // Shouldn't happen because UserHalService validates the status
1300 Log.wtf(TAG, "Received invalid user switch status from HAL: " + resp);
1301 }
1302 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_RESP, status,
1303 resultStatus, resp.errorMessage);
1304 if (user == null) {
Felipe Leme6b34fc32020-10-26 15:49:17 -07001305 removeCreatedUser(newUser, "HAL returned "
felipealdfdf8512020-06-01 09:35:45 -07001306 + UserCreationResult.statusToString(resultStatus));
1307 }
1308 sendUserCreationResult(receiver, resultStatus, user, resp.errorMessage);
1309 });
1310 } catch (Exception e) {
1311 Log.w(TAG, "mHal.createUser(" + request + ") failed", e);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001312 removeCreatedUser(newUser, "mHal.createUser() failed");
felipealdfdf8512020-06-01 09:35:45 -07001313 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_HAL_INTERNAL_FAILURE);
1314 }
1315 }
1316
Felipe Leme6b34fc32020-10-26 15:49:17 -07001317 private void removeCreatedUser(@NonNull UserInfo user, @NonNull String reason) {
1318 int userId = user.id;
1319 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_USER_REMOVED, userId, reason);
1320
1321 synchronized (mLockUser) {
1322 mFailedToCreateUserIds.put(userId, true);
1323 }
1324
felipealdfdf8512020-06-01 09:35:45 -07001325 try {
Felipe Leme6b34fc32020-10-26 15:49:17 -07001326 if (!mUserManager.removeUser(userId)) {
felipealdfdf8512020-06-01 09:35:45 -07001327 Log.w(TAG, "Failed to remove user " + user.toFullString());
1328 }
1329 } catch (Exception e) {
1330 Log.e(TAG, "Failed to remove user " + user.toFullString(), e);
1331 }
1332 }
1333
1334 @Override
felipeal159a2a42020-05-08 10:32:11 -07001335 public UserIdentificationAssociationResponse getUserIdentificationAssociation(int[] types) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001336 if (!isUserHalUserAssociationSupported()) {
1337 return UserIdentificationAssociationResponse.forFailure(VEHICLE_HAL_NOT_SUPPORTED);
1338 }
1339
felipeal5e3ede42020-04-23 18:04:07 -07001340 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type");
Felipe Leme17799202020-09-03 12:55:53 -07001341 checkManageOrCreateUsersPermission("getUserIdentificationAssociation");
felipeal5e3ede42020-04-23 18:04:07 -07001342
1343 int uid = getCallingUid();
1344 int userId = UserHandle.getUserId(uid);
1345 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_GET_USER_AUTH_REQ, uid, userId);
1346
1347 UserIdentificationGetRequest request = new UserIdentificationGetRequest();
1348 request.userInfo.userId = userId;
1349 request.userInfo.flags = getHalUserInfoFlags(userId);
1350
1351 request.numberAssociationTypes = types.length;
1352 for (int i = 0; i < types.length; i++) {
1353 request.associationTypes.add(types[i]);
1354 }
1355
1356 UserIdentificationResponse halResponse = mHal.getUserAssociation(request);
1357 if (halResponse == null) {
1358 Log.w(TAG, "getUserIdentificationAssociation(): HAL returned null for "
1359 + Arrays.toString(types));
felipeal159a2a42020-05-08 10:32:11 -07001360 return UserIdentificationAssociationResponse.forFailure();
felipeal5e3ede42020-04-23 18:04:07 -07001361 }
1362
1363 int[] values = new int[halResponse.associations.size()];
1364 for (int i = 0; i < values.length; i++) {
1365 values[i] = halResponse.associations.get(i).value;
1366 }
1367 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_GET_USER_AUTH_RESP, values.length);
1368
felipeal159a2a42020-05-08 10:32:11 -07001369 return UserIdentificationAssociationResponse.forSuccess(values, halResponse.errorMessage);
1370 }
1371
1372 @Override
1373 public void setUserIdentificationAssociation(int timeoutMs, int[] types, int[] values,
1374 AndroidFuture<UserIdentificationAssociationResponse> result) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001375 if (!isUserHalUserAssociationSupported()) {
1376 result.complete(
1377 UserIdentificationAssociationResponse.forFailure(VEHICLE_HAL_NOT_SUPPORTED));
1378 return;
1379 }
1380
felipeal159a2a42020-05-08 10:32:11 -07001381 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type");
1382 Preconditions.checkArgument(!ArrayUtils.isEmpty(values), "must have at least one value");
1383 if (types.length != values.length) {
1384 throw new IllegalArgumentException("types (" + Arrays.toString(types) + ") and values ("
1385 + Arrays.toString(values) + ") should have the same length");
1386 }
Felipe Leme17799202020-09-03 12:55:53 -07001387 checkManageOrCreateUsersPermission("setUserIdentificationAssociation");
felipeal159a2a42020-05-08 10:32:11 -07001388
1389 int uid = getCallingUid();
1390 int userId = UserHandle.getUserId(uid);
1391 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_REQ, uid, userId, types.length);
1392
1393 UserIdentificationSetRequest request = new UserIdentificationSetRequest();
1394 request.userInfo.userId = userId;
1395 request.userInfo.flags = getHalUserInfoFlags(userId);
1396
1397 request.numberAssociations = types.length;
1398 for (int i = 0; i < types.length; i++) {
1399 UserIdentificationSetAssociation association = new UserIdentificationSetAssociation();
1400 association.type = types[i];
1401 association.value = values[i];
1402 request.associations.add(association);
1403 }
1404
1405 mHal.setUserAssociation(timeoutMs, request, (status, resp) -> {
1406 if (status != HalCallback.STATUS_OK) {
1407 Log.w(TAG, "setUserIdentificationAssociation(): invalid callback status ("
1408 + UserHalHelper.halCallbackStatusToString(status) + ") for response "
1409 + resp);
1410 if (resp == null || TextUtils.isEmpty(resp.errorMessage)) {
1411 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, 0);
1412 result.complete(UserIdentificationAssociationResponse.forFailure());
1413 return;
1414 }
1415 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, 0,
1416 resp.errorMessage);
1417 result.complete(
1418 UserIdentificationAssociationResponse.forFailure(resp.errorMessage));
1419 return;
1420 }
1421 int respSize = resp.associations.size();
1422 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, respSize,
1423 resp.errorMessage);
1424
1425 int[] responseTypes = new int[respSize];
1426 for (int i = 0; i < respSize; i++) {
1427 responseTypes[i] = resp.associations.get(i).value;
1428 }
1429 UserIdentificationAssociationResponse response = UserIdentificationAssociationResponse
1430 .forSuccess(responseTypes, resp.errorMessage);
1431 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1432 Log.d(TAG, "setUserIdentificationAssociation(): resp= " + resp
1433 + ", converted=" + response);
1434 }
1435 result.complete(response);
1436 });
felipeal5e3ede42020-04-23 18:04:07 -07001437 }
1438
1439 /**
1440 * Gets the User HAL flags for the given user.
1441 *
1442 * @throws IllegalArgumentException if the user does not exist.
1443 */
1444 private int getHalUserInfoFlags(@UserIdInt int userId) {
1445 UserInfo user = mUserManager.getUserInfo(userId);
1446 Preconditions.checkArgument(user != null, "no user for id %d", userId);
1447 return UserHalHelper.convertFlags(user);
1448 }
1449
Mayank Garg0e239142020-04-14 19:16:31 -07001450 private void sendResult(@NonNull IResultReceiver receiver, int resultCode,
1451 @Nullable Bundle resultData) {
1452 try {
1453 receiver.send(resultCode, resultData);
1454 } catch (RemoteException e) {
1455 // ignore
1456 Log.w(TAG_USER, "error while sending results", e);
1457 }
1458 }
1459
felipealdfdf8512020-06-01 09:35:45 -07001460 private void sendUserSwitchResult(@NonNull AndroidFuture<UserSwitchResult> receiver,
Felipe Leme5d5ab142020-10-27 13:49:10 -07001461 @UserSwitchResult.Status int userSwitchStatus) {
1462 sendUserSwitchResult(receiver, HalCallback.STATUS_INVALID, userSwitchStatus,
1463 /* errorMessage= */ null);
felipeale5bf0322020-04-16 15:10:57 -07001464 }
1465
felipealdfdf8512020-06-01 09:35:45 -07001466 private void sendUserSwitchResult(@NonNull AndroidFuture<UserSwitchResult> receiver,
Felipe Leme5d5ab142020-10-27 13:49:10 -07001467 @HalCallback.HalCallbackStatus int halCallbackStatus,
1468 @UserSwitchResult.Status int userSwitchStatus, @Nullable String errorMessage) {
1469 if (errorMessage != null) {
1470 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_RESP, halCallbackStatus,
1471 userSwitchStatus, errorMessage);
1472 } else {
1473 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_RESP, halCallbackStatus,
1474 userSwitchStatus);
1475 }
1476 receiver.complete(new UserSwitchResult(userSwitchStatus, errorMessage));
felipeale5bf0322020-04-16 15:10:57 -07001477 }
1478
felipealdfdf8512020-06-01 09:35:45 -07001479 private void sendUserCreationResultFailure(@NonNull AndroidFuture<UserCreationResult> receiver,
1480 @UserCreationResult.Status int status) {
1481 sendUserCreationResult(receiver, status, /* user= */ null, /* errorMessage= */ null);
1482 }
1483
1484 private void sendUserCreationResult(@NonNull AndroidFuture<UserCreationResult> receiver,
1485 @UserCreationResult.Status int status, @NonNull UserInfo user,
1486 @Nullable String errorMessage) {
1487 if (TextUtils.isEmpty(errorMessage)) {
1488 errorMessage = null;
1489 }
1490 receiver.complete(new UserCreationResult(status, user, errorMessage));
1491 }
1492
Mayank Garg6307fe42020-04-15 23:09:03 -07001493 /**
1494 * Calls activity manager for user switch.
1495 *
1496 * <p><b>NOTE</b> This method is meant to be called just by UserHalService.
1497 *
1498 * @param requestId for the user switch request
1499 * @param targetUserId of the target user
1500 *
1501 * @hide
1502 */
1503 public void switchAndroidUserFromHal(int requestId, @UserIdInt int targetUserId) {
1504 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_FROM_HAL_REQ, requestId,
1505 targetUserId);
1506 Log.i(TAG_USER, "User hal requested a user switch. Target user id " + targetUserId);
1507
1508 try {
1509 boolean result = mAm.switchUser(targetUserId);
1510 if (result) {
1511 updateUserSwitchInProcess(requestId, targetUserId);
1512 } else {
1513 postSwitchHalResponse(requestId, targetUserId);
1514 }
1515 } catch (RemoteException e) {
1516 // ignore
1517 Log.w(TAG_USER, "error while switching user " + targetUserId, e);
1518 }
1519 }
1520
1521 private void updateUserSwitchInProcess(int requestId, @UserIdInt int targetUserId) {
1522 synchronized (mLockUser) {
1523 if (mUserIdForUserSwitchInProcess != UserHandle.USER_NULL) {
1524 // Some other user switch is in process.
1525 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1526 Log.d(TAG_USER, "User switch for user: " + mUserIdForUserSwitchInProcess
1527 + " is in process. Abandoning it as a new user switch is requested"
1528 + " for the target user: " + targetUserId);
1529 }
1530 }
1531 mUserIdForUserSwitchInProcess = targetUserId;
1532 mRequestIdForUserSwitchInProcess = requestId;
1533 }
1534 }
Mayank Garg9ed099e2020-06-04 16:05:20 -07001535
Mayank Garg7a114c82020-04-08 21:25:06 -07001536 private void postSwitchHalResponse(int requestId, @UserIdInt int targetUserId) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001537 if (!isUserHalSupported()) return;
1538
felipealdfdf8512020-06-01 09:35:45 -07001539 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
Mayank Gargeb37d092020-06-02 14:37:57 -07001540 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_POST_SWITCH_USER_REQ, requestId,
1541 targetUserId, usersInfo.currentUser.userId);
1542 SwitchUserRequest request = createUserSwitchRequest(targetUserId, usersInfo);
1543 request.requestId = requestId;
1544 mHal.postSwitchResponse(request);
1545 }
1546
1547 private SwitchUserRequest createUserSwitchRequest(@UserIdInt int targetUserId,
1548 @NonNull UsersInfo usersInfo) {
1549 UserInfo targetUser = mUserManager.getUserInfo(targetUserId);
Mayank Garg7a114c82020-04-08 21:25:06 -07001550 android.hardware.automotive.vehicle.V2_0.UserInfo halTargetUser =
1551 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1552 halTargetUser.userId = targetUser.id;
1553 halTargetUser.flags = UserHalHelper.convertFlags(targetUser);
Mayank Gargeb37d092020-06-02 14:37:57 -07001554 SwitchUserRequest request = new SwitchUserRequest();
1555 request.targetUser = halTargetUser;
1556 request.usersInfo = usersInfo;
1557 return request;
Mayank Garg7a114c82020-04-08 21:25:06 -07001558 }
1559
Mayank Garg59f22192020-03-27 00:51:45 -07001560 /**
Felipe Lemee3cab982020-03-12 11:39:29 -07001561 * Checks if the User HAL is supported.
1562 */
1563 public boolean isUserHalSupported() {
1564 return mHal.isSupported();
1565 }
1566
Mayank Garg587f1942020-05-06 01:41:34 -07001567 /**
Mayank Garg9ed099e2020-06-04 16:05:20 -07001568 * Checks if the User HAL user association is supported.
1569 */
1570 @Override
1571 public boolean isUserHalUserAssociationSupported() {
1572 return mHal.isUserAssociationSupported();
1573 }
1574
1575 /**
Mayank Garg587f1942020-05-06 01:41:34 -07001576 * Sets a callback which is invoked before user switch.
1577 *
1578 * <p>
1579 * This method should only be called by the Car System UI. The purpose of this call is to notify
1580 * Car System UI to show the user switch UI before the user switch.
1581 */
1582 @Override
1583 public void setUserSwitchUiCallback(@NonNull IResultReceiver receiver) {
Yan Zhu67a383e2020-05-11 20:46:24 -07001584 checkManageUsersPermission("setUserSwitchUiCallback");
Mayank Garga480dd92020-05-14 03:14:57 -07001585
1586 // Confirm that caller is system UI.
1587 String systemUiPackageName = getSystemUiPackageName();
1588 if (systemUiPackageName == null) {
1589 throw new IllegalStateException("System UI package not found.");
1590 }
1591
1592 try {
1593 int systemUiUid = mContext
1594 .createContextAsUser(UserHandle.SYSTEM, /* flags= */ 0).getPackageManager()
1595 .getPackageUid(systemUiPackageName, PackageManager.MATCH_SYSTEM_ONLY);
1596 int callerUid = Binder.getCallingUid();
1597 if (systemUiUid != callerUid) {
1598 throw new SecurityException("Invalid caller. Only" + systemUiPackageName
1599 + " is allowed to make this call");
1600 }
1601 } catch (NameNotFoundException e) {
1602 throw new IllegalStateException("Package " + systemUiPackageName + " not found.");
1603 }
1604
Mayank Garg587f1942020-05-06 01:41:34 -07001605 mUserSwitchUiReceiver = receiver;
1606 }
1607
Mayank Garga480dd92020-05-14 03:14:57 -07001608 // TODO(157082995): This information can be taken from
1609 // PackageManageInternalImpl.getSystemUiServiceComponent
1610 @Nullable
1611 private String getSystemUiPackageName() {
1612 try {
1613 ComponentName componentName = ComponentName.unflattenFromString(mContext.getResources()
1614 .getString(com.android.internal.R.string.config_systemUIServiceComponent));
1615 return componentName.getPackageName();
1616 } catch (RuntimeException e) {
1617 Log.w(TAG_USER, "error while getting system UI package name.", e);
1618 return null;
1619 }
1620 }
1621
Keun young Park13a7a822019-04-04 15:53:08 -07001622 private void updateDefaultUserRestriction() {
1623 // We want to set restrictions on system and guest users only once. These are persisted
1624 // onto disk, so it's sufficient to do it once + we minimize the number of disk writes.
1625 if (Settings.Global.getInt(mContext.getContentResolver(),
Eric Jeong1545f3b2019-09-16 13:56:52 -07001626 CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, /* default= */ 0) != 0) {
1627 return;
Keun young Park13a7a822019-04-04 15:53:08 -07001628 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07001629 // Only apply the system user restrictions if the system user is headless.
1630 if (UserManager.isHeadlessSystemUserMode()) {
1631 setSystemUserRestrictions();
1632 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07001633 Settings.Global.putInt(mContext.getContentResolver(),
1634 CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, 1);
Keun young Park13a7a822019-04-04 15:53:08 -07001635 }
1636
Eric Jeong1545f3b2019-09-16 13:56:52 -07001637 private boolean isPersistentUser(@UserIdInt int userId) {
Anthony Hugh9932a252019-06-12 16:19:56 -07001638 return !mUserManager.getUserInfo(userId).isEphemeral();
1639 }
1640
Antonio Kantekc8114752020-03-05 21:37:39 -08001641 /**
Antonio Kantekc8114752020-03-05 21:37:39 -08001642 * Adds a new {@link UserLifecycleListener} to listen to user activity events.
1643 */
1644 public void addUserLifecycleListener(@NonNull UserLifecycleListener listener) {
1645 Objects.requireNonNull(listener, "listener cannot be null");
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001646 mHandler.post(() -> mUserLifecycleListeners.add(listener));
Antonio Kantekc8114752020-03-05 21:37:39 -08001647 }
1648
1649 /**
1650 * Removes previously added {@link UserLifecycleListener}.
1651 */
1652 public void removeUserLifecycleListener(@NonNull UserLifecycleListener listener) {
1653 Objects.requireNonNull(listener, "listener cannot be null");
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001654 mHandler.post(() -> mUserLifecycleListeners.remove(listener));
Antonio Kantekc8114752020-03-05 21:37:39 -08001655 }
1656
Eric Jeongc91f9452019-08-30 15:04:21 -07001657 /** Adds callback to listen to passenger activity events. */
1658 public void addPassengerCallback(@NonNull PassengerCallback callback) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00001659 Objects.requireNonNull(callback, "callback cannot be null");
Eric Jeongc91f9452019-08-30 15:04:21 -07001660 mPassengerCallbacks.add(callback);
1661 }
1662
1663 /** Removes previously added callback to listen passenger events. */
1664 public void removePassengerCallback(@NonNull PassengerCallback callback) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00001665 Objects.requireNonNull(callback, "callback cannot be null");
Eric Jeongc91f9452019-08-30 15:04:21 -07001666 mPassengerCallbacks.remove(callback);
1667 }
1668
1669 /** Sets the implementation of ZoneUserBindingHelper. */
1670 public void setZoneUserBindingHelper(@NonNull ZoneUserBindingHelper helper) {
1671 synchronized (mLockHelper) {
1672 mZoneUserBindingHelper = helper;
1673 }
1674 }
1675
felipeal98900c82020-04-09 09:05:02 -07001676 private void onUserUnlocked(@UserIdInt int userId) {
Keun-young Parkd462a912019-02-11 08:53:42 -08001677 ArrayList<Runnable> tasks = null;
Eric Jeongc91f9452019-08-30 15:04:21 -07001678 synchronized (mLockUser) {
Mayank Garg7a114c82020-04-08 21:25:06 -07001679 sendPostSwitchToHalLocked(userId);
Eric Jeong1545f3b2019-09-16 13:56:52 -07001680 if (userId == UserHandle.USER_SYSTEM) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001681 if (!mUser0Unlocked) { // user 0, unlocked, do this only once
1682 updateDefaultUserRestriction();
1683 tasks = new ArrayList<>(mUser0UnlockTasks);
1684 mUser0UnlockTasks.clear();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001685 mUser0Unlocked = true;
Keun young Parkf3523cd2019-04-08 10:09:17 -07001686 }
1687 } else { // none user0
Eric Jeong1545f3b2019-09-16 13:56:52 -07001688 Integer user = userId;
1689 if (isPersistentUser(userId)) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001690 // current foreground user should stay in top priority.
Anthony Hughfbb67762019-10-15 12:54:54 -07001691 if (userId == ActivityManager.getCurrentUser()) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001692 mBackgroundUsersToRestart.remove(user);
1693 mBackgroundUsersToRestart.add(0, user);
1694 }
1695 // -1 for user 0
1696 if (mBackgroundUsersToRestart.size() > (mMaxRunningUsers - 1)) {
Eric Jeong1545f3b2019-09-16 13:56:52 -07001697 int userToDrop = mBackgroundUsersToRestart.get(
Keun young Parkf3523cd2019-04-08 10:09:17 -07001698 mBackgroundUsersToRestart.size() - 1);
Eric Jeong1545f3b2019-09-16 13:56:52 -07001699 Log.i(TAG_USER, "New user unlocked:" + userId
Keun young Parkf3523cd2019-04-08 10:09:17 -07001700 + ", dropping least recently user from restart list:" + userToDrop);
1701 // Drop the least recently used user.
1702 mBackgroundUsersToRestart.remove(mBackgroundUsersToRestart.size() - 1);
1703 }
1704 }
Keun-young Parkd462a912019-02-11 08:53:42 -08001705 }
1706 }
1707 if (tasks != null && tasks.size() > 0) {
Eric Jeong1545f3b2019-09-16 13:56:52 -07001708 Log.d(TAG_USER, "User0 unlocked, run queued tasks:" + tasks.size());
Keun-young Parkd462a912019-02-11 08:53:42 -08001709 for (Runnable r : tasks) {
1710 r.run();
1711 }
1712 }
1713 }
1714
1715 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -07001716 * Starts all background users that were active in system.
1717 *
Keun young Parkfb656372019-03-12 18:37:55 -07001718 * @return list of background users started successfully.
1719 */
Eric Jeong1545f3b2019-09-16 13:56:52 -07001720 @NonNull
Keun young Parkfb656372019-03-12 18:37:55 -07001721 public ArrayList<Integer> startAllBackgroundUsers() {
1722 ArrayList<Integer> users;
Eric Jeongc91f9452019-08-30 15:04:21 -07001723 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001724 users = new ArrayList<>(mBackgroundUsersToRestart);
1725 mBackgroundUsersRestartedHere.clear();
1726 mBackgroundUsersRestartedHere.addAll(mBackgroundUsersToRestart);
Keun young Parkfb656372019-03-12 18:37:55 -07001727 }
1728 ArrayList<Integer> startedUsers = new ArrayList<>();
1729 for (Integer user : users) {
Anthony Hughfbb67762019-10-15 12:54:54 -07001730 if (user == ActivityManager.getCurrentUser()) {
Keun young Parkfb656372019-03-12 18:37:55 -07001731 continue;
1732 }
1733 try {
1734 if (mAm.startUserInBackground(user)) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001735 if (mUserManager.isUserUnlockingOrUnlocked(user)) {
1736 // already unlocked / unlocking. No need to unlock.
Keun young Parkfb656372019-03-12 18:37:55 -07001737 startedUsers.add(user);
Keun young Parkf3523cd2019-04-08 10:09:17 -07001738 } else if (mAm.unlockUser(user, null, null, null)) {
1739 startedUsers.add(user);
1740 } else { // started but cannot unlock
Eric Jeong1545f3b2019-09-16 13:56:52 -07001741 Log.w(TAG_USER, "Background user started but cannot be unlocked:" + user);
Keun young Parkf3523cd2019-04-08 10:09:17 -07001742 if (mUserManager.isUserRunning(user)) {
1743 // add to started list so that it can be stopped later.
1744 startedUsers.add(user);
1745 }
Keun young Parkfb656372019-03-12 18:37:55 -07001746 }
1747 }
1748 } catch (RemoteException e) {
1749 // ignore
Eric Jeong1545f3b2019-09-16 13:56:52 -07001750 Log.w(TAG_USER, "error while starting user in background", e);
Keun young Parkfb656372019-03-12 18:37:55 -07001751 }
1752 }
Keun young Parkf3523cd2019-04-08 10:09:17 -07001753 // Keep only users that were re-started in mBackgroundUsersRestartedHere
Eric Jeongc91f9452019-08-30 15:04:21 -07001754 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001755 ArrayList<Integer> usersToRemove = new ArrayList<>();
1756 for (Integer user : mBackgroundUsersToRestart) {
1757 if (!startedUsers.contains(user)) {
1758 usersToRemove.add(user);
1759 }
1760 }
1761 mBackgroundUsersRestartedHere.removeAll(usersToRemove);
1762 }
Keun young Parkfb656372019-03-12 18:37:55 -07001763 return startedUsers;
1764 }
1765
1766 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -07001767 * Stops all background users that were active in system.
1768 *
1769 * @return whether stopping succeeds.
Keun young Parkfb656372019-03-12 18:37:55 -07001770 */
Eric Jeong1545f3b2019-09-16 13:56:52 -07001771 public boolean stopBackgroundUser(@UserIdInt int userId) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001772 if (userId == UserHandle.USER_SYSTEM) {
1773 return false;
1774 }
Anthony Hughfbb67762019-10-15 12:54:54 -07001775 if (userId == ActivityManager.getCurrentUser()) {
Eric Jeong1545f3b2019-09-16 13:56:52 -07001776 Log.i(TAG_USER, "stopBackgroundUser, already a FG user:" + userId);
Keun young Parkfb656372019-03-12 18:37:55 -07001777 return false;
1778 }
1779 try {
Keun young Parked9e6282019-09-19 17:38:26 -07001780 int r = mAm.stopUserWithDelayedLocking(userId, true, null);
Keun young Parkf3523cd2019-04-08 10:09:17 -07001781 if (r == ActivityManager.USER_OP_SUCCESS) {
Eric Jeongc91f9452019-08-30 15:04:21 -07001782 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001783 Integer user = userId;
1784 mBackgroundUsersRestartedHere.remove(user);
1785 }
1786 } else if (r == ActivityManager.USER_OP_IS_CURRENT) {
1787 return false;
1788 } else {
Eric Jeong1545f3b2019-09-16 13:56:52 -07001789 Log.i(TAG_USER, "stopBackgroundUser failed, user:" + userId + " err:" + r);
Keun young Parkfb656372019-03-12 18:37:55 -07001790 return false;
1791 }
1792 } catch (RemoteException e) {
1793 // ignore
Eric Jeong1545f3b2019-09-16 13:56:52 -07001794 Log.w(TAG_USER, "error while stopping user", e);
Keun young Parkfb656372019-03-12 18:37:55 -07001795 }
1796 return true;
1797 }
1798
1799 /**
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001800 * Notifies all registered {@link UserLifecycleListener} with the event passed as argument.
Pavel Maltsev17e81832019-04-04 14:38:41 -07001801 */
Mayank Gargccad8062020-08-30 15:05:10 -07001802 public void onUserLifecycleEvent(@UserLifecycleEventType int eventType,
felipeale8c5dce2020-04-15 11:27:06 -07001803 @UserIdInt int fromUserId, @UserIdInt int toUserId) {
1804 int userId = toUserId;
felipeal98900c82020-04-09 09:05:02 -07001805
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001806 // Handle special cases first...
felipeal98900c82020-04-09 09:05:02 -07001807 if (eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING) {
Mayank Garge5de0f92020-04-23 21:38:38 -07001808 onUserSwitching(fromUserId, toUserId);
felipeal98900c82020-04-09 09:05:02 -07001809 } else if (eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_UNLOCKED) {
1810 onUserUnlocked(userId);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001811 }
1812
felipeale8c5dce2020-04-15 11:27:06 -07001813 // ...then notify listeners.
Yan Zhue7921522020-04-16 15:59:25 -07001814 UserLifecycleEvent event = new UserLifecycleEvent(eventType, fromUserId, userId);
felipeale8c5dce2020-04-15 11:27:06 -07001815
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001816 mHandler.post(() -> {
1817 handleNotifyServiceUserLifecycleListeners(event);
1818 handleNotifyAppUserLifecycleListeners(event);
1819 });
felipeale8c5dce2020-04-15 11:27:06 -07001820 }
1821
Mayank Garg7a114c82020-04-08 21:25:06 -07001822 private void sendPostSwitchToHalLocked(@UserIdInt int userId) {
felipealf7368962020-04-16 12:55:19 -07001823 if (mUserIdForUserSwitchInProcess == UserHandle.USER_NULL
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001824 || mUserIdForUserSwitchInProcess != userId
1825 || mRequestIdForUserSwitchInProcess == 0) {
Mayank Garg7a114c82020-04-08 21:25:06 -07001826 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1827 Log.d(TAG_USER, "No user switch request Id. No android post switch sent.");
1828 }
1829 return;
1830 }
felipealf7368962020-04-16 12:55:19 -07001831 postSwitchHalResponse(mRequestIdForUserSwitchInProcess, mUserIdForUserSwitchInProcess);
1832 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001833 mRequestIdForUserSwitchInProcess = 0;
Mayank Garg7a114c82020-04-08 21:25:06 -07001834 }
1835
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001836 private void handleNotifyAppUserLifecycleListeners(UserLifecycleEvent event) {
1837 int listenersSize = mAppLifecycleListeners.size();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001838 if (listenersSize == 0) {
felipeal2a84d512020-04-06 18:52:15 -07001839 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1840 Log.d(TAG_USER, "No app listener to be notified of " + event);
1841 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001842 return;
1843 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001844 // Must use a different TimingsTraceLog because it's another thread
1845 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1846 Log.d(TAG_USER, "Notifying " + listenersSize + " app listeners of " + event);
1847 }
felipeal2a84d512020-04-06 18:52:15 -07001848 int userId = event.getUserId();
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001849 TimingsTraceLog t = new TimingsTraceLog(TAG_USER, Trace.TRACE_TAG_SYSTEM_SERVER);
felipealde1e16d2020-06-03 13:20:48 -07001850 int eventType = event.getEventType();
1851 t.traceBegin("notify-app-listeners-user-" + userId + "-event-" + eventType);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001852 for (int i = 0; i < listenersSize; i++) {
1853 int uid = mAppLifecycleListeners.keyAt(i);
felipealde1e16d2020-06-03 13:20:48 -07001854
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001855 IResultReceiver listener = mAppLifecycleListeners.valueAt(i);
1856 Bundle data = new Bundle();
felipealde1e16d2020-06-03 13:20:48 -07001857 data.putInt(CarUserManager.BUNDLE_PARAM_ACTION, eventType);
Yan Zhue7921522020-04-16 15:59:25 -07001858
felipealde1e16d2020-06-03 13:20:48 -07001859 int fromUserId = event.getPreviousUserId();
1860 if (fromUserId != UserHandle.USER_NULL) {
1861 data.putInt(CarUserManager.BUNDLE_PARAM_PREVIOUS_USER_ID, fromUserId);
Yan Zhue7921522020-04-16 15:59:25 -07001862 }
1863
felipeal2a84d512020-04-06 18:52:15 -07001864 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001865 Log.d(TAG_USER, "Notifying listener for uid " + uid);
felipeal2a84d512020-04-06 18:52:15 -07001866 }
felipealde1e16d2020-06-03 13:20:48 -07001867 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_NOTIFY_APP_LIFECYCLE_LISTENER,
1868 uid, eventType, fromUserId, userId);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001869 try {
felipealde1e16d2020-06-03 13:20:48 -07001870 t.traceBegin("notify-app-listener-uid-" + uid);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001871 listener.send(userId, data);
1872 } catch (RemoteException e) {
1873 Log.e(TAG_USER, "Error calling lifecycle listener", e);
1874 } finally {
1875 t.traceEnd();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001876 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001877 }
1878 t.traceEnd(); // notify-app-listeners-user-USERID-event-EVENT_TYPE
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001879 }
1880
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001881 private void handleNotifyServiceUserLifecycleListeners(UserLifecycleEvent event) {
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001882 TimingsTraceLog t = new TimingsTraceLog(TAG_USER, Trace.TRACE_TAG_SYSTEM_SERVER);
1883 if (mUserLifecycleListeners.isEmpty()) {
felipeal2a84d512020-04-06 18:52:15 -07001884 Log.w(TAG_USER, "Not notifying internal UserLifecycleListeners");
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001885 return;
felipeal2a84d512020-04-06 18:52:15 -07001886 } else if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1887 Log.d(TAG_USER, "Notifying " + mUserLifecycleListeners.size() + " service listeners of "
1888 + event);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001889 }
felipeal2a84d512020-04-06 18:52:15 -07001890
felipealde1e16d2020-06-03 13:20:48 -07001891 int userId = event.getUserId();
1892 int eventType = event.getEventType();
1893 t.traceBegin("notify-listeners-user-" + userId + "-event-" + eventType);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001894 for (UserLifecycleListener listener : mUserLifecycleListeners) {
felipeal2a84d512020-04-06 18:52:15 -07001895 String listenerName = FunctionalUtils.getLambdaName(listener);
felipealde1e16d2020-06-03 13:20:48 -07001896 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_NOTIFY_INTERNAL_LIFECYCLE_LISTENER,
1897 listenerName, eventType, event.getPreviousUserId(), userId);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001898 try {
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001899 t.traceBegin("notify-listener-" + listenerName);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001900 listener.onEvent(event);
1901 } catch (RuntimeException e) {
1902 Log.e(TAG_USER,
felipeal2a84d512020-04-06 18:52:15 -07001903 "Exception raised when invoking onEvent for " + listenerName, e);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001904 } finally {
1905 t.traceEnd();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001906 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001907 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001908 t.traceEnd(); // notify-listeners-user-USERID-event-EVENT_TYPE
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001909 }
1910
Mayank Garge5de0f92020-04-23 21:38:38 -07001911 private void onUserSwitching(@UserIdInt int fromUserId, @UserIdInt int toUserId) {
Eric Jeong40f8fa32020-05-12 12:23:33 -07001912 Log.i(TAG_USER, "onUserSwitching() callback for user " + toUserId);
Felipe Leme5528ff72020-02-10 19:05:14 -08001913 TimingsTraceLog t = new TimingsTraceLog(TAG_USER, Trace.TRACE_TAG_SYSTEM_SERVER);
Mayank Garge5de0f92020-04-23 21:38:38 -07001914 t.traceBegin("onUserSwitching-" + toUserId);
Felipe Leme5528ff72020-02-10 19:05:14 -08001915
Mayank Garge5de0f92020-04-23 21:38:38 -07001916 // Switch HAL users if user switch is not requested by CarUserService
1917 notifyHalLegacySwitch(fromUserId, toUserId);
1918
Mayank Garge90a4082020-09-30 12:57:34 -07001919 mInitialUserSetter.setLastActiveUser(toUserId);
felipealbf327652020-06-03 11:33:29 -07001920
Eric Jeongc91f9452019-08-30 15:04:21 -07001921 if (mLastPassengerId != UserHandle.USER_NULL) {
1922 stopPassengerInternal(mLastPassengerId, false);
1923 }
1924 if (mEnablePassengerSupport && isPassengerDisplayAvailable()) {
1925 setupPassengerUser();
Mayank Garge5de0f92020-04-23 21:38:38 -07001926 startFirstPassenger(toUserId);
Eric Jeongc91f9452019-08-30 15:04:21 -07001927 }
felipeal98900c82020-04-09 09:05:02 -07001928 t.traceEnd();
Pavel Maltsev17e81832019-04-04 14:38:41 -07001929 }
1930
Mayank Garge5de0f92020-04-23 21:38:38 -07001931 private void notifyHalLegacySwitch(@UserIdInt int fromUserId, @UserIdInt int toUserId) {
1932 synchronized (mLockUser) {
felipeal7d12ee22020-06-05 09:30:19 -07001933 if (mUserIdForUserSwitchInProcess != UserHandle.USER_NULL) {
1934 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1935 Log.d(TAG, "notifyHalLegacySwitch(" + fromUserId + ", " + toUserId
1936 + "): not needed, normal switch for " + mUserIdForUserSwitchInProcess);
1937 }
1938 return;
1939 }
Mayank Garge5de0f92020-04-23 21:38:38 -07001940 }
1941
Mayank Garg9ed099e2020-06-04 16:05:20 -07001942 if (!isUserHalSupported()) return;
1943
Mayank Garge5de0f92020-04-23 21:38:38 -07001944 // switch HAL user
felipeal7d12ee22020-06-05 09:30:19 -07001945 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager, fromUserId);
Mayank Gargeb37d092020-06-02 14:37:57 -07001946 SwitchUserRequest request = createUserSwitchRequest(toUserId, usersInfo);
1947 mHal.legacyUserSwitch(request);
Mayank Garge5de0f92020-04-23 21:38:38 -07001948 }
1949
Pavel Maltsev17e81832019-04-04 14:38:41 -07001950 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -07001951 * 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 -08001952 * run inside this call.
Eric Jeong1545f3b2019-09-16 13:56:52 -07001953 *
Keun-young Parkd462a912019-02-11 08:53:42 -08001954 * @param r Runnable to run.
1955 */
Eric Jeong1545f3b2019-09-16 13:56:52 -07001956 public void runOnUser0Unlock(@NonNull Runnable r) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00001957 Objects.requireNonNull(r, "runnable cannot be null");
Keun-young Parkd462a912019-02-11 08:53:42 -08001958 boolean runNow = false;
Eric Jeongc91f9452019-08-30 15:04:21 -07001959 synchronized (mLockUser) {
Keun-young Parkd462a912019-02-11 08:53:42 -08001960 if (mUser0Unlocked) {
1961 runNow = true;
1962 } else {
1963 mUser0UnlockTasks.add(r);
1964 }
1965 }
1966 if (runNow) {
1967 r.run();
1968 }
1969 }
1970
Keun young Parkf3523cd2019-04-08 10:09:17 -07001971 @VisibleForTesting
Eric Jeong1545f3b2019-09-16 13:56:52 -07001972 @NonNull
1973 ArrayList<Integer> getBackgroundUsersToRestart() {
1974 ArrayList<Integer> backgroundUsersToRestart = null;
Eric Jeongc91f9452019-08-30 15:04:21 -07001975 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001976 backgroundUsersToRestart = new ArrayList<>(mBackgroundUsersToRestart);
1977 }
1978 return backgroundUsersToRestart;
1979 }
1980
Ying Zheng1ab32b62018-06-26 12:47:26 -07001981 private void setSystemUserRestrictions() {
Ying Zheng1ab32b62018-06-26 12:47:26 -07001982 // Disable Location service for system user.
1983 LocationManager locationManager =
1984 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
Anthony Hugh04ee04f2019-12-17 16:11:33 -08001985 locationManager.setLocationEnabledForUser(
1986 /* enabled= */ false, UserHandle.of(UserHandle.USER_SYSTEM));
Ying Zheng1ab32b62018-06-26 12:47:26 -07001987 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07001988
1989 /**
Anthony Hugh6fed1e92019-10-22 16:22:03 -07001990 * Assigns a default icon to a user according to the user's id.
1991 *
1992 * @param userInfo User whose avatar is set to default icon.
Anthony Hugh6fed1e92019-10-22 16:22:03 -07001993 */
Eric Jeongb2dc6ff2020-06-05 17:00:26 -07001994 private void assignDefaultIcon(UserInfo userInfo) {
Anthony Hugh6fed1e92019-10-22 16:22:03 -07001995 int idForIcon = userInfo.isGuest() ? UserHandle.USER_NULL : userInfo.id;
1996 Bitmap bitmap = UserIcons.convertToBitmap(
1997 UserIcons.getDefaultUserIcon(mContext.getResources(), idForIcon, false));
1998 mUserManager.setUserIcon(userInfo.id, bitmap);
Anthony Hugh6fed1e92019-10-22 16:22:03 -07001999 }
2000
Eric Jeong1545f3b2019-09-16 13:56:52 -07002001 private interface UserFilter {
2002 boolean isEligibleUser(UserInfo user);
2003 }
2004
2005 /** Returns all users who are matched by the given filter. */
2006 private List<UserInfo> getUsers(UserFilter filter) {
Colin Cross0df71ea2020-08-27 04:12:26 +00002007 List<UserInfo> users = mUserManager.getAliveUsers();
Eric Jeong1545f3b2019-09-16 13:56:52 -07002008
2009 for (Iterator<UserInfo> iterator = users.iterator(); iterator.hasNext(); ) {
2010 UserInfo user = iterator.next();
2011 if (!filter.isEligibleUser(user)) {
2012 iterator.remove();
2013 }
2014 }
2015 return users;
2016 }
2017
felipeal2d0483c2019-11-02 14:07:22 -07002018 private static void checkManageUsersOrDumpPermission(String message) {
Felipe Leme55236722020-10-16 16:54:32 -07002019 checkHasAtLeastOnePermissionGranted(message,
felipeal2d0483c2019-11-02 14:07:22 -07002020 android.Manifest.permission.MANAGE_USERS,
2021 android.Manifest.permission.DUMP);
2022 }
2023
Felipe Leme5528ff72020-02-10 19:05:14 -08002024 private void checkInteractAcrossUsersPermission(String message) {
Felipe Leme55236722020-10-16 16:54:32 -07002025 checkHasAtLeastOnePermissionGranted(message,
2026 android.Manifest.permission.INTERACT_ACROSS_USERS,
Felipe Leme5528ff72020-02-10 19:05:14 -08002027 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
2028 }
2029
Eric Jeongc91f9452019-08-30 15:04:21 -07002030 private int getNumberOfManagedProfiles(@UserIdInt int userId) {
Colin Cross0df71ea2020-08-27 04:12:26 +00002031 List<UserInfo> users = mUserManager.getAliveUsers();
Eric Jeongc91f9452019-08-30 15:04:21 -07002032 // Count all users that are managed profiles of the given user.
2033 int managedProfilesCount = 0;
2034 for (UserInfo user : users) {
2035 if (user.isManagedProfile() && user.profileGroupId == userId) {
2036 managedProfilesCount++;
2037 }
2038 }
2039 return managedProfilesCount;
2040 }
2041
2042 /**
2043 * Starts the first passenger of the given driver and assigns the passenger to the front
2044 * passenger zone.
2045 *
2046 * @param driverId User id of the driver.
2047 * @return whether it succeeds.
2048 */
2049 private boolean startFirstPassenger(@UserIdInt int driverId) {
2050 int zoneId = getAvailablePassengerZone();
2051 if (zoneId == OccupantZoneInfo.INVALID_ZONE_ID) {
2052 Log.w(TAG_USER, "passenger occupant zone is not found");
2053 return false;
2054 }
2055 List<UserInfo> passengers = getPassengers(driverId);
2056 if (passengers.size() < 1) {
2057 Log.w(TAG_USER, "passenger is not found");
2058 return false;
2059 }
2060 // Only one passenger is supported. If there are two or more passengers, the first passenger
2061 // is chosen.
2062 int passengerId = passengers.get(0).id;
2063 if (!startPassenger(passengerId, zoneId)) {
2064 Log.w(TAG_USER, "cannot start passenger " + passengerId);
2065 return false;
2066 }
2067 return true;
2068 }
2069
2070 private int getAvailablePassengerZone() {
2071 int[] occupantTypes = new int[] {CarOccupantZoneManager.OCCUPANT_TYPE_FRONT_PASSENGER,
2072 CarOccupantZoneManager.OCCUPANT_TYPE_REAR_PASSENGER};
2073 for (int occupantType : occupantTypes) {
2074 int zoneId = getZoneId(occupantType);
2075 if (zoneId != OccupantZoneInfo.INVALID_ZONE_ID) {
2076 return zoneId;
2077 }
2078 }
2079 return OccupantZoneInfo.INVALID_ZONE_ID;
2080 }
2081
2082 /**
2083 * Creates a new passenger user when there is no passenger user.
2084 */
2085 private void setupPassengerUser() {
2086 int currentUser = ActivityManager.getCurrentUser();
2087 int profileCount = getNumberOfManagedProfiles(currentUser);
2088 if (profileCount > 0) {
2089 Log.w(TAG_USER, "max profile of user" + currentUser
2090 + " is exceeded: current profile count is " + profileCount);
2091 return;
2092 }
2093 // TODO(b/140311342): Use resource string for the default passenger name.
2094 UserInfo passenger = createPassenger("Passenger", currentUser);
2095 if (passenger == null) {
2096 // Couldn't create user, most likely because there are too many.
2097 Log.w(TAG_USER, "cannot create a passenger user");
2098 return;
2099 }
2100 }
2101
2102 @NonNull
2103 private List<OccupantZoneInfo> getOccupantZones(@OccupantTypeEnum int occupantType) {
2104 ZoneUserBindingHelper helper = null;
2105 synchronized (mLockHelper) {
2106 if (mZoneUserBindingHelper == null) {
2107 Log.w(TAG_USER, "implementation is not delegated");
2108 return new ArrayList<OccupantZoneInfo>();
2109 }
2110 helper = mZoneUserBindingHelper;
2111 }
2112 return helper.getOccupantZones(occupantType);
2113 }
2114
2115 private boolean assignUserToOccupantZone(@UserIdInt int userId, int zoneId) {
2116 ZoneUserBindingHelper helper = null;
2117 synchronized (mLockHelper) {
2118 if (mZoneUserBindingHelper == null) {
2119 Log.w(TAG_USER, "implementation is not delegated");
2120 return false;
2121 }
2122 helper = mZoneUserBindingHelper;
2123 }
2124 return helper.assignUserToOccupantZone(userId, zoneId);
2125 }
2126
2127 private boolean unassignUserFromOccupantZone(@UserIdInt int userId) {
2128 ZoneUserBindingHelper helper = null;
2129 synchronized (mLockHelper) {
2130 if (mZoneUserBindingHelper == null) {
2131 Log.w(TAG_USER, "implementation is not delegated");
2132 return false;
2133 }
2134 helper = mZoneUserBindingHelper;
2135 }
2136 return helper.unassignUserFromOccupantZone(userId);
2137 }
2138
2139 private boolean isPassengerDisplayAvailable() {
2140 ZoneUserBindingHelper helper = null;
2141 synchronized (mLockHelper) {
2142 if (mZoneUserBindingHelper == null) {
2143 Log.w(TAG_USER, "implementation is not delegated");
2144 return false;
2145 }
2146 helper = mZoneUserBindingHelper;
2147 }
2148 return helper.isPassengerDisplayAvailable();
2149 }
2150
2151 /**
2152 * Gets the zone id of the given occupant type. If there are two or more zones, the first found
2153 * zone is returned.
2154 *
2155 * @param occupantType The type of an occupant.
2156 * @return The zone id of the given occupant type. {@link OccupantZoneInfo.INVALID_ZONE_ID},
2157 * if not found.
2158 */
2159 private int getZoneId(@OccupantTypeEnum int occupantType) {
2160 List<OccupantZoneInfo> zoneInfos = getOccupantZones(occupantType);
2161 return (zoneInfos.size() > 0) ? zoneInfos.get(0).zoneId : OccupantZoneInfo.INVALID_ZONE_ID;
2162 }
Mayank Garg9732d602020-08-09 21:02:40 -07002163
2164 /**
2165 * Manages the required number of pre-created users.
2166 */
2167 public void preCreateUsers() {
2168 mUserPreCreator.managePreCreatedUsers();
2169 }
Felipe Leme17799202020-09-03 12:55:53 -07002170
2171 // TODO(b/167698977): members below were copied from UserManagerService; it would be better to
2172 // move them to some internal android.os class instead.
2173
2174 private static final int ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION =
2175 UserInfo.FLAG_MANAGED_PROFILE
2176 | UserInfo.FLAG_PROFILE
2177 | UserInfo.FLAG_EPHEMERAL
2178 | UserInfo.FLAG_RESTRICTED
2179 | UserInfo.FLAG_GUEST
2180 | UserInfo.FLAG_DEMO
2181 | UserInfo.FLAG_FULL;
2182
2183 private static void checkManageUsersPermission(String message) {
2184 if (!hasManageUsersPermission()) {
2185 throw new SecurityException("You need " + MANAGE_USERS + " permission to: " + message);
2186 }
2187 }
2188
2189 private static void checkManageOrCreateUsersPermission(String message) {
2190 if (!hasManageOrCreateUsersPermission()) {
2191 throw new SecurityException(
2192 "You either need " + MANAGE_USERS + " or " + CREATE_USERS + " permission to: "
2193 + message);
2194 }
2195 }
2196
2197 private static void checkManageOrCreateUsersPermission(int creationFlags) {
2198 if ((creationFlags & ~ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION) == 0) {
2199 if (!hasManageOrCreateUsersPermission()) {
2200 throw new SecurityException("You either need " + MANAGE_USERS + " or "
2201 + CREATE_USERS + "permission to create a user with flags "
2202 + creationFlags);
2203 }
2204 } else if (!hasManageUsersPermission()) {
2205 throw new SecurityException("You need " + MANAGE_USERS + " permission to create a user"
2206 + " with flags " + creationFlags);
2207 }
2208 }
2209
2210 private static boolean hasManageUsersPermission() {
2211 final int callingUid = Binder.getCallingUid();
2212 return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
2213 || callingUid == Process.ROOT_UID
2214 || hasPermissionGranted(MANAGE_USERS, callingUid);
2215 }
2216
2217 private static boolean hasManageUsersOrPermission(String alternativePermission) {
2218 final int callingUid = Binder.getCallingUid();
2219 return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
2220 || callingUid == Process.ROOT_UID
2221 || hasPermissionGranted(MANAGE_USERS, callingUid)
2222 || hasPermissionGranted(alternativePermission, callingUid);
2223 }
2224
2225 private static boolean hasManageOrCreateUsersPermission() {
2226 return hasManageUsersOrPermission(CREATE_USERS);
2227 }
2228
2229 private static boolean hasPermissionGranted(String permission, int uid) {
2230 return ActivityManager.checkComponentPermission(permission, uid, /* owningUid= */ -1,
2231 /* exported= */ true) == PackageManager.PERMISSION_GRANTED;
2232 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002233}