blob: f56d7e699b9615ef8ab9e0d6aeffd4567785d036 [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;
Mayank Garg3f566582020-10-02 22:10:16 -070040import android.car.user.CarUserManager.UserIdentificationAssociationSetValue;
41import android.car.user.CarUserManager.UserIdentificationAssociationType;
Antonio Kantekc8114752020-03-05 21:37:39 -080042import android.car.user.CarUserManager.UserLifecycleEvent;
43import android.car.user.CarUserManager.UserLifecycleListener;
felipealdfdf8512020-06-01 09:35:45 -070044import android.car.user.UserCreationResult;
felipeal159a2a42020-05-08 10:32:11 -070045import android.car.user.UserIdentificationAssociationResponse;
Mayank Garga55c3092020-05-28 03:19:24 -070046import android.car.user.UserRemovalResult;
felipeale5bf0322020-04-16 15:10:57 -070047import android.car.user.UserSwitchResult;
felipeal19e3d732020-03-18 12:07:32 -070048import android.car.userlib.HalCallback;
49import android.car.userlib.UserHalHelper;
Mayank Garge90a4082020-09-30 12:57:34 -070050import android.car.userlib.UserHelper;
Felipe Leme6b34fc32020-10-26 15:49:17 -070051import android.content.BroadcastReceiver;
Mayank Garga480dd92020-05-14 03:14:57 -070052import android.content.ComponentName;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070053import android.content.Context;
Felipe Leme6b34fc32020-10-26 15:49:17 -070054import android.content.Intent;
55import android.content.IntentFilter;
Mayank Garga480dd92020-05-14 03:14:57 -070056import android.content.pm.PackageManager;
57import android.content.pm.PackageManager.NameNotFoundException;
Eric Jeong1545f3b2019-09-16 13:56:52 -070058import android.content.pm.UserInfo;
felipealdfdf8512020-06-01 09:35:45 -070059import android.content.pm.UserInfo.UserInfoFlag;
Felipe Leme315a53b2020-03-12 10:51:04 -070060import android.content.res.Resources;
Anthony Hugh6fed1e92019-10-22 16:22:03 -070061import android.graphics.Bitmap;
felipealdfdf8512020-06-01 09:35:45 -070062import android.hardware.automotive.vehicle.V2_0.CreateUserRequest;
63import android.hardware.automotive.vehicle.V2_0.CreateUserStatus;
Mayank Garg70732a82020-08-05 20:17:47 -070064import android.hardware.automotive.vehicle.V2_0.InitialUserInfoRequestType;
Felipe Lemec6e3c2a2020-02-19 16:53:57 -080065import android.hardware.automotive.vehicle.V2_0.InitialUserInfoResponseAction;
Mayank Garga55c3092020-05-28 03:19:24 -070066import android.hardware.automotive.vehicle.V2_0.RemoveUserRequest;
Mayank Gargeb37d092020-06-02 14:37:57 -070067import android.hardware.automotive.vehicle.V2_0.SwitchUserRequest;
Mayank Garg59f22192020-03-27 00:51:45 -070068import android.hardware.automotive.vehicle.V2_0.SwitchUserStatus;
felipeal5e3ede42020-04-23 18:04:07 -070069import android.hardware.automotive.vehicle.V2_0.UserIdentificationGetRequest;
70import android.hardware.automotive.vehicle.V2_0.UserIdentificationResponse;
felipeal159a2a42020-05-08 10:32:11 -070071import android.hardware.automotive.vehicle.V2_0.UserIdentificationSetAssociation;
72import android.hardware.automotive.vehicle.V2_0.UserIdentificationSetRequest;
Felipe Lemec6e3c2a2020-02-19 16:53:57 -080073import android.hardware.automotive.vehicle.V2_0.UsersInfo;
Ying Zheng1ab32b62018-06-26 12:47:26 -070074import android.location.LocationManager;
Eric Jeong1545f3b2019-09-16 13:56:52 -070075import android.os.Binder;
Felipe Leme5528ff72020-02-10 19:05:14 -080076import android.os.Bundle;
Antonio Kantek7236a5b2020-04-06 19:53:55 -070077import android.os.Handler;
78import android.os.HandlerThread;
Felipe Leme17799202020-09-03 12:55:53 -070079import android.os.Process;
Keun young Parkfb656372019-03-12 18:37:55 -070080import android.os.RemoteException;
Mayank Garg31e73042020-01-23 00:10:38 -080081import android.os.Trace;
Ying Zhengcf20f442018-06-22 16:54:51 -070082import android.os.UserHandle;
Ying Zheng8f90edb2018-06-13 12:42:31 -070083import android.os.UserManager;
jovanak24470652018-09-11 17:51:57 -070084import android.provider.Settings;
Felipe Lemee3cab982020-03-12 11:39:29 -070085import android.sysprop.CarProperties;
felipeal159a2a42020-05-08 10:32:11 -070086import android.text.TextUtils;
felipeal312416a2020-04-14 12:28:24 -070087import android.util.EventLog;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070088import android.util.Log;
Felipe Leme5528ff72020-02-10 19:05:14 -080089import android.util.SparseArray;
Felipe Leme6b34fc32020-10-26 15:49:17 -070090import android.util.SparseBooleanArray;
Mayank Garg31e73042020-01-23 00:10:38 -080091import android.util.TimingsTraceLog;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070092
93import com.android.car.CarServiceBase;
Keun young Parkb241d022020-04-20 20:31:34 -070094import com.android.car.CarServiceUtils;
Felipe Leme5d5ab142020-10-27 13:49:10 -070095import com.android.car.CarUxRestrictionsManagerService;
Eric Jeongc91f9452019-08-30 15:04:21 -070096import com.android.car.R;
Felipe Leme58412202020-01-09 13:45:33 -080097import com.android.car.hal.UserHalService;
Mayank Gargf59f95b2020-10-01 14:55:11 -070098import com.android.car.internal.common.CommonConstants.UserLifecycleEventType;
Mayank Garg801ea6a2020-09-29 15:43:49 -070099import com.android.car.internal.common.EventLogTags;
100import com.android.car.internal.common.UserHelperLite;
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700101import com.android.car.power.CarPowerManagementService;
Mayank Garg665c20b2020-08-07 16:19:28 -0700102import com.android.car.user.InitialUserSetter.InitialUserInfo;
Keun-young Parkd462a912019-02-11 08:53:42 -0800103import com.android.internal.annotations.GuardedBy;
Keun young Parkf3523cd2019-04-08 10:09:17 -0700104import com.android.internal.annotations.VisibleForTesting;
felipeale5bf0322020-04-16 15:10:57 -0700105import com.android.internal.infra.AndroidFuture;
Felipe Leme5528ff72020-02-10 19:05:14 -0800106import com.android.internal.os.IResultReceiver;
felipeal5e3ede42020-04-23 18:04:07 -0700107import com.android.internal.util.ArrayUtils;
felipeal2a84d512020-04-06 18:52:15 -0700108import com.android.internal.util.FunctionalUtils;
Mayank Garge19c2922020-03-30 18:05:53 -0700109import com.android.internal.util.Preconditions;
Anthony Hugh6fed1e92019-10-22 16:22:03 -0700110import com.android.internal.util.UserIcons;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700111
112import java.io.PrintWriter;
Keun-young Parkd462a912019-02-11 08:53:42 -0800113import java.util.ArrayList;
felipeal2d0483c2019-11-02 14:07:22 -0700114import java.util.Arrays;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700115import java.util.Iterator;
116import java.util.List;
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +0000117import java.util.Objects;
Pavel Maltsev17e81832019-04-04 14:38:41 -0700118import java.util.concurrent.CopyOnWriteArrayList;
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700119import java.util.concurrent.CountDownLatch;
120import java.util.concurrent.TimeUnit;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700121
122/**
123 * User service for cars. Manages users at boot time. Including:
124 *
125 * <ol>
Eric Jeong1545f3b2019-09-16 13:56:52 -0700126 * <li> Creates a user used as driver.
127 * <li> Creates a user used as passenger.
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700128 * <li> Creates a secondary admin user on first run.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700129 * <li> Switch drivers.
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700130 * <ol/>
131 */
Eric Jeong1545f3b2019-09-16 13:56:52 -0700132public final class CarUserService extends ICarUserService.Stub implements CarServiceBase {
Felipe Leme5528ff72020-02-10 19:05:14 -0800133
felipealf7368962020-04-16 12:55:19 -0700134 private static final String TAG = TAG_USER;
135
Felipe Lemeabbf2da2020-02-24 18:25:29 -0800136 /** {@code int} extra used to represent a user id in a {@link IResultReceiver} response. */
Mayank Garg8f932822020-09-17 16:09:12 -0700137 public static final String BUNDLE_USER_ID = "user.id";
Felipe Lemeabbf2da2020-02-24 18:25:29 -0800138 /** {@code int} extra used to represent user flags in a {@link IResultReceiver} response. */
Mayank Garg8f932822020-09-17 16:09:12 -0700139 public static final String BUNDLE_USER_FLAGS = "user.flags";
Felipe Lemeabbf2da2020-02-24 18:25:29 -0800140 /** {@code String} extra used to represent a user name in a {@link IResultReceiver} response. */
Mayank Garg8f932822020-09-17 16:09:12 -0700141 public static final String BUNDLE_USER_NAME = "user.name";
felipeala68ecef2020-05-19 12:46:08 -0700142 /**
143 * {@code int} extra used to represent the user locales in a {@link IResultReceiver} response.
144 */
Mayank Garg8f932822020-09-17 16:09:12 -0700145 public static final String BUNDLE_USER_LOCALES = "user.locales";
felipeala68ecef2020-05-19 12:46:08 -0700146 /**
147 * {@code int} extra used to represent the info action in a {@link IResultReceiver} response.
148 */
Mayank Garg8f932822020-09-17 16:09:12 -0700149 public static final String BUNDLE_INITIAL_INFO_ACTION = "initial_info.action";
Felipe Leme5528ff72020-02-10 19:05:14 -0800150
Mayank Garg9ed099e2020-06-04 16:05:20 -0700151 public static final String VEHICLE_HAL_NOT_SUPPORTED = "Vehicle Hal not supported.";
152
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700153 private final Context mContext;
Keun young Parkfb656372019-03-12 18:37:55 -0700154 private final IActivityManager mAm;
Anthony Hugh9932a252019-06-12 16:19:56 -0700155 private final UserManager mUserManager;
156 private final int mMaxRunningUsers;
Mayank Garg70732a82020-08-05 20:17:47 -0700157 private final InitialUserSetter mInitialUserSetter;
Eric Jeongc91f9452019-08-30 15:04:21 -0700158 private final boolean mEnablePassengerSupport;
Mayank Garg9732d602020-08-09 21:02:40 -0700159 private final UserPreCreator mUserPreCreator;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700160
Eric Jeongc91f9452019-08-30 15:04:21 -0700161 private final Object mLockUser = new Object();
162 @GuardedBy("mLockUser")
Keun-young Parkd462a912019-02-11 08:53:42 -0800163 private boolean mUser0Unlocked;
Eric Jeongc91f9452019-08-30 15:04:21 -0700164 @GuardedBy("mLockUser")
Keun-young Parkd462a912019-02-11 08:53:42 -0800165 private final ArrayList<Runnable> mUser0UnlockTasks = new ArrayList<>();
Eric Jeongc91f9452019-08-30 15:04:21 -0700166 // Only one passenger is supported.
167 @GuardedBy("mLockUser")
168 private @UserIdInt int mLastPassengerId;
Keun young Parkf3523cd2019-04-08 10:09:17 -0700169 /**
170 * Background users that will be restarted in garage mode. This list can include the
Mayank Garg31e73042020-01-23 00:10:38 -0800171 * current foreground user but the current foreground user should not be restarted.
Keun young Parkf3523cd2019-04-08 10:09:17 -0700172 */
Eric Jeongc91f9452019-08-30 15:04:21 -0700173 @GuardedBy("mLockUser")
Keun young Parkf3523cd2019-04-08 10:09:17 -0700174 private final ArrayList<Integer> mBackgroundUsersToRestart = new ArrayList<>();
175 /**
176 * Keep the list of background users started here. This is wholly for debugging purpose.
177 */
Eric Jeongc91f9452019-08-30 15:04:21 -0700178 @GuardedBy("mLockUser")
Keun young Parkf3523cd2019-04-08 10:09:17 -0700179 private final ArrayList<Integer> mBackgroundUsersRestartedHere = new ArrayList<>();
180
Felipe Leme58412202020-01-09 13:45:33 -0800181 private final UserHalService mHal;
182
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700183 // HandlerThread and Handler used when notifying app listeners (mAppLifecycleListeners).
Keun young Parkb241d022020-04-20 20:31:34 -0700184 private final HandlerThread mHandlerThread = CarServiceUtils.getHandlerThread(
185 getClass().getSimpleName());
186 private final Handler mHandler = new Handler(mHandlerThread.getLooper());
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700187
Felipe Leme5528ff72020-02-10 19:05:14 -0800188 /**
Antonio Kantekc8114752020-03-05 21:37:39 -0800189 * List of listeners to be notified on new user activities events.
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700190 * This collection should be accessed and manipulated by mHandlerThread only.
Antonio Kantekc8114752020-03-05 21:37:39 -0800191 */
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700192 private final List<UserLifecycleListener> mUserLifecycleListeners = new ArrayList<>();
Antonio Kantekc8114752020-03-05 21:37:39 -0800193
194 /**
Felipe Leme5528ff72020-02-10 19:05:14 -0800195 * List of lifecycle listeners by uid.
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700196 * This collection should be accessed and manipulated by mHandlerThread only.
Felipe Leme5528ff72020-02-10 19:05:14 -0800197 */
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700198 private final SparseArray<IResultReceiver> mAppLifecycleListeners = new SparseArray<>();
Felipe Leme5528ff72020-02-10 19:05:14 -0800199
Mayank Garg7a114c82020-04-08 21:25:06 -0700200 /**
201 * User Id for the user switch in process, if any.
202 */
203 @GuardedBy("mLockUser")
felipealf7368962020-04-16 12:55:19 -0700204 private int mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
Mayank Garg7a114c82020-04-08 21:25:06 -0700205 /**
206 * Request Id for the user switch in process, if any.
207 */
208 @GuardedBy("mLockUser")
felipealf7368962020-04-16 12:55:19 -0700209 private int mRequestIdForUserSwitchInProcess;
Felipe Lemee3cab982020-03-12 11:39:29 -0700210 private final int mHalTimeoutMs = CarProperties.user_hal_timeout().orElse(5_000);
211
Eric Jeongc91f9452019-08-30 15:04:21 -0700212 private final CopyOnWriteArrayList<PassengerCallback> mPassengerCallbacks =
213 new CopyOnWriteArrayList<>();
214
Mayank Garg7e1450b2020-08-07 18:15:15 -0700215 // TODO(b/163566866): Use mSwitchGuestUserBeforeSleep for new create guest request
216 private final boolean mSwitchGuestUserBeforeSleep;
217
felipeal61ce3732020-04-03 11:01:00 -0700218 @Nullable
219 @GuardedBy("mLockUser")
220 private UserInfo mInitialUser;
221
Mayank Garg587f1942020-05-06 01:41:34 -0700222 private IResultReceiver mUserSwitchUiReceiver;
223
Felipe Leme5d5ab142020-10-27 13:49:10 -0700224 private final CarUxRestrictionsManagerService mUxRestrictionService;
225
Eric Jeongc91f9452019-08-30 15:04:21 -0700226 /** Interface for callbaks related to passenger activities. */
227 public interface PassengerCallback {
228 /** Called when passenger is started at a certain zone. */
229 void onPassengerStarted(@UserIdInt int passengerId, int zoneId);
230 /** Called when passenger is stopped. */
231 void onPassengerStopped(@UserIdInt int passengerId);
232 }
233
234 /** Interface for delegating zone-related implementation to CarOccupantZoneService. */
235 public interface ZoneUserBindingHelper {
236 /** Gets occupant zones corresponding to the occupant type. */
237 @NonNull
238 List<OccupantZoneInfo> getOccupantZones(@OccupantTypeEnum int occupantType);
239 /** Assigns the user to the occupant zone. */
240 boolean assignUserToOccupantZone(@UserIdInt int userId, int zoneId);
241 /** Makes the occupant zone unoccupied. */
242 boolean unassignUserFromOccupantZone(@UserIdInt int userId);
243 /** Returns whether there is a passenger display. */
244 boolean isPassengerDisplayAvailable();
245 }
246
247 private final Object mLockHelper = new Object();
248 @GuardedBy("mLockHelper")
249 private ZoneUserBindingHelper mZoneUserBindingHelper;
250
Felipe Leme6b34fc32020-10-26 15:49:17 -0700251 private final BroadcastReceiver mUserLifecycleReceiver = new BroadcastReceiver() {
252 @Override
253 public void onReceive(Context context, Intent intent) {
254 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
255 Log.d(TAG_USER, "onReceive: " + intent);
256 }
257 switch(intent.getAction()) {
258 case Intent.ACTION_USER_REMOVED:
259 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
260 notifyHalUserRemoved(userId);
261 break;
262 default:
263 Log.w(TAG, "received unexpected intent: " + intent);
264 }
265 }
266 };
267
268 /** Map used to avoid calling UserHAL when a user was removed because HAL creation failed. */
269 @GuardedBy("mLockUser")
270 private final SparseBooleanArray mFailedToCreateUserIds = new SparseBooleanArray(1);
271
Felipe Leme58412202020-01-09 13:45:33 -0800272 public CarUserService(@NonNull Context context, @NonNull UserHalService hal,
Mayank Garge90a4082020-09-30 12:57:34 -0700273 @NonNull UserManager userManager,
Felipe Leme5d5ab142020-10-27 13:49:10 -0700274 @NonNull IActivityManager am, int maxRunningUsers,
275 @NonNull CarUxRestrictionsManagerService uxRestrictionService) {
Mayank Garge90a4082020-09-30 12:57:34 -0700276 this(context, hal, userManager, am, maxRunningUsers,
Felipe Leme5d5ab142020-10-27 13:49:10 -0700277 /* initialUserSetter= */ null, /* userPreCreator= */ null, uxRestrictionService);
Mayank Garg71661ea2020-04-29 01:25:03 -0700278 }
279
280 @VisibleForTesting
281 CarUserService(@NonNull Context context, @NonNull UserHalService hal,
Mayank Garge90a4082020-09-30 12:57:34 -0700282 @NonNull UserManager userManager,
Mayank Gargccad8062020-08-30 15:05:10 -0700283 @NonNull IActivityManager am, int maxRunningUsers,
Mayank Garg1bb1c382020-09-03 17:11:11 -0700284 @Nullable InitialUserSetter initialUserSetter,
Felipe Leme5d5ab142020-10-27 13:49:10 -0700285 @Nullable UserPreCreator userPreCreator,
286 @NonNull CarUxRestrictionsManagerService uxRestrictionService) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700287 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
288 Log.d(TAG_USER, "constructed");
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700289 }
290 mContext = context;
Felipe Leme58412202020-01-09 13:45:33 -0800291 mHal = hal;
Keun young Parkf3523cd2019-04-08 10:09:17 -0700292 mAm = am;
293 mMaxRunningUsers = maxRunningUsers;
Anthony Hugh9932a252019-06-12 16:19:56 -0700294 mUserManager = userManager;
Eric Jeongc91f9452019-08-30 15:04:21 -0700295 mLastPassengerId = UserHandle.USER_NULL;
Mayank Garg1bb1c382020-09-03 17:11:11 -0700296 mInitialUserSetter =
297 initialUserSetter == null ? new InitialUserSetter(context, (u) -> setInitialUser(u))
298 : initialUserSetter;
299 mUserPreCreator =
300 userPreCreator == null ? new UserPreCreator(mUserManager) : userPreCreator;
Mayank Garg7e1450b2020-08-07 18:15:15 -0700301 Resources resources = context.getResources();
302 mEnablePassengerSupport = resources.getBoolean(R.bool.enablePassengerSupport);
303 mSwitchGuestUserBeforeSleep = resources.getBoolean(
304 R.bool.config_switchGuestUserBeforeGoingSleep);
Felipe Leme5d5ab142020-10-27 13:49:10 -0700305 mUxRestrictionService = uxRestrictionService;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700306 }
307
308 @Override
309 public void init() {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700310 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
311 Log.d(TAG_USER, "init");
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700312 }
Felipe Leme6b34fc32020-10-26 15:49:17 -0700313 mContext.registerReceiver(mUserLifecycleReceiver,
314 new IntentFilter(Intent.ACTION_USER_REMOVED));
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700315 }
316
317 @Override
318 public void release() {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700319 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
320 Log.d(TAG_USER, "release");
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700321 }
Felipe Leme6b34fc32020-10-26 15:49:17 -0700322 mContext.unregisterReceiver(mUserLifecycleReceiver);
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700323 }
324
325 @Override
Eric Jeong1545f3b2019-09-16 13:56:52 -0700326 public void dump(@NonNull PrintWriter writer) {
Felipe Leme55236722020-10-16 16:54:32 -0700327 checkHasDumpPermissionGranted("dump()");
328
Eric Jeong1545f3b2019-09-16 13:56:52 -0700329 writer.println("*CarUserService*");
Felipe Leme5528ff72020-02-10 19:05:14 -0800330 String indent = " ";
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700331 handleDumpListeners(writer, indent);
Mayank Garg587f1942020-05-06 01:41:34 -0700332 writer.printf("User switch UI receiver %s\n", mUserSwitchUiReceiver);
Eric Jeongc91f9452019-08-30 15:04:21 -0700333 synchronized (mLockUser) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700334 writer.println("User0Unlocked: " + mUser0Unlocked);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700335 writer.println("BackgroundUsersToRestart: " + mBackgroundUsersToRestart);
336 writer.println("BackgroundUsersRestarted: " + mBackgroundUsersRestartedHere);
Felipe Leme6b34fc32020-10-26 15:49:17 -0700337 if (mFailedToCreateUserIds.size() > 0) {
338 writer.println("FailedToCreateUserIds: " + mFailedToCreateUserIds);
339 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700340 }
341 writer.println("MaxRunningUsers: " + mMaxRunningUsers);
342 List<UserInfo> allDrivers = getAllDrivers();
343 int driversSize = allDrivers.size();
344 writer.println("NumberOfDrivers: " + driversSize);
345 for (int i = 0; i < driversSize; i++) {
346 int driverId = allDrivers.get(i).id;
347 writer.print(indent + "#" + i + ": id=" + driverId);
348 List<UserInfo> passengers = getPassengers(driverId);
349 int passengersSize = passengers.size();
350 writer.print(" NumberPassengers: " + passengersSize);
351 if (passengersSize > 0) {
352 writer.print(" [");
353 for (int j = 0; j < passengersSize; j++) {
354 writer.print(passengers.get(j).id);
355 if (j < passengersSize - 1) {
356 writer.print(" ");
felipeal2d0483c2019-11-02 14:07:22 -0700357 }
felipeal2d0483c2019-11-02 14:07:22 -0700358 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700359 writer.print("]");
felipeal2d0483c2019-11-02 14:07:22 -0700360 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700361 writer.println();
362 }
363 writer.printf("EnablePassengerSupport: %s\n", mEnablePassengerSupport);
364 writer.printf("User HAL timeout: %dms\n", mHalTimeoutMs);
365 writer.printf("Initial user: %s\n", mInitialUser);
felipealbf327652020-06-03 11:33:29 -0700366
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700367 writer.println("Relevant overlayable properties");
368 Resources res = mContext.getResources();
369 writer.printf("%sowner_name=%s\n", indent,
370 res.getString(com.android.internal.R.string.owner_name));
371 writer.printf("%sdefault_guest_name=%s\n", indent,
372 res.getString(R.string.default_guest_name));
felipealf7368962020-04-16 12:55:19 -0700373 writer.printf("User switch in process=%d\n", mUserIdForUserSwitchInProcess);
Mayank Garg7a114c82020-04-08 21:25:06 -0700374 writer.printf("Request Id for the user switch in process=%d\n ",
375 mRequestIdForUserSwitchInProcess);
Mayank Garga480dd92020-05-14 03:14:57 -0700376 writer.printf("System UI package name=%s\n", getSystemUiPackageName());
Felipe Leme5d5ab142020-10-27 13:49:10 -0700377 writer.printf("Is UX restricted: %b\n", isUxRestricted());
felipeale8c5dce2020-04-15 11:27:06 -0700378
felipealbf327652020-06-03 11:33:29 -0700379 writer.println("Relevant Global settings");
380 dumpGlobalProperty(writer, indent, CarSettings.Global.LAST_ACTIVE_USER_ID);
381 dumpGlobalProperty(writer, indent, CarSettings.Global.LAST_ACTIVE_PERSISTENT_USER_ID);
382
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700383 mInitialUserSetter.dump(writer);
felipeale8c5dce2020-04-15 11:27:06 -0700384 }
385
felipealbf327652020-06-03 11:33:29 -0700386 private void dumpGlobalProperty(PrintWriter writer, String indent, String property) {
387 String value = Settings.Global.getString(mContext.getContentResolver(), property);
388 writer.printf("%s%s=%s\n", indent, property, value);
389 }
390
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700391 private void handleDumpListeners(@NonNull PrintWriter writer, String indent) {
392 CountDownLatch latch = new CountDownLatch(1);
393 mHandler.post(() -> {
felipealde1e16d2020-06-03 13:20:48 -0700394 handleDumpServiceLifecycleListeners(writer);
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700395 handleDumpAppLifecycleListeners(writer, indent);
396 latch.countDown();
397 });
398 int timeout = 5;
399 try {
400 if (!latch.await(timeout, TimeUnit.SECONDS)) {
401 writer.printf("Handler thread didn't respond in %ds when dumping listeners\n",
402 timeout);
403 }
404 } catch (InterruptedException e) {
405 Thread.currentThread().interrupt();
406 writer.println("Interrupted waiting for handler thread to dump app and user listeners");
407 }
408 }
409
felipealde1e16d2020-06-03 13:20:48 -0700410 private void handleDumpServiceLifecycleListeners(@NonNull PrintWriter writer) {
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700411 if (mUserLifecycleListeners.isEmpty()) {
felipealde1e16d2020-06-03 13:20:48 -0700412 writer.println("No lifecycle listeners for internal services");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700413 return;
414 }
felipealde1e16d2020-06-03 13:20:48 -0700415 int size = mUserLifecycleListeners.size();
416 writer.printf("%d lifecycle listener%s for services\n", size, size == 1 ? "" : "s");
417 String indent = " ";
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700418 for (UserLifecycleListener listener : mUserLifecycleListeners) {
felipealde1e16d2020-06-03 13:20:48 -0700419 writer.printf("%s%s\n", indent, FunctionalUtils.getLambdaName(listener));
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700420 }
421 }
422
423 private void handleDumpAppLifecycleListeners(@NonNull PrintWriter writer, String indent) {
felipealde1e16d2020-06-03 13:20:48 -0700424 int size = mAppLifecycleListeners.size();
425 if (size == 0) {
426 writer.println("No lifecycle listeners for apps");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700427 return;
428 }
felipealde1e16d2020-06-03 13:20:48 -0700429 writer.printf("%d lifecycle listener%s for apps \n", size, size == 1 ? "" : "s");
430 for (int i = 0; i < size; i++) {
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700431 int uid = mAppLifecycleListeners.keyAt(i);
432 IResultReceiver listener = mAppLifecycleListeners.valueAt(i);
Felipe Lemeea4b5322020-10-26 15:33:36 -0700433 writer.printf("%suid: %d listener: %s\n", indent, uid,
434 FunctionalUtils.getLambdaName(listener));
Keun-young Parkd462a912019-02-11 08:53:42 -0800435 }
Eric Jeong1545f3b2019-09-16 13:56:52 -0700436 }
437
438 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700439 * @see ExperimentalCarUserManager.createDriver
Eric Jeong1545f3b2019-09-16 13:56:52 -0700440 */
441 @Override
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700442 public AndroidFuture<UserCreationResult> createDriver(@NonNull String name, boolean admin) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700443 checkManageUsersPermission("createDriver");
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +0000444 Objects.requireNonNull(name, "name cannot be null");
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700445
446 AndroidFuture<UserCreationResult> future = new AndroidFuture<UserCreationResult>() {
447 @Override
448 protected void onCompleted(UserCreationResult result, Throwable err) {
449 if (result == null) {
450 Log.w(TAG, "createDriver(" + name + "," + admin + ") failed: " + err);
451 } else {
452 if (result.getStatus() == UserCreationResult.STATUS_SUCCESSFUL) {
453 assignDefaultIcon(result.getUser());
454 }
455 }
456 super.onCompleted(result, err);
457 };
458 };
459 int flags = 0;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700460 if (admin) {
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700461 if (!(mUserManager.isAdminUser() || mUserManager.isSystemUser())) {
462 Log.e(TAG_USER, "Only admin users and system user can create other admins.");
463 sendUserCreationResultFailure(future, UserCreationResult.STATUS_INVALID_REQUEST);
464 return future;
465 }
466 flags = UserInfo.FLAG_ADMIN;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700467 }
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700468 createUser(name, UserInfo.getDefaultUserType(flags), flags, mHalTimeoutMs, future);
469 return future;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700470 }
471
472 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700473 * @see ExperimentalCarUserManager.createPassenger
Eric Jeong1545f3b2019-09-16 13:56:52 -0700474 */
475 @Override
476 @Nullable
477 public UserInfo createPassenger(@NonNull String name, @UserIdInt int driverId) {
478 checkManageUsersPermission("createPassenger");
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +0000479 Objects.requireNonNull(name, "name cannot be null");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700480 UserInfo driver = mUserManager.getUserInfo(driverId);
481 if (driver == null) {
482 Log.w(TAG_USER, "the driver is invalid");
483 return null;
484 }
485 if (driver.isGuest()) {
486 Log.w(TAG_USER, "a guest driver cannot create a passenger");
487 return null;
488 }
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700489 // createPassenger doesn't use user HAL because user HAL doesn't support profile user yet.
Bookatz42fb1a62019-10-30 11:45:01 -0700490 UserInfo user = mUserManager.createProfileForUser(name,
491 UserManager.USER_TYPE_PROFILE_MANAGED, /* flags */ 0, driverId);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700492 if (user == null) {
493 // Couldn't create user, most likely because there are too many.
494 Log.w(TAG_USER, "can't create a profile for user" + driverId);
495 return null;
496 }
497 // Passenger user should be a non-admin user.
Mayank Garge90a4082020-09-30 12:57:34 -0700498 UserHelper.setDefaultNonAdminRestrictions(mContext, user, /* enable= */ true);
Anthony Hugh6fed1e92019-10-22 16:22:03 -0700499 assignDefaultIcon(user);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700500 return user;
501 }
502
503 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700504 * @see ExperimentalCarUserManager.switchDriver
Eric Jeong1545f3b2019-09-16 13:56:52 -0700505 */
506 @Override
Eric Jeong25666cf2020-05-14 15:16:27 -0700507 public void switchDriver(@UserIdInt int driverId, AndroidFuture<UserSwitchResult> receiver) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700508 checkManageUsersPermission("switchDriver");
Mayank Garg94f3eb92020-08-12 12:38:58 -0700509 if (UserHelperLite.isHeadlessSystemUser(driverId)) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700510 // System user doesn't associate with real person, can not be switched to.
511 Log.w(TAG_USER, "switching to system user in headless system user mode is not allowed");
felipealdfdf8512020-06-01 09:35:45 -0700512 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_INVALID_REQUEST);
Eric Jeong25666cf2020-05-14 15:16:27 -0700513 return;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700514 }
515 int userSwitchable = mUserManager.getUserSwitchability();
516 if (userSwitchable != UserManager.SWITCHABILITY_STATUS_OK) {
517 Log.w(TAG_USER, "current process is not allowed to switch user");
felipealdfdf8512020-06-01 09:35:45 -0700518 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_INVALID_REQUEST);
Eric Jeong25666cf2020-05-14 15:16:27 -0700519 return;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700520 }
Eric Jeong25666cf2020-05-14 15:16:27 -0700521 switchUser(driverId, mHalTimeoutMs, receiver);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700522 }
523
524 /**
Eric Jeonge7916fc2019-12-20 14:03:34 -0800525 * Returns all drivers who can occupy the driving zone. Guest users are included in the list.
526 *
527 * @return the list of {@link UserInfo} who can be a driver on the device.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700528 */
529 @Override
530 @NonNull
531 public List<UserInfo> getAllDrivers() {
felipeal2d0483c2019-11-02 14:07:22 -0700532 checkManageUsersOrDumpPermission("getAllDrivers");
Mayank Garg94f3eb92020-08-12 12:38:58 -0700533 return getUsers((user) -> !UserHelperLite.isHeadlessSystemUser(user.id) && user.isEnabled()
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700534 && !user.isManagedProfile() && !user.isEphemeral());
Eric Jeong1545f3b2019-09-16 13:56:52 -0700535 }
536
537 /**
Eric Jeonge7916fc2019-12-20 14:03:34 -0800538 * Returns all passengers under the given driver.
539 *
540 * @param driverId User id of a driver.
541 * @return the list of {@link UserInfo} who is a passenger under the given driver.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700542 */
543 @Override
544 @NonNull
545 public List<UserInfo> getPassengers(@UserIdInt int driverId) {
felipeal2d0483c2019-11-02 14:07:22 -0700546 checkManageUsersOrDumpPermission("getPassengers");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700547 return getUsers((user) -> {
Mayank Garg94f3eb92020-08-12 12:38:58 -0700548 return !UserHelperLite.isHeadlessSystemUser(user.id) && user.isEnabled()
Eric Jeong40f8fa32020-05-12 12:23:33 -0700549 && user.isManagedProfile() && user.profileGroupId == driverId;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700550 });
551 }
552
553 /**
554 * @see CarUserManager.startPassenger
555 */
556 @Override
557 public boolean startPassenger(@UserIdInt int passengerId, int zoneId) {
558 checkManageUsersPermission("startPassenger");
Eric Jeongc91f9452019-08-30 15:04:21 -0700559 synchronized (mLockUser) {
560 try {
561 if (!mAm.startUserInBackgroundWithListener(passengerId, null)) {
562 Log.w(TAG_USER, "could not start passenger");
563 return false;
564 }
565 } catch (RemoteException e) {
566 // ignore
567 Log.w(TAG_USER, "error while starting passenger", e);
568 return false;
569 }
570 if (!assignUserToOccupantZone(passengerId, zoneId)) {
571 Log.w(TAG_USER, "could not assign passenger to zone");
572 return false;
573 }
574 mLastPassengerId = passengerId;
575 }
576 for (PassengerCallback callback : mPassengerCallbacks) {
577 callback.onPassengerStarted(passengerId, zoneId);
578 }
579 return true;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700580 }
581
582 /**
583 * @see CarUserManager.stopPassenger
584 */
585 @Override
586 public boolean stopPassenger(@UserIdInt int passengerId) {
587 checkManageUsersPermission("stopPassenger");
Eric Jeongc91f9452019-08-30 15:04:21 -0700588 return stopPassengerInternal(passengerId, true);
589 }
590
591 private boolean stopPassengerInternal(@UserIdInt int passengerId, boolean checkCurrentDriver) {
592 synchronized (mLockUser) {
593 UserInfo passenger = mUserManager.getUserInfo(passengerId);
594 if (passenger == null) {
595 Log.w(TAG_USER, "passenger " + passengerId + " doesn't exist");
596 return false;
597 }
598 if (mLastPassengerId != passengerId) {
599 Log.w(TAG_USER, "passenger " + passengerId + " hasn't been started");
600 return true;
601 }
602 if (checkCurrentDriver) {
603 int currentUser = ActivityManager.getCurrentUser();
604 if (passenger.profileGroupId != currentUser) {
605 Log.w(TAG_USER, "passenger " + passengerId
606 + " is not a profile of the current user");
607 return false;
608 }
609 }
610 // Passenger is a profile, so cannot be stopped through activity manager.
611 // Instead, activities started by the passenger are stopped and the passenger is
612 // unassigned from the zone.
613 stopAllTasks(passengerId);
614 if (!unassignUserFromOccupantZone(passengerId)) {
615 Log.w(TAG_USER, "could not unassign user from occupant zone");
616 return false;
617 }
618 mLastPassengerId = UserHandle.USER_NULL;
619 }
620 for (PassengerCallback callback : mPassengerCallbacks) {
621 callback.onPassengerStopped(passengerId);
622 }
623 return true;
624 }
625
626 private void stopAllTasks(@UserIdInt int userId) {
627 try {
Louis Chang3bf2f202020-08-18 13:04:28 +0800628 for (RootTaskInfo info : mAm.getAllRootTaskInfos()) {
629 for (int i = 0; i < info.childTaskIds.length; i++) {
630 if (info.childTaskUserIds[i] == userId) {
631 int taskId = info.childTaskIds[i];
Eric Jeongc91f9452019-08-30 15:04:21 -0700632 if (!mAm.removeTask(taskId)) {
633 Log.w(TAG_USER, "could not remove task " + taskId);
634 }
635 }
636 }
637 }
638 } catch (RemoteException e) {
639 Log.e(TAG_USER, "could not get stack info", e);
640 }
Eric Jeong1545f3b2019-09-16 13:56:52 -0700641 }
642
Felipe Leme5528ff72020-02-10 19:05:14 -0800643 @Override
644 public void setLifecycleListenerForUid(IResultReceiver listener) {
645 int uid = Binder.getCallingUid();
felipeal312416a2020-04-14 12:28:24 -0700646 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SET_LIFECYCLE_LISTENER, uid);
Felipe Leme5528ff72020-02-10 19:05:14 -0800647 checkInteractAcrossUsersPermission("setLifecycleListenerForUid" + uid);
648
649 try {
650 listener.asBinder().linkToDeath(() -> onListenerDeath(uid), 0);
651 } catch (RemoteException e) {
652 Log.wtf(TAG_USER, "Cannot listen to death of " + uid);
653 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700654 mHandler.post(() -> mAppLifecycleListeners.append(uid, listener));
Felipe Leme5528ff72020-02-10 19:05:14 -0800655 }
656
657 private void onListenerDeath(int uid) {
658 Log.i(TAG_USER, "Removing listeners for uid " + uid + " on binder death");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700659 mHandler.post(() -> mAppLifecycleListeners.remove(uid));
Felipe Leme5528ff72020-02-10 19:05:14 -0800660 }
661
662 @Override
663 public void resetLifecycleListenerForUid() {
664 int uid = Binder.getCallingUid();
felipeal312416a2020-04-14 12:28:24 -0700665 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_RESET_LIFECYCLE_LISTENER, uid);
Felipe Leme5528ff72020-02-10 19:05:14 -0800666 checkInteractAcrossUsersPermission("resetLifecycleListenerForUid-" + uid);
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700667 mHandler.post(() -> mAppLifecycleListeners.remove(uid));
Felipe Leme5528ff72020-02-10 19:05:14 -0800668 }
669
Felipe Lemee3cab982020-03-12 11:39:29 -0700670 /**
felipeal61ce3732020-04-03 11:01:00 -0700671 * Gets the initial foreground user after the device boots or resumes from suspension.
672 *
673 * <p>When the OEM supports the User HAL, the initial user won't be available until the HAL
674 * returns the initial value to {@code CarService} - if HAL takes too long or times out, this
675 * method returns {@code null}.
676 *
677 * <p>If the HAL eventually times out, {@code CarService} will fallback to its default behavior
678 * (like switching to the last active user), and this method will return the result of such
679 * operation.
680 *
681 * <p>Notice that if {@code CarService} crashes, subsequent calls to this method will return
682 * {@code null}.
683 *
684 * @hide
685 */
686 @Nullable
687 public UserInfo getInitialUser() {
688 checkInteractAcrossUsersPermission("getInitialUser");
689 synchronized (mLockUser) {
690 return mInitialUser;
691 }
692 }
693
felipeal61ce3732020-04-03 11:01:00 -0700694 /**
695 * Sets the initial foreground user after the device boots or resumes from suspension.
696 */
697 public void setInitialUser(@Nullable UserInfo user) {
felipeal312416a2020-04-14 12:28:24 -0700698 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SET_INITIAL_USER,
699 user == null ? UserHandle.USER_NULL : user.id);
felipeal61ce3732020-04-03 11:01:00 -0700700 synchronized (mLockUser) {
701 mInitialUser = user;
702 }
703 if (user == null) {
704 // This mean InitialUserSetter failed and could not fallback, so the initial user was
705 // not switched (and most likely is SYSTEM_USER).
706 // TODO(b/153104378): should we set it to ActivityManager.getCurrentUser() instead?
707 Log.wtf(TAG_USER, "Initial user set to null");
708 }
709 }
710
Mayank Garg7e1450b2020-08-07 18:15:15 -0700711 private void initResumeReplaceGuest() {
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700712 int currentUserId = ActivityManager.getCurrentUser();
713 UserInfo currentUser = mUserManager.getUserInfo(currentUserId);
714
715 if (!mInitialUserSetter.canReplaceGuestUser(currentUser)) return; // Not a guest
716
717 InitialUserInfo info =
718 new InitialUserSetter.Builder(InitialUserSetter.TYPE_REPLACE_GUEST).build();
719
720 mInitialUserSetter.set(info);
721 }
722
723 /**
Mayank Garg0baf88a2020-08-30 21:57:36 -0700724 * Calls to switch user at the power suspend.
Mayank Garg7e1450b2020-08-07 18:15:15 -0700725 *
726 * <p><b>Note:</b> Should be used only by {@link CarPowerManagementService}
727 *
Mayank Garg7e1450b2020-08-07 18:15:15 -0700728 */
Mayank Garg0baf88a2020-08-30 21:57:36 -0700729 public void onSuspend() {
Mayank Garg7e1450b2020-08-07 18:15:15 -0700730 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
Mayank Garg0baf88a2020-08-30 21:57:36 -0700731 Log.d(TAG_USER, "onSuspend called.");
Mayank Garg7e1450b2020-08-07 18:15:15 -0700732 }
733
Mayank Garg0baf88a2020-08-30 21:57:36 -0700734 if (mSwitchGuestUserBeforeSleep) {
735 initResumeReplaceGuest();
Mayank Garg7e1450b2020-08-07 18:15:15 -0700736 }
Mayank Garg1bb1c382020-09-03 17:11:11 -0700737
738 preCreateUsers();
Mayank Garg7e1450b2020-08-07 18:15:15 -0700739 }
740
741 /**
Mayank Garg0baf88a2020-08-30 21:57:36 -0700742 * Calls to switch user at the power resume.
743 *
744 * <p>
745 * <b>Note:</b> Should be used only by {@link CarPowerManagementService}
746 *
747 */
748 public void onResume() {
749 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
750 Log.d(TAG_USER, "onResume called.");
751 }
752
753 initBootUser(InitialUserInfoRequestType.RESUME);
754 }
755
756 /**
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700757 * Calls to start user at the android startup.
Mayank Garg70732a82020-08-05 20:17:47 -0700758 */
759 public void initBootUser() {
760 int requestType = getInitialUserInfoRequestType();
Mayank Garg7e1450b2020-08-07 18:15:15 -0700761 initBootUser(requestType);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700762 }
763
Mayank Garg7e1450b2020-08-07 18:15:15 -0700764 private void initBootUser(int requestType) {
765 boolean replaceGuest =
766 requestType == InitialUserInfoRequestType.RESUME && !mSwitchGuestUserBeforeSleep;
Mayank Garg70732a82020-08-05 20:17:47 -0700767 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_REQ, requestType,
768 mHalTimeoutMs);
769 checkManageUsersPermission("startInitialUser");
770
771 if (!isUserHalSupported()) {
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700772 fallbackToDefaultInitialUserBehavior(/* userLocales= */ null, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700773 return;
774 }
775
776 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
777 mHal.getInitialUserInfo(requestType, mHalTimeoutMs, usersInfo, (status, resp) -> {
778 if (resp != null) {
779 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_RESP,
780 status, resp.action, resp.userToSwitchOrCreate.userId,
781 resp.userToSwitchOrCreate.flags, resp.userNameToCreate, resp.userLocales);
782
783 String userLocales = resp.userLocales;
784 InitialUserInfo info;
785 switch (resp.action) {
786 case InitialUserInfoResponseAction.SWITCH:
787 int userId = resp.userToSwitchOrCreate.userId;
788 if (userId <= 0) {
789 Log.w(TAG, "invalid (or missing) user id sent by HAL: " + userId);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700790 fallbackToDefaultInitialUserBehavior(userLocales, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700791 break;
792 }
793 info = new InitialUserSetter.Builder(InitialUserSetter.TYPE_SWITCH)
794 .setUserLocales(userLocales)
795 .setSwitchUserId(userId)
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700796 .setReplaceGuest(replaceGuest)
Mayank Garg70732a82020-08-05 20:17:47 -0700797 .build();
798 mInitialUserSetter.set(info);
799 break;
800
801 case InitialUserInfoResponseAction.CREATE:
802 int halFlags = resp.userToSwitchOrCreate.flags;
803 String userName = resp.userNameToCreate;
804 info = new InitialUserSetter.Builder(InitialUserSetter.TYPE_CREATE)
805 .setUserLocales(userLocales)
806 .setNewUserName(userName)
807 .setNewUserFlags(halFlags)
808 .build();
809 mInitialUserSetter.set(info);
810 break;
811
812 case InitialUserInfoResponseAction.DEFAULT:
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700813 fallbackToDefaultInitialUserBehavior(userLocales, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700814 break;
815 default:
816 Log.w(TAG_USER, "invalid response action on " + resp);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700817 fallbackToDefaultInitialUserBehavior(/* user locale */ null, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700818 break;
819
820 }
821 } else {
822 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_RESP, status);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700823 fallbackToDefaultInitialUserBehavior(/* user locale */ null, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700824 }
825 });
826 }
827
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700828 private void fallbackToDefaultInitialUserBehavior(String userLocales, boolean replaceGuest) {
Mayank Garg70732a82020-08-05 20:17:47 -0700829 InitialUserInfo info = new InitialUserSetter.Builder(
830 InitialUserSetter.TYPE_DEFAULT_BEHAVIOR)
831 .setUserLocales(userLocales)
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700832 .setReplaceGuest(replaceGuest)
Mayank Garg70732a82020-08-05 20:17:47 -0700833 .build();
834 mInitialUserSetter.set(info);
835 }
836
837 @VisibleForTesting
838 int getInitialUserInfoRequestType() {
Mayank Garge90a4082020-09-30 12:57:34 -0700839 if (!mInitialUserSetter.hasInitialUser()) {
Mayank Garg70732a82020-08-05 20:17:47 -0700840 return InitialUserInfoRequestType.FIRST_BOOT;
841 }
842 if (mContext.getPackageManager().isDeviceUpgrading()) {
843 return InitialUserInfoRequestType.FIRST_BOOT_AFTER_OTA;
844 }
845 return InitialUserInfoRequestType.COLD_BOOT;
846 }
847
Felipe Leme5d5ab142020-10-27 13:49:10 -0700848 private boolean isUxRestricted() {
849 CarUxRestrictions restrictions = mUxRestrictionService.getCurrentUxRestrictions();
850 boolean restricted = restrictions != null
851 && (restrictions.getActiveRestrictions() & UX_RESTRICTIONS_NO_SETUP)
852 == UX_RESTRICTIONS_NO_SETUP;
853 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
854 Log.d(TAG_USER, "isUxRestricted(): restrictions=" + restrictions
855 + ", restricted=" + restricted);
856 }
857 return restricted;
858 }
859
Mayank Garg70732a82020-08-05 20:17:47 -0700860 /**
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700861 * Calls the {@link UserHalService} and {@link IActivityManager} for user switch.
862 *
863 * <p>
Mayank Gargb08f6772020-05-01 18:06:48 -0700864 * When everything works well, the workflow is:
865 * <ol>
866 * <li> {@link UserHalService} is called for HAL user switch with ANDROID_SWITCH request
867 * type, current user id, target user id, and a callback.
868 * <li> HAL called back with SUCCESS.
869 * <li> {@link IActivityManager} is called for Android user switch.
870 * <li> Receiver would receive {@code STATUS_SUCCESSFUL}.
871 * <li> Once user is unlocked, {@link UserHalService} is again called with ANDROID_POST_SWITCH
872 * request type, current user id, and target user id. In this case, the current and target
873 * user IDs would be same.
874 * <ol/>
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700875 *
876 * <p>
Mayank Gargb08f6772020-05-01 18:06:48 -0700877 * Corner cases:
878 * <ul>
879 * <li> If target user is already the current user, no user switch is performed and receiver
Mayank Gargef1b9332020-06-11 17:36:56 -0700880 * would receive {@code STATUS_OK_USER_ALREADY_IN_FOREGROUND} right away.
Mayank Gargb08f6772020-05-01 18:06:48 -0700881 * <li> If HAL user switch call fails, no Android user switch. Receiver would receive
882 * {@code STATUS_HAL_INTERNAL_FAILURE}.
883 * <li> If HAL user switch call is successful, but android user switch call fails,
884 * {@link UserHalService} is again called with request type POST_SWITCH, current user id, and
885 * target user id, but in this case the current and target user IDs would be different.
886 * <li> If another user switch request for the same target user is received while previous
887 * request is in process, receiver would receive
888 * {@code STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO} for the new request right away.
889 * <li> If a user switch request is received while another user switch request for different
890 * target user is in process, the previous request would be abandoned and new request will be
891 * processed. No POST_SWITCH would be sent for the previous request.
892 * <ul/>
Mayank Garg59f22192020-03-27 00:51:45 -0700893 *
Mayank Garge19c2922020-03-30 18:05:53 -0700894 * @param targetUserId - target user Id
Mayank Garg59f22192020-03-27 00:51:45 -0700895 * @param timeoutMs - timeout for HAL to wait
896 * @param receiver - receiver for the results
897 */
Mayank Garge19c2922020-03-30 18:05:53 -0700898 @Override
899 public void switchUser(@UserIdInt int targetUserId, int timeoutMs,
felipeale5bf0322020-04-16 15:10:57 -0700900 @NonNull AndroidFuture<UserSwitchResult> receiver) {
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700901 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_REQ, targetUserId, timeoutMs);
Felipe Leme17799202020-09-03 12:55:53 -0700902 checkManageOrCreateUsersPermission("switchUser");
Mayank Garge19c2922020-03-30 18:05:53 -0700903 Objects.requireNonNull(receiver);
904 UserInfo targetUser = mUserManager.getUserInfo(targetUserId);
felipealf7368962020-04-16 12:55:19 -0700905 Preconditions.checkArgument(targetUser != null, "Target user doesn't exist");
Mayank Garg7a114c82020-04-08 21:25:06 -0700906
felipealf7368962020-04-16 12:55:19 -0700907 int currentUser = ActivityManager.getCurrentUser();
908 if (currentUser == targetUserId) {
Mayank Garg0e239142020-04-14 19:16:31 -0700909 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
910 Log.d(TAG_USER, "Current user is same as requested target user: " + targetUserId);
911 }
Mayank Gargef1b9332020-06-11 17:36:56 -0700912 int resultStatus = UserSwitchResult.STATUS_OK_USER_ALREADY_IN_FOREGROUND;
felipealdfdf8512020-06-01 09:35:45 -0700913 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg0e239142020-04-14 19:16:31 -0700914 return;
915 }
916
Felipe Leme5d5ab142020-10-27 13:49:10 -0700917 if (isUxRestricted()) {
918 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_UX_RESTRICTION_FAILURE);
919 return;
920 }
921
Mayank Garg9ed099e2020-06-04 16:05:20 -0700922 // If User Hal is not supported, just android user switch.
923 if (!isUserHalSupported()) {
924 try {
925 if (mAm.switchUser(targetUserId)) {
926 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_SUCCESSFUL);
927 return;
928 }
929 } catch (RemoteException e) {
930 // ignore
931 Log.w(TAG_USER,
932 "error while switching user " + targetUser.toFullString(), e);
933 }
934 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_ANDROID_FAILURE);
935 return;
936 }
937
Mayank Garg7a114c82020-04-08 21:25:06 -0700938 synchronized (mLockUser) {
felipealf7368962020-04-16 12:55:19 -0700939 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
940 Log.d(TAG_USER, "switchUser(" + targetUserId + "): currentuser=" + currentUser
941 + ", mUserIdForUserSwitchInProcess=" + mUserIdForUserSwitchInProcess);
942 }
943
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700944 // If there is another request for the same target user, return another request in
945 // process, else {@link mUserIdForUserSwitchInProcess} is updated and {@link
946 // mRequestIdForUserSwitchInProcess} is reset. It is possible that there may be another
947 // user switch request in process for different target user, but that request is now
948 // ignored.
felipealf7368962020-04-16 12:55:19 -0700949 if (mUserIdForUserSwitchInProcess == targetUserId) {
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700950 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
951 Log.d(TAG_USER,
952 "Another user switch request in process for the requested target user: "
953 + targetUserId);
954 }
955
956 int resultStatus = UserSwitchResult.STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO;
felipealdfdf8512020-06-01 09:35:45 -0700957 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg7a114c82020-04-08 21:25:06 -0700958 return;
959 }
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700960 else {
961 mUserIdForUserSwitchInProcess = targetUserId;
962 mRequestIdForUserSwitchInProcess = 0;
963 }
Mayank Garg7a114c82020-04-08 21:25:06 -0700964 }
965
felipealdfdf8512020-06-01 09:35:45 -0700966 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
Mayank Gargeb37d092020-06-02 14:37:57 -0700967 SwitchUserRequest request = createUserSwitchRequest(targetUserId, usersInfo);
968
Felipe Leme5d5ab142020-10-27 13:49:10 -0700969 mHal.switchUser(request, timeoutMs, (halCallbackStatus, resp) -> {
felipealf7368962020-04-16 12:55:19 -0700970 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
971 Log.d(TAG, "switch response: status="
Felipe Leme5d5ab142020-10-27 13:49:10 -0700972 + UserHalHelper.halCallbackStatusToString(halCallbackStatus)
973 + ", resp=" + resp);
felipealf7368962020-04-16 12:55:19 -0700974 }
975
felipeale5bf0322020-04-16 15:10:57 -0700976 int resultStatus = UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE;
felipealf7368962020-04-16 12:55:19 -0700977
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700978 synchronized (mLockUser) {
Felipe Leme5d5ab142020-10-27 13:49:10 -0700979 if (halCallbackStatus != HalCallback.STATUS_OK) {
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700980 Log.w(TAG, "invalid callback status ("
Felipe Leme5d5ab142020-10-27 13:49:10 -0700981 + UserHalHelper.halCallbackStatusToString(halCallbackStatus)
982 + ") for response " + resp);
felipealdfdf8512020-06-01 09:35:45 -0700983 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700984 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
985 return;
986 }
felipealf7368962020-04-16 12:55:19 -0700987
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700988 if (mUserIdForUserSwitchInProcess != targetUserId) {
989 // Another user switch request received while HAL responded. No need to process
990 // this request further
991 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
992 Log.d(TAG_USER, "Another user switch received while HAL responsed. Request "
993 + "abondoned for : " + targetUserId + ". Current user in process: "
994 + mUserIdForUserSwitchInProcess);
felipealf7368962020-04-16 12:55:19 -0700995 }
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700996 resultStatus =
997 UserSwitchResult.STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST;
felipealdfdf8512020-06-01 09:35:45 -0700998 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700999 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
1000 return;
1001 }
1002
1003 switch (resp.status) {
1004 case SwitchUserStatus.SUCCESS:
1005 boolean switched;
1006 try {
1007 switched = mAm.switchUser(targetUserId);
1008 if (switched) {
Mayank Garg587f1942020-05-06 01:41:34 -07001009 sendUserSwitchUiCallback(targetUserId);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001010 resultStatus = UserSwitchResult.STATUS_SUCCESSFUL;
1011 mRequestIdForUserSwitchInProcess = resp.requestId;
1012 } else {
1013 resultStatus = UserSwitchResult.STATUS_ANDROID_FAILURE;
1014 postSwitchHalResponse(resp.requestId, targetUserId);
1015 }
1016 } catch (RemoteException e) {
1017 // ignore
1018 Log.w(TAG_USER,
1019 "error while switching user " + targetUser.toFullString(), e);
1020 }
1021 break;
1022 case SwitchUserStatus.FAILURE:
1023 // HAL failed to switch user
1024 resultStatus = UserSwitchResult.STATUS_HAL_FAILURE;
1025 break;
felipealdfdf8512020-06-01 09:35:45 -07001026 default:
1027 // Shouldn't happen because UserHalService validates the status
1028 Log.wtf(TAG, "Received invalid user switch status from HAL: " + resp);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001029 }
1030
1031 if (mRequestIdForUserSwitchInProcess == 0) {
1032 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
1033 }
Mayank Garg59f22192020-03-27 00:51:45 -07001034 }
Felipe Leme5d5ab142020-10-27 13:49:10 -07001035 sendUserSwitchResult(receiver, halCallbackStatus, resultStatus, resp.errorMessage);
Mayank Garg59f22192020-03-27 00:51:45 -07001036 });
1037 }
1038
Mayank Garga55c3092020-05-28 03:19:24 -07001039 @Override
Felipe Leme55236722020-10-16 16:54:32 -07001040 public UserRemovalResult removeUser(@UserIdInt int userId) {
1041 return removeUser(userId, /* hasCallerRestrictions= */ false);
1042 }
1043
1044 /**
1045 * Internal implementation of {@code removeUser()}, which is used by both
1046 * {@code ICarUserService} and {@code ICarDevicePolicyService}.
1047 *
1048 * @param userId user to be removed
1049 * @param hasCallerRestrictions when {@code true}, if the caller user is not an admin, it can
1050 * only remove itself.
1051 *
1052 * @return result of the operation.
1053 */
Felipe Lemee5bb26b2020-10-26 15:49:17 -07001054 public UserRemovalResult removeUser(@UserIdInt int userId, boolean hasCallerRestrictions) {
Felipe Leme17799202020-09-03 12:55:53 -07001055 checkManageOrCreateUsersPermission("removeUser");
Felipe Leme55236722020-10-16 16:54:32 -07001056 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_REMOVE_USER_REQ, userId,
1057 hasCallerRestrictions ? 1 : 0);
Felipe Lemee5bb26b2020-10-26 15:49:17 -07001058
Mayank Garga55c3092020-05-28 03:19:24 -07001059 // If the requested user is the current user, return error.
1060 if (ActivityManager.getCurrentUser() == userId) {
1061 return logAndGetResults(userId,
1062 UserRemovalResult.STATUS_TARGET_USER_IS_CURRENT_USER);
1063 }
1064
1065 // If requested user is the only admin user, return error.
1066 UserInfo userInfo = mUserManager.getUserInfo(userId);
1067 if (userInfo == null) {
1068 return logAndGetResults(userId, UserRemovalResult.STATUS_USER_DOES_NOT_EXIST);
1069 }
1070
Felipe Lemee5bb26b2020-10-26 15:49:17 -07001071 if (hasCallerRestrictions) {
1072 // Restrictions: non-admin user can only remove itself, admins have no restrictions
1073 int callingUserId = Binder.getCallingUserHandle().getIdentifier();
1074 UserInfo callingUser = mUserManager.getUserInfo(callingUserId);
1075 if (!callingUser.isAdmin() && userId != callingUserId) {
1076 throw new SecurityException("Non-admin user " + callingUserId
1077 + " can only remove itself");
1078 }
1079 }
1080
Mayank Garga55c3092020-05-28 03:19:24 -07001081 android.hardware.automotive.vehicle.V2_0.UserInfo halUser =
1082 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1083 halUser.userId = userInfo.id;
1084 halUser.flags = UserHalHelper.convertFlags(userInfo);
1085 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1086
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001087 // check if the user is last admin user.
1088 boolean isLastAdmin = false;
Mayank Garga55c3092020-05-28 03:19:24 -07001089 if (UserHalHelper.isAdmin(halUser.flags)) {
1090 int size = usersInfo.existingUsers.size();
1091 int totalAdminUsers = 0;
1092 for (int i = 0; i < size; i++) {
1093 if (UserHalHelper.isAdmin(usersInfo.existingUsers.get(i).flags)) {
1094 totalAdminUsers++;
1095 }
1096 }
1097 if (totalAdminUsers == 1) {
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001098 isLastAdmin = true;
Mayank Garga55c3092020-05-28 03:19:24 -07001099 }
1100 }
1101
1102 // First remove user from android and then remove from HAL because HAL remove user is one
1103 // way call.
1104 if (!mUserManager.removeUser(userId)) {
1105 return logAndGetResults(userId, UserRemovalResult.STATUS_ANDROID_FAILURE);
1106 }
1107
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001108 if (isLastAdmin) {
1109 Log.w(TAG_USER, "Last admin user successfully removed. User Id: " + userId);
1110 }
1111
1112 return logAndGetResults(userId,
1113 isLastAdmin ? UserRemovalResult.STATUS_SUCCESSFUL_LAST_ADMIN_REMOVED
1114 : UserRemovalResult.STATUS_SUCCESSFUL);
Mayank Garga55c3092020-05-28 03:19:24 -07001115 }
1116
Felipe Leme6b34fc32020-10-26 15:49:17 -07001117 private void notifyHalUserRemoved(@UserIdInt int userId) {
1118 if (!isUserHalSupported()) return;
1119
1120 if (userId == UserHandle.USER_NULL) {
1121 Log.wtf(TAG, "notifyHalUserRemoved() Called for UserHandle.USER_NULL");
1122 return;
1123 }
1124
1125 synchronized (mLockUser) {
1126 if (mFailedToCreateUserIds.get(userId)) {
1127 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1128 Log.d(TAG, "notifyHalUserRemoved(): skipping " + userId);
1129 }
1130 mFailedToCreateUserIds.delete(userId);
1131 return;
1132 }
1133 }
1134
1135 android.hardware.automotive.vehicle.V2_0.UserInfo halUser =
1136 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1137 halUser.userId = userId;
1138 // TODO(b/155913815): per the REMOVE_USER API, the userFlags should be set as well, but it's
1139 // gone. We'll need to either update the documentation, or if that's not possible (as it's
1140 // breaking the contract), either change the intent to contain the flags, or keep track of
1141 // the flags internally.
1142
1143 RemoveUserRequest request = new RemoveUserRequest();
1144 request.removedUserInfo = halUser;
1145 request.usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1146 mHal.removeUser(request);
1147 }
1148
Mayank Garga55c3092020-05-28 03:19:24 -07001149 private UserRemovalResult logAndGetResults(@UserIdInt int userId,
1150 @UserRemovalResult.Status int result) {
1151 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_REMOVE_USER_RESP, userId, result);
1152 return new UserRemovalResult(result);
1153 }
1154
Mayank Garg587f1942020-05-06 01:41:34 -07001155 private void sendUserSwitchUiCallback(@UserIdInt int targetUserId) {
1156 if (mUserSwitchUiReceiver == null) {
1157 Log.w(TAG_USER, "No User switch UI receiver.");
1158 return;
1159 }
1160
felipealdfdf8512020-06-01 09:35:45 -07001161 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_UI_REQ, targetUserId);
Mayank Garg587f1942020-05-06 01:41:34 -07001162 try {
Mayank Garg587f1942020-05-06 01:41:34 -07001163 mUserSwitchUiReceiver.send(targetUserId, null);
1164 } catch (RemoteException e) {
1165 Log.e(TAG_USER, "Error calling user switch UI receiver.", e);
1166 }
1167 }
1168
felipeal5e3ede42020-04-23 18:04:07 -07001169 @Override
felipealdfdf8512020-06-01 09:35:45 -07001170 public void createUser(@Nullable String name, @NonNull String userType, @UserInfoFlag int flags,
1171 int timeoutMs, @NonNull AndroidFuture<UserCreationResult> receiver) {
Felipe Leme8c888ab2020-11-02 17:39:52 -08001172 createUser(name, userType, flags, timeoutMs, receiver, /* hasCallerRestrictions= */ false);
1173 }
1174
1175 /**
1176 * Internal implementation of {@code createUser()}, which is used by both
1177 * {@code ICarUserService} and {@code ICarDevicePolicyService}.
1178 *
1179 * @param hasCallerRestrictions when {@code true}, if the caller user is not an admin, it can
1180 * only create admin users
1181 */
1182 public void createUser(@Nullable String name, @NonNull String userType, @UserInfoFlag int flags,
1183 int timeoutMs, @NonNull AndroidFuture<UserCreationResult> receiver,
1184 boolean hasCallerRestrictions) {
felipealdfdf8512020-06-01 09:35:45 -07001185 Objects.requireNonNull(userType, "user type cannot be null");
1186 Objects.requireNonNull(receiver, "receiver cannot be null");
Felipe Leme17799202020-09-03 12:55:53 -07001187 checkManageOrCreateUsersPermission(flags);
1188
Mayank Garg94f3eb92020-08-12 12:38:58 -07001189 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_REQ,
Felipe Leme8c888ab2020-11-02 17:39:52 -08001190 UserHelperLite.safeName(name), userType, flags, timeoutMs,
1191 hasCallerRestrictions ? 1 : 0);
1192
1193 if (hasCallerRestrictions) {
1194 // Restrictions:
1195 // - type/flag can only be normal user, admin, or guest
1196 // - non-admin user can only create non-admin users
1197
1198 boolean validCombination;
1199 switch (userType) {
1200 case UserManager.USER_TYPE_FULL_SECONDARY:
1201 validCombination = flags == 0
1202 || (flags & UserInfo.FLAG_ADMIN) == UserInfo.FLAG_ADMIN;
1203 break;
1204 case UserManager.USER_TYPE_FULL_GUEST:
1205 validCombination = flags == 0;
1206 break;
1207 default:
1208 validCombination = false;
1209 }
1210 if (!validCombination) {
Felipe Leme71d296f2020-11-04 12:11:42 -08001211 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1212 Log.d(TAG, "Invalid combination of user type(" + userType
1213 + ") and flags (" + UserInfo.flagsToString(flags)
1214 + ") for caller with restrictions");
1215 }
1216 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_INVALID_REQUEST);
1217 return;
1218
Felipe Leme8c888ab2020-11-02 17:39:52 -08001219 }
1220
1221 int callingUserId = Binder.getCallingUserHandle().getIdentifier();
1222 UserInfo callingUser = mUserManager.getUserInfo(callingUserId);
1223 if (!callingUser.isAdmin() && (flags & UserInfo.FLAG_ADMIN) == UserInfo.FLAG_ADMIN) {
Felipe Leme71d296f2020-11-04 12:11:42 -08001224 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1225 Log.d(TAG, "Non-admin user " + callingUserId
1226 + " can only create non-admin users");
1227 }
1228 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_INVALID_REQUEST);
1229 return;
Felipe Leme8c888ab2020-11-02 17:39:52 -08001230 }
Felipe Leme71d296f2020-11-04 12:11:42 -08001231
Felipe Leme8c888ab2020-11-02 17:39:52 -08001232 }
felipealdfdf8512020-06-01 09:35:45 -07001233
1234 UserInfo newUser;
1235 try {
1236 newUser = mUserManager.createUser(name, userType, flags);
1237 if (newUser == null) {
1238 Log.w(TAG, "um.createUser() returned null for user of type " + userType
1239 + " and flags " + UserInfo.flagsToString(flags));
1240 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_ANDROID_FAILURE);
1241 return;
1242 }
1243 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1244 Log.d(TAG, "Created user: " + newUser.toFullString());
1245 }
1246 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_USER_CREATED, newUser.id,
Mayank Garg94f3eb92020-08-12 12:38:58 -07001247 UserHelperLite.safeName(newUser.name), newUser.userType, newUser.flags);
felipealdfdf8512020-06-01 09:35:45 -07001248 } catch (RuntimeException e) {
1249 Log.e(TAG_USER, "Error creating user of type " + userType + " and flags"
1250 + UserInfo.flagsToString(flags), e);
1251 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_ANDROID_FAILURE);
1252 return;
1253 }
1254
Mayank Garg9ed099e2020-06-04 16:05:20 -07001255 if (!isUserHalSupported()) {
1256 sendUserCreationResult(receiver, UserCreationResult.STATUS_SUCCESSFUL, newUser, null);
1257 return;
1258 }
1259
felipealdfdf8512020-06-01 09:35:45 -07001260 CreateUserRequest request = new CreateUserRequest();
1261 request.usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1262 if (!TextUtils.isEmpty(name)) {
1263 request.newUserName = name;
1264 }
1265 request.newUserInfo.userId = newUser.id;
1266 request.newUserInfo.flags = UserHalHelper.convertFlags(newUser);
1267 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1268 Log.d(TAG, "Create user request: " + request);
1269 }
1270
1271 try {
1272 mHal.createUser(request, timeoutMs, (status, resp) -> {
1273 int resultStatus = UserCreationResult.STATUS_HAL_INTERNAL_FAILURE;
1274 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1275 Log.d(TAG, "createUserResponse: status="
1276 + UserHalHelper.halCallbackStatusToString(status) + ", resp=" + resp);
1277 }
1278 UserInfo user = null; // user returned in the result
1279 if (status != HalCallback.STATUS_OK) {
1280 Log.w(TAG, "invalid callback status ("
1281 + UserHalHelper.halCallbackStatusToString(status) + ") for response "
1282 + resp);
1283 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_RESP, status,
1284 resultStatus, resp.errorMessage);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001285 removeCreatedUser(newUser, "HAL call failed with "
felipealdfdf8512020-06-01 09:35:45 -07001286 + UserHalHelper.halCallbackStatusToString(status));
1287 sendUserCreationResult(receiver, resultStatus, user, /* errorMsg= */ null);
1288 return;
1289 }
1290
1291 switch (resp.status) {
1292 case CreateUserStatus.SUCCESS:
1293 resultStatus = UserCreationResult.STATUS_SUCCESSFUL;
1294 user = newUser;
1295 break;
1296 case CreateUserStatus.FAILURE:
1297 // HAL failed to switch user
1298 resultStatus = UserCreationResult.STATUS_HAL_FAILURE;
1299 break;
1300 default:
1301 // Shouldn't happen because UserHalService validates the status
1302 Log.wtf(TAG, "Received invalid user switch status from HAL: " + resp);
1303 }
1304 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_RESP, status,
1305 resultStatus, resp.errorMessage);
1306 if (user == null) {
Felipe Leme6b34fc32020-10-26 15:49:17 -07001307 removeCreatedUser(newUser, "HAL returned "
felipealdfdf8512020-06-01 09:35:45 -07001308 + UserCreationResult.statusToString(resultStatus));
1309 }
1310 sendUserCreationResult(receiver, resultStatus, user, resp.errorMessage);
1311 });
1312 } catch (Exception e) {
1313 Log.w(TAG, "mHal.createUser(" + request + ") failed", e);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001314 removeCreatedUser(newUser, "mHal.createUser() failed");
felipealdfdf8512020-06-01 09:35:45 -07001315 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_HAL_INTERNAL_FAILURE);
1316 }
1317 }
1318
Felipe Leme6b34fc32020-10-26 15:49:17 -07001319 private void removeCreatedUser(@NonNull UserInfo user, @NonNull String reason) {
1320 int userId = user.id;
1321 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_USER_REMOVED, userId, reason);
1322
1323 synchronized (mLockUser) {
1324 mFailedToCreateUserIds.put(userId, true);
1325 }
1326
felipealdfdf8512020-06-01 09:35:45 -07001327 try {
Felipe Leme6b34fc32020-10-26 15:49:17 -07001328 if (!mUserManager.removeUser(userId)) {
felipealdfdf8512020-06-01 09:35:45 -07001329 Log.w(TAG, "Failed to remove user " + user.toFullString());
1330 }
1331 } catch (Exception e) {
1332 Log.e(TAG, "Failed to remove user " + user.toFullString(), e);
1333 }
1334 }
1335
1336 @Override
Mayank Garg3f566582020-10-02 22:10:16 -07001337 public UserIdentificationAssociationResponse getUserIdentificationAssociation(
1338 @UserIdentificationAssociationType int[] types) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001339 if (!isUserHalUserAssociationSupported()) {
1340 return UserIdentificationAssociationResponse.forFailure(VEHICLE_HAL_NOT_SUPPORTED);
1341 }
1342
felipeal5e3ede42020-04-23 18:04:07 -07001343 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type");
Felipe Leme17799202020-09-03 12:55:53 -07001344 checkManageOrCreateUsersPermission("getUserIdentificationAssociation");
felipeal5e3ede42020-04-23 18:04:07 -07001345
1346 int uid = getCallingUid();
1347 int userId = UserHandle.getUserId(uid);
1348 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_GET_USER_AUTH_REQ, uid, userId);
1349
1350 UserIdentificationGetRequest request = new UserIdentificationGetRequest();
1351 request.userInfo.userId = userId;
1352 request.userInfo.flags = getHalUserInfoFlags(userId);
1353
1354 request.numberAssociationTypes = types.length;
1355 for (int i = 0; i < types.length; i++) {
1356 request.associationTypes.add(types[i]);
1357 }
1358
1359 UserIdentificationResponse halResponse = mHal.getUserAssociation(request);
1360 if (halResponse == null) {
1361 Log.w(TAG, "getUserIdentificationAssociation(): HAL returned null for "
1362 + Arrays.toString(types));
felipeal159a2a42020-05-08 10:32:11 -07001363 return UserIdentificationAssociationResponse.forFailure();
felipeal5e3ede42020-04-23 18:04:07 -07001364 }
1365
1366 int[] values = new int[halResponse.associations.size()];
1367 for (int i = 0; i < values.length; i++) {
1368 values[i] = halResponse.associations.get(i).value;
1369 }
1370 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_GET_USER_AUTH_RESP, values.length);
1371
felipeal159a2a42020-05-08 10:32:11 -07001372 return UserIdentificationAssociationResponse.forSuccess(values, halResponse.errorMessage);
1373 }
1374
1375 @Override
Mayank Garg3f566582020-10-02 22:10:16 -07001376 public void setUserIdentificationAssociation(int timeoutMs,
1377 @UserIdentificationAssociationType int[] types,
1378 @UserIdentificationAssociationSetValue int[] values,
felipeal159a2a42020-05-08 10:32:11 -07001379 AndroidFuture<UserIdentificationAssociationResponse> result) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001380 if (!isUserHalUserAssociationSupported()) {
1381 result.complete(
1382 UserIdentificationAssociationResponse.forFailure(VEHICLE_HAL_NOT_SUPPORTED));
1383 return;
1384 }
1385
felipeal159a2a42020-05-08 10:32:11 -07001386 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type");
1387 Preconditions.checkArgument(!ArrayUtils.isEmpty(values), "must have at least one value");
1388 if (types.length != values.length) {
1389 throw new IllegalArgumentException("types (" + Arrays.toString(types) + ") and values ("
1390 + Arrays.toString(values) + ") should have the same length");
1391 }
Felipe Leme17799202020-09-03 12:55:53 -07001392 checkManageOrCreateUsersPermission("setUserIdentificationAssociation");
felipeal159a2a42020-05-08 10:32:11 -07001393
1394 int uid = getCallingUid();
1395 int userId = UserHandle.getUserId(uid);
1396 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_REQ, uid, userId, types.length);
1397
1398 UserIdentificationSetRequest request = new UserIdentificationSetRequest();
1399 request.userInfo.userId = userId;
1400 request.userInfo.flags = getHalUserInfoFlags(userId);
1401
1402 request.numberAssociations = types.length;
1403 for (int i = 0; i < types.length; i++) {
1404 UserIdentificationSetAssociation association = new UserIdentificationSetAssociation();
1405 association.type = types[i];
1406 association.value = values[i];
1407 request.associations.add(association);
1408 }
1409
1410 mHal.setUserAssociation(timeoutMs, request, (status, resp) -> {
1411 if (status != HalCallback.STATUS_OK) {
1412 Log.w(TAG, "setUserIdentificationAssociation(): invalid callback status ("
1413 + UserHalHelper.halCallbackStatusToString(status) + ") for response "
1414 + resp);
1415 if (resp == null || TextUtils.isEmpty(resp.errorMessage)) {
1416 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, 0);
1417 result.complete(UserIdentificationAssociationResponse.forFailure());
1418 return;
1419 }
1420 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, 0,
1421 resp.errorMessage);
1422 result.complete(
1423 UserIdentificationAssociationResponse.forFailure(resp.errorMessage));
1424 return;
1425 }
1426 int respSize = resp.associations.size();
1427 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, respSize,
1428 resp.errorMessage);
1429
1430 int[] responseTypes = new int[respSize];
1431 for (int i = 0; i < respSize; i++) {
1432 responseTypes[i] = resp.associations.get(i).value;
1433 }
1434 UserIdentificationAssociationResponse response = UserIdentificationAssociationResponse
1435 .forSuccess(responseTypes, resp.errorMessage);
1436 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1437 Log.d(TAG, "setUserIdentificationAssociation(): resp= " + resp
1438 + ", converted=" + response);
1439 }
1440 result.complete(response);
1441 });
felipeal5e3ede42020-04-23 18:04:07 -07001442 }
1443
1444 /**
1445 * Gets the User HAL flags for the given user.
1446 *
1447 * @throws IllegalArgumentException if the user does not exist.
1448 */
1449 private int getHalUserInfoFlags(@UserIdInt int userId) {
1450 UserInfo user = mUserManager.getUserInfo(userId);
1451 Preconditions.checkArgument(user != null, "no user for id %d", userId);
1452 return UserHalHelper.convertFlags(user);
1453 }
1454
Mayank Garg0e239142020-04-14 19:16:31 -07001455 private void sendResult(@NonNull IResultReceiver receiver, int resultCode,
1456 @Nullable Bundle resultData) {
1457 try {
1458 receiver.send(resultCode, resultData);
1459 } catch (RemoteException e) {
1460 // ignore
1461 Log.w(TAG_USER, "error while sending results", e);
1462 }
1463 }
1464
felipealdfdf8512020-06-01 09:35:45 -07001465 private void sendUserSwitchResult(@NonNull AndroidFuture<UserSwitchResult> receiver,
Felipe Leme5d5ab142020-10-27 13:49:10 -07001466 @UserSwitchResult.Status int userSwitchStatus) {
1467 sendUserSwitchResult(receiver, HalCallback.STATUS_INVALID, userSwitchStatus,
1468 /* errorMessage= */ null);
felipeale5bf0322020-04-16 15:10:57 -07001469 }
1470
felipealdfdf8512020-06-01 09:35:45 -07001471 private void sendUserSwitchResult(@NonNull AndroidFuture<UserSwitchResult> receiver,
Felipe Leme5d5ab142020-10-27 13:49:10 -07001472 @HalCallback.HalCallbackStatus int halCallbackStatus,
1473 @UserSwitchResult.Status int userSwitchStatus, @Nullable String errorMessage) {
1474 if (errorMessage != null) {
1475 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_RESP, halCallbackStatus,
1476 userSwitchStatus, errorMessage);
1477 } else {
1478 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_RESP, halCallbackStatus,
1479 userSwitchStatus);
1480 }
1481 receiver.complete(new UserSwitchResult(userSwitchStatus, errorMessage));
felipeale5bf0322020-04-16 15:10:57 -07001482 }
1483
felipealdfdf8512020-06-01 09:35:45 -07001484 private void sendUserCreationResultFailure(@NonNull AndroidFuture<UserCreationResult> receiver,
1485 @UserCreationResult.Status int status) {
1486 sendUserCreationResult(receiver, status, /* user= */ null, /* errorMessage= */ null);
1487 }
1488
1489 private void sendUserCreationResult(@NonNull AndroidFuture<UserCreationResult> receiver,
1490 @UserCreationResult.Status int status, @NonNull UserInfo user,
1491 @Nullable String errorMessage) {
1492 if (TextUtils.isEmpty(errorMessage)) {
1493 errorMessage = null;
1494 }
1495 receiver.complete(new UserCreationResult(status, user, errorMessage));
1496 }
1497
Mayank Garg6307fe42020-04-15 23:09:03 -07001498 /**
1499 * Calls activity manager for user switch.
1500 *
1501 * <p><b>NOTE</b> This method is meant to be called just by UserHalService.
1502 *
1503 * @param requestId for the user switch request
1504 * @param targetUserId of the target user
1505 *
1506 * @hide
1507 */
1508 public void switchAndroidUserFromHal(int requestId, @UserIdInt int targetUserId) {
1509 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_FROM_HAL_REQ, requestId,
1510 targetUserId);
1511 Log.i(TAG_USER, "User hal requested a user switch. Target user id " + targetUserId);
1512
1513 try {
1514 boolean result = mAm.switchUser(targetUserId);
1515 if (result) {
1516 updateUserSwitchInProcess(requestId, targetUserId);
1517 } else {
1518 postSwitchHalResponse(requestId, targetUserId);
1519 }
1520 } catch (RemoteException e) {
1521 // ignore
1522 Log.w(TAG_USER, "error while switching user " + targetUserId, e);
1523 }
1524 }
1525
1526 private void updateUserSwitchInProcess(int requestId, @UserIdInt int targetUserId) {
1527 synchronized (mLockUser) {
1528 if (mUserIdForUserSwitchInProcess != UserHandle.USER_NULL) {
1529 // Some other user switch is in process.
1530 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1531 Log.d(TAG_USER, "User switch for user: " + mUserIdForUserSwitchInProcess
1532 + " is in process. Abandoning it as a new user switch is requested"
1533 + " for the target user: " + targetUserId);
1534 }
1535 }
1536 mUserIdForUserSwitchInProcess = targetUserId;
1537 mRequestIdForUserSwitchInProcess = requestId;
1538 }
1539 }
Mayank Garg9ed099e2020-06-04 16:05:20 -07001540
Mayank Garg7a114c82020-04-08 21:25:06 -07001541 private void postSwitchHalResponse(int requestId, @UserIdInt int targetUserId) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001542 if (!isUserHalSupported()) return;
1543
felipealdfdf8512020-06-01 09:35:45 -07001544 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
Mayank Gargeb37d092020-06-02 14:37:57 -07001545 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_POST_SWITCH_USER_REQ, requestId,
1546 targetUserId, usersInfo.currentUser.userId);
1547 SwitchUserRequest request = createUserSwitchRequest(targetUserId, usersInfo);
1548 request.requestId = requestId;
1549 mHal.postSwitchResponse(request);
1550 }
1551
1552 private SwitchUserRequest createUserSwitchRequest(@UserIdInt int targetUserId,
1553 @NonNull UsersInfo usersInfo) {
1554 UserInfo targetUser = mUserManager.getUserInfo(targetUserId);
Mayank Garg7a114c82020-04-08 21:25:06 -07001555 android.hardware.automotive.vehicle.V2_0.UserInfo halTargetUser =
1556 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1557 halTargetUser.userId = targetUser.id;
1558 halTargetUser.flags = UserHalHelper.convertFlags(targetUser);
Mayank Gargeb37d092020-06-02 14:37:57 -07001559 SwitchUserRequest request = new SwitchUserRequest();
1560 request.targetUser = halTargetUser;
1561 request.usersInfo = usersInfo;
1562 return request;
Mayank Garg7a114c82020-04-08 21:25:06 -07001563 }
1564
Mayank Garg59f22192020-03-27 00:51:45 -07001565 /**
Felipe Lemee3cab982020-03-12 11:39:29 -07001566 * Checks if the User HAL is supported.
1567 */
1568 public boolean isUserHalSupported() {
1569 return mHal.isSupported();
1570 }
1571
Mayank Garg587f1942020-05-06 01:41:34 -07001572 /**
Mayank Garg9ed099e2020-06-04 16:05:20 -07001573 * Checks if the User HAL user association is supported.
1574 */
1575 @Override
1576 public boolean isUserHalUserAssociationSupported() {
1577 return mHal.isUserAssociationSupported();
1578 }
1579
1580 /**
Mayank Garg587f1942020-05-06 01:41:34 -07001581 * Sets a callback which is invoked before user switch.
1582 *
1583 * <p>
1584 * This method should only be called by the Car System UI. The purpose of this call is to notify
1585 * Car System UI to show the user switch UI before the user switch.
1586 */
1587 @Override
1588 public void setUserSwitchUiCallback(@NonNull IResultReceiver receiver) {
Yan Zhu67a383e2020-05-11 20:46:24 -07001589 checkManageUsersPermission("setUserSwitchUiCallback");
Mayank Garga480dd92020-05-14 03:14:57 -07001590
1591 // Confirm that caller is system UI.
1592 String systemUiPackageName = getSystemUiPackageName();
1593 if (systemUiPackageName == null) {
1594 throw new IllegalStateException("System UI package not found.");
1595 }
1596
1597 try {
1598 int systemUiUid = mContext
1599 .createContextAsUser(UserHandle.SYSTEM, /* flags= */ 0).getPackageManager()
1600 .getPackageUid(systemUiPackageName, PackageManager.MATCH_SYSTEM_ONLY);
1601 int callerUid = Binder.getCallingUid();
1602 if (systemUiUid != callerUid) {
1603 throw new SecurityException("Invalid caller. Only" + systemUiPackageName
1604 + " is allowed to make this call");
1605 }
1606 } catch (NameNotFoundException e) {
1607 throw new IllegalStateException("Package " + systemUiPackageName + " not found.");
1608 }
1609
Mayank Garg587f1942020-05-06 01:41:34 -07001610 mUserSwitchUiReceiver = receiver;
1611 }
1612
Mayank Garga480dd92020-05-14 03:14:57 -07001613 // TODO(157082995): This information can be taken from
1614 // PackageManageInternalImpl.getSystemUiServiceComponent
1615 @Nullable
1616 private String getSystemUiPackageName() {
1617 try {
1618 ComponentName componentName = ComponentName.unflattenFromString(mContext.getResources()
1619 .getString(com.android.internal.R.string.config_systemUIServiceComponent));
1620 return componentName.getPackageName();
1621 } catch (RuntimeException e) {
1622 Log.w(TAG_USER, "error while getting system UI package name.", e);
1623 return null;
1624 }
1625 }
1626
Keun young Park13a7a822019-04-04 15:53:08 -07001627 private void updateDefaultUserRestriction() {
1628 // We want to set restrictions on system and guest users only once. These are persisted
1629 // onto disk, so it's sufficient to do it once + we minimize the number of disk writes.
1630 if (Settings.Global.getInt(mContext.getContentResolver(),
Eric Jeong1545f3b2019-09-16 13:56:52 -07001631 CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, /* default= */ 0) != 0) {
1632 return;
Keun young Park13a7a822019-04-04 15:53:08 -07001633 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07001634 // Only apply the system user restrictions if the system user is headless.
1635 if (UserManager.isHeadlessSystemUserMode()) {
1636 setSystemUserRestrictions();
1637 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07001638 Settings.Global.putInt(mContext.getContentResolver(),
1639 CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, 1);
Keun young Park13a7a822019-04-04 15:53:08 -07001640 }
1641
Eric Jeong1545f3b2019-09-16 13:56:52 -07001642 private boolean isPersistentUser(@UserIdInt int userId) {
Anthony Hugh9932a252019-06-12 16:19:56 -07001643 return !mUserManager.getUserInfo(userId).isEphemeral();
1644 }
1645
Antonio Kantekc8114752020-03-05 21:37:39 -08001646 /**
Antonio Kantekc8114752020-03-05 21:37:39 -08001647 * Adds a new {@link UserLifecycleListener} to listen to user activity events.
1648 */
1649 public void addUserLifecycleListener(@NonNull UserLifecycleListener listener) {
1650 Objects.requireNonNull(listener, "listener cannot be null");
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001651 mHandler.post(() -> mUserLifecycleListeners.add(listener));
Antonio Kantekc8114752020-03-05 21:37:39 -08001652 }
1653
1654 /**
1655 * Removes previously added {@link UserLifecycleListener}.
1656 */
1657 public void removeUserLifecycleListener(@NonNull UserLifecycleListener listener) {
1658 Objects.requireNonNull(listener, "listener cannot be null");
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001659 mHandler.post(() -> mUserLifecycleListeners.remove(listener));
Antonio Kantekc8114752020-03-05 21:37:39 -08001660 }
1661
Eric Jeongc91f9452019-08-30 15:04:21 -07001662 /** Adds callback to listen to passenger activity events. */
1663 public void addPassengerCallback(@NonNull PassengerCallback callback) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00001664 Objects.requireNonNull(callback, "callback cannot be null");
Eric Jeongc91f9452019-08-30 15:04:21 -07001665 mPassengerCallbacks.add(callback);
1666 }
1667
1668 /** Removes previously added callback to listen passenger events. */
1669 public void removePassengerCallback(@NonNull PassengerCallback callback) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00001670 Objects.requireNonNull(callback, "callback cannot be null");
Eric Jeongc91f9452019-08-30 15:04:21 -07001671 mPassengerCallbacks.remove(callback);
1672 }
1673
1674 /** Sets the implementation of ZoneUserBindingHelper. */
1675 public void setZoneUserBindingHelper(@NonNull ZoneUserBindingHelper helper) {
1676 synchronized (mLockHelper) {
1677 mZoneUserBindingHelper = helper;
1678 }
1679 }
1680
felipeal98900c82020-04-09 09:05:02 -07001681 private void onUserUnlocked(@UserIdInt int userId) {
Keun-young Parkd462a912019-02-11 08:53:42 -08001682 ArrayList<Runnable> tasks = null;
Eric Jeongc91f9452019-08-30 15:04:21 -07001683 synchronized (mLockUser) {
Mayank Garg7a114c82020-04-08 21:25:06 -07001684 sendPostSwitchToHalLocked(userId);
Eric Jeong1545f3b2019-09-16 13:56:52 -07001685 if (userId == UserHandle.USER_SYSTEM) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001686 if (!mUser0Unlocked) { // user 0, unlocked, do this only once
1687 updateDefaultUserRestriction();
1688 tasks = new ArrayList<>(mUser0UnlockTasks);
1689 mUser0UnlockTasks.clear();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001690 mUser0Unlocked = true;
Keun young Parkf3523cd2019-04-08 10:09:17 -07001691 }
1692 } else { // none user0
Eric Jeong1545f3b2019-09-16 13:56:52 -07001693 Integer user = userId;
1694 if (isPersistentUser(userId)) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001695 // current foreground user should stay in top priority.
Anthony Hughfbb67762019-10-15 12:54:54 -07001696 if (userId == ActivityManager.getCurrentUser()) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001697 mBackgroundUsersToRestart.remove(user);
1698 mBackgroundUsersToRestart.add(0, user);
1699 }
1700 // -1 for user 0
1701 if (mBackgroundUsersToRestart.size() > (mMaxRunningUsers - 1)) {
Eric Jeong1545f3b2019-09-16 13:56:52 -07001702 int userToDrop = mBackgroundUsersToRestart.get(
Keun young Parkf3523cd2019-04-08 10:09:17 -07001703 mBackgroundUsersToRestart.size() - 1);
Eric Jeong1545f3b2019-09-16 13:56:52 -07001704 Log.i(TAG_USER, "New user unlocked:" + userId
Keun young Parkf3523cd2019-04-08 10:09:17 -07001705 + ", dropping least recently user from restart list:" + userToDrop);
1706 // Drop the least recently used user.
1707 mBackgroundUsersToRestart.remove(mBackgroundUsersToRestart.size() - 1);
1708 }
1709 }
Keun-young Parkd462a912019-02-11 08:53:42 -08001710 }
1711 }
1712 if (tasks != null && tasks.size() > 0) {
Eric Jeong1545f3b2019-09-16 13:56:52 -07001713 Log.d(TAG_USER, "User0 unlocked, run queued tasks:" + tasks.size());
Keun-young Parkd462a912019-02-11 08:53:42 -08001714 for (Runnable r : tasks) {
1715 r.run();
1716 }
1717 }
1718 }
1719
1720 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -07001721 * Starts all background users that were active in system.
1722 *
Keun young Parkfb656372019-03-12 18:37:55 -07001723 * @return list of background users started successfully.
1724 */
Eric Jeong1545f3b2019-09-16 13:56:52 -07001725 @NonNull
Keun young Parkfb656372019-03-12 18:37:55 -07001726 public ArrayList<Integer> startAllBackgroundUsers() {
1727 ArrayList<Integer> users;
Eric Jeongc91f9452019-08-30 15:04:21 -07001728 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001729 users = new ArrayList<>(mBackgroundUsersToRestart);
1730 mBackgroundUsersRestartedHere.clear();
1731 mBackgroundUsersRestartedHere.addAll(mBackgroundUsersToRestart);
Keun young Parkfb656372019-03-12 18:37:55 -07001732 }
1733 ArrayList<Integer> startedUsers = new ArrayList<>();
1734 for (Integer user : users) {
Anthony Hughfbb67762019-10-15 12:54:54 -07001735 if (user == ActivityManager.getCurrentUser()) {
Keun young Parkfb656372019-03-12 18:37:55 -07001736 continue;
1737 }
1738 try {
1739 if (mAm.startUserInBackground(user)) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001740 if (mUserManager.isUserUnlockingOrUnlocked(user)) {
1741 // already unlocked / unlocking. No need to unlock.
Keun young Parkfb656372019-03-12 18:37:55 -07001742 startedUsers.add(user);
Keun young Parkf3523cd2019-04-08 10:09:17 -07001743 } else if (mAm.unlockUser(user, null, null, null)) {
1744 startedUsers.add(user);
1745 } else { // started but cannot unlock
Eric Jeong1545f3b2019-09-16 13:56:52 -07001746 Log.w(TAG_USER, "Background user started but cannot be unlocked:" + user);
Keun young Parkf3523cd2019-04-08 10:09:17 -07001747 if (mUserManager.isUserRunning(user)) {
1748 // add to started list so that it can be stopped later.
1749 startedUsers.add(user);
1750 }
Keun young Parkfb656372019-03-12 18:37:55 -07001751 }
1752 }
1753 } catch (RemoteException e) {
1754 // ignore
Eric Jeong1545f3b2019-09-16 13:56:52 -07001755 Log.w(TAG_USER, "error while starting user in background", e);
Keun young Parkfb656372019-03-12 18:37:55 -07001756 }
1757 }
Keun young Parkf3523cd2019-04-08 10:09:17 -07001758 // Keep only users that were re-started in mBackgroundUsersRestartedHere
Eric Jeongc91f9452019-08-30 15:04:21 -07001759 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001760 ArrayList<Integer> usersToRemove = new ArrayList<>();
1761 for (Integer user : mBackgroundUsersToRestart) {
1762 if (!startedUsers.contains(user)) {
1763 usersToRemove.add(user);
1764 }
1765 }
1766 mBackgroundUsersRestartedHere.removeAll(usersToRemove);
1767 }
Keun young Parkfb656372019-03-12 18:37:55 -07001768 return startedUsers;
1769 }
1770
1771 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -07001772 * Stops all background users that were active in system.
1773 *
1774 * @return whether stopping succeeds.
Keun young Parkfb656372019-03-12 18:37:55 -07001775 */
Eric Jeong1545f3b2019-09-16 13:56:52 -07001776 public boolean stopBackgroundUser(@UserIdInt int userId) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001777 if (userId == UserHandle.USER_SYSTEM) {
1778 return false;
1779 }
Anthony Hughfbb67762019-10-15 12:54:54 -07001780 if (userId == ActivityManager.getCurrentUser()) {
Eric Jeong1545f3b2019-09-16 13:56:52 -07001781 Log.i(TAG_USER, "stopBackgroundUser, already a FG user:" + userId);
Keun young Parkfb656372019-03-12 18:37:55 -07001782 return false;
1783 }
1784 try {
Keun young Parked9e6282019-09-19 17:38:26 -07001785 int r = mAm.stopUserWithDelayedLocking(userId, true, null);
Keun young Parkf3523cd2019-04-08 10:09:17 -07001786 if (r == ActivityManager.USER_OP_SUCCESS) {
Eric Jeongc91f9452019-08-30 15:04:21 -07001787 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001788 Integer user = userId;
1789 mBackgroundUsersRestartedHere.remove(user);
1790 }
1791 } else if (r == ActivityManager.USER_OP_IS_CURRENT) {
1792 return false;
1793 } else {
Eric Jeong1545f3b2019-09-16 13:56:52 -07001794 Log.i(TAG_USER, "stopBackgroundUser failed, user:" + userId + " err:" + r);
Keun young Parkfb656372019-03-12 18:37:55 -07001795 return false;
1796 }
1797 } catch (RemoteException e) {
1798 // ignore
Eric Jeong1545f3b2019-09-16 13:56:52 -07001799 Log.w(TAG_USER, "error while stopping user", e);
Keun young Parkfb656372019-03-12 18:37:55 -07001800 }
1801 return true;
1802 }
1803
1804 /**
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001805 * Notifies all registered {@link UserLifecycleListener} with the event passed as argument.
Pavel Maltsev17e81832019-04-04 14:38:41 -07001806 */
Mayank Gargccad8062020-08-30 15:05:10 -07001807 public void onUserLifecycleEvent(@UserLifecycleEventType int eventType,
felipeale8c5dce2020-04-15 11:27:06 -07001808 @UserIdInt int fromUserId, @UserIdInt int toUserId) {
1809 int userId = toUserId;
felipeal98900c82020-04-09 09:05:02 -07001810
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001811 // Handle special cases first...
felipeal98900c82020-04-09 09:05:02 -07001812 if (eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING) {
Mayank Garge5de0f92020-04-23 21:38:38 -07001813 onUserSwitching(fromUserId, toUserId);
felipeal98900c82020-04-09 09:05:02 -07001814 } else if (eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_UNLOCKED) {
1815 onUserUnlocked(userId);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001816 }
1817
felipeale8c5dce2020-04-15 11:27:06 -07001818 // ...then notify listeners.
Yan Zhue7921522020-04-16 15:59:25 -07001819 UserLifecycleEvent event = new UserLifecycleEvent(eventType, fromUserId, userId);
felipeale8c5dce2020-04-15 11:27:06 -07001820
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001821 mHandler.post(() -> {
1822 handleNotifyServiceUserLifecycleListeners(event);
1823 handleNotifyAppUserLifecycleListeners(event);
1824 });
felipeale8c5dce2020-04-15 11:27:06 -07001825 }
1826
Mayank Garg7a114c82020-04-08 21:25:06 -07001827 private void sendPostSwitchToHalLocked(@UserIdInt int userId) {
felipealf7368962020-04-16 12:55:19 -07001828 if (mUserIdForUserSwitchInProcess == UserHandle.USER_NULL
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001829 || mUserIdForUserSwitchInProcess != userId
1830 || mRequestIdForUserSwitchInProcess == 0) {
Mayank Garg7a114c82020-04-08 21:25:06 -07001831 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1832 Log.d(TAG_USER, "No user switch request Id. No android post switch sent.");
1833 }
1834 return;
1835 }
felipealf7368962020-04-16 12:55:19 -07001836 postSwitchHalResponse(mRequestIdForUserSwitchInProcess, mUserIdForUserSwitchInProcess);
1837 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001838 mRequestIdForUserSwitchInProcess = 0;
Mayank Garg7a114c82020-04-08 21:25:06 -07001839 }
1840
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001841 private void handleNotifyAppUserLifecycleListeners(UserLifecycleEvent event) {
1842 int listenersSize = mAppLifecycleListeners.size();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001843 if (listenersSize == 0) {
felipeal2a84d512020-04-06 18:52:15 -07001844 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1845 Log.d(TAG_USER, "No app listener to be notified of " + event);
1846 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001847 return;
1848 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001849 // Must use a different TimingsTraceLog because it's another thread
1850 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1851 Log.d(TAG_USER, "Notifying " + listenersSize + " app listeners of " + event);
1852 }
felipeal2a84d512020-04-06 18:52:15 -07001853 int userId = event.getUserId();
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001854 TimingsTraceLog t = new TimingsTraceLog(TAG_USER, Trace.TRACE_TAG_SYSTEM_SERVER);
felipealde1e16d2020-06-03 13:20:48 -07001855 int eventType = event.getEventType();
1856 t.traceBegin("notify-app-listeners-user-" + userId + "-event-" + eventType);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001857 for (int i = 0; i < listenersSize; i++) {
1858 int uid = mAppLifecycleListeners.keyAt(i);
felipealde1e16d2020-06-03 13:20:48 -07001859
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001860 IResultReceiver listener = mAppLifecycleListeners.valueAt(i);
1861 Bundle data = new Bundle();
felipealde1e16d2020-06-03 13:20:48 -07001862 data.putInt(CarUserManager.BUNDLE_PARAM_ACTION, eventType);
Yan Zhue7921522020-04-16 15:59:25 -07001863
felipealde1e16d2020-06-03 13:20:48 -07001864 int fromUserId = event.getPreviousUserId();
1865 if (fromUserId != UserHandle.USER_NULL) {
1866 data.putInt(CarUserManager.BUNDLE_PARAM_PREVIOUS_USER_ID, fromUserId);
Yan Zhue7921522020-04-16 15:59:25 -07001867 }
1868
felipeal2a84d512020-04-06 18:52:15 -07001869 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001870 Log.d(TAG_USER, "Notifying listener for uid " + uid);
felipeal2a84d512020-04-06 18:52:15 -07001871 }
felipealde1e16d2020-06-03 13:20:48 -07001872 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_NOTIFY_APP_LIFECYCLE_LISTENER,
1873 uid, eventType, fromUserId, userId);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001874 try {
felipealde1e16d2020-06-03 13:20:48 -07001875 t.traceBegin("notify-app-listener-uid-" + uid);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001876 listener.send(userId, data);
1877 } catch (RemoteException e) {
1878 Log.e(TAG_USER, "Error calling lifecycle listener", e);
1879 } finally {
1880 t.traceEnd();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001881 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001882 }
1883 t.traceEnd(); // notify-app-listeners-user-USERID-event-EVENT_TYPE
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001884 }
1885
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001886 private void handleNotifyServiceUserLifecycleListeners(UserLifecycleEvent event) {
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001887 TimingsTraceLog t = new TimingsTraceLog(TAG_USER, Trace.TRACE_TAG_SYSTEM_SERVER);
1888 if (mUserLifecycleListeners.isEmpty()) {
felipeal2a84d512020-04-06 18:52:15 -07001889 Log.w(TAG_USER, "Not notifying internal UserLifecycleListeners");
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001890 return;
felipeal2a84d512020-04-06 18:52:15 -07001891 } else if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1892 Log.d(TAG_USER, "Notifying " + mUserLifecycleListeners.size() + " service listeners of "
1893 + event);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001894 }
felipeal2a84d512020-04-06 18:52:15 -07001895
felipealde1e16d2020-06-03 13:20:48 -07001896 int userId = event.getUserId();
1897 int eventType = event.getEventType();
1898 t.traceBegin("notify-listeners-user-" + userId + "-event-" + eventType);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001899 for (UserLifecycleListener listener : mUserLifecycleListeners) {
felipeal2a84d512020-04-06 18:52:15 -07001900 String listenerName = FunctionalUtils.getLambdaName(listener);
felipealde1e16d2020-06-03 13:20:48 -07001901 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_NOTIFY_INTERNAL_LIFECYCLE_LISTENER,
1902 listenerName, eventType, event.getPreviousUserId(), userId);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001903 try {
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001904 t.traceBegin("notify-listener-" + listenerName);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001905 listener.onEvent(event);
1906 } catch (RuntimeException e) {
1907 Log.e(TAG_USER,
felipeal2a84d512020-04-06 18:52:15 -07001908 "Exception raised when invoking onEvent for " + listenerName, e);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001909 } finally {
1910 t.traceEnd();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001911 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001912 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001913 t.traceEnd(); // notify-listeners-user-USERID-event-EVENT_TYPE
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001914 }
1915
Mayank Garge5de0f92020-04-23 21:38:38 -07001916 private void onUserSwitching(@UserIdInt int fromUserId, @UserIdInt int toUserId) {
Eric Jeong40f8fa32020-05-12 12:23:33 -07001917 Log.i(TAG_USER, "onUserSwitching() callback for user " + toUserId);
Felipe Leme5528ff72020-02-10 19:05:14 -08001918 TimingsTraceLog t = new TimingsTraceLog(TAG_USER, Trace.TRACE_TAG_SYSTEM_SERVER);
Mayank Garge5de0f92020-04-23 21:38:38 -07001919 t.traceBegin("onUserSwitching-" + toUserId);
Felipe Leme5528ff72020-02-10 19:05:14 -08001920
Mayank Garge5de0f92020-04-23 21:38:38 -07001921 // Switch HAL users if user switch is not requested by CarUserService
1922 notifyHalLegacySwitch(fromUserId, toUserId);
1923
Mayank Garge90a4082020-09-30 12:57:34 -07001924 mInitialUserSetter.setLastActiveUser(toUserId);
felipealbf327652020-06-03 11:33:29 -07001925
Eric Jeongc91f9452019-08-30 15:04:21 -07001926 if (mLastPassengerId != UserHandle.USER_NULL) {
1927 stopPassengerInternal(mLastPassengerId, false);
1928 }
1929 if (mEnablePassengerSupport && isPassengerDisplayAvailable()) {
1930 setupPassengerUser();
Mayank Garge5de0f92020-04-23 21:38:38 -07001931 startFirstPassenger(toUserId);
Eric Jeongc91f9452019-08-30 15:04:21 -07001932 }
felipeal98900c82020-04-09 09:05:02 -07001933 t.traceEnd();
Pavel Maltsev17e81832019-04-04 14:38:41 -07001934 }
1935
Mayank Garge5de0f92020-04-23 21:38:38 -07001936 private void notifyHalLegacySwitch(@UserIdInt int fromUserId, @UserIdInt int toUserId) {
1937 synchronized (mLockUser) {
felipeal7d12ee22020-06-05 09:30:19 -07001938 if (mUserIdForUserSwitchInProcess != UserHandle.USER_NULL) {
1939 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1940 Log.d(TAG, "notifyHalLegacySwitch(" + fromUserId + ", " + toUserId
1941 + "): not needed, normal switch for " + mUserIdForUserSwitchInProcess);
1942 }
1943 return;
1944 }
Mayank Garge5de0f92020-04-23 21:38:38 -07001945 }
1946
Mayank Garg9ed099e2020-06-04 16:05:20 -07001947 if (!isUserHalSupported()) return;
1948
Mayank Garge5de0f92020-04-23 21:38:38 -07001949 // switch HAL user
felipeal7d12ee22020-06-05 09:30:19 -07001950 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager, fromUserId);
Mayank Gargeb37d092020-06-02 14:37:57 -07001951 SwitchUserRequest request = createUserSwitchRequest(toUserId, usersInfo);
1952 mHal.legacyUserSwitch(request);
Mayank Garge5de0f92020-04-23 21:38:38 -07001953 }
1954
Pavel Maltsev17e81832019-04-04 14:38:41 -07001955 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -07001956 * 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 -08001957 * run inside this call.
Eric Jeong1545f3b2019-09-16 13:56:52 -07001958 *
Keun-young Parkd462a912019-02-11 08:53:42 -08001959 * @param r Runnable to run.
1960 */
Eric Jeong1545f3b2019-09-16 13:56:52 -07001961 public void runOnUser0Unlock(@NonNull Runnable r) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00001962 Objects.requireNonNull(r, "runnable cannot be null");
Keun-young Parkd462a912019-02-11 08:53:42 -08001963 boolean runNow = false;
Eric Jeongc91f9452019-08-30 15:04:21 -07001964 synchronized (mLockUser) {
Keun-young Parkd462a912019-02-11 08:53:42 -08001965 if (mUser0Unlocked) {
1966 runNow = true;
1967 } else {
1968 mUser0UnlockTasks.add(r);
1969 }
1970 }
1971 if (runNow) {
1972 r.run();
1973 }
1974 }
1975
Keun young Parkf3523cd2019-04-08 10:09:17 -07001976 @VisibleForTesting
Eric Jeong1545f3b2019-09-16 13:56:52 -07001977 @NonNull
1978 ArrayList<Integer> getBackgroundUsersToRestart() {
1979 ArrayList<Integer> backgroundUsersToRestart = null;
Eric Jeongc91f9452019-08-30 15:04:21 -07001980 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001981 backgroundUsersToRestart = new ArrayList<>(mBackgroundUsersToRestart);
1982 }
1983 return backgroundUsersToRestart;
1984 }
1985
Ying Zheng1ab32b62018-06-26 12:47:26 -07001986 private void setSystemUserRestrictions() {
Ying Zheng1ab32b62018-06-26 12:47:26 -07001987 // Disable Location service for system user.
1988 LocationManager locationManager =
1989 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
Anthony Hugh04ee04f2019-12-17 16:11:33 -08001990 locationManager.setLocationEnabledForUser(
1991 /* enabled= */ false, UserHandle.of(UserHandle.USER_SYSTEM));
Ying Zheng1ab32b62018-06-26 12:47:26 -07001992 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07001993
1994 /**
Anthony Hugh6fed1e92019-10-22 16:22:03 -07001995 * Assigns a default icon to a user according to the user's id.
1996 *
1997 * @param userInfo User whose avatar is set to default icon.
Anthony Hugh6fed1e92019-10-22 16:22:03 -07001998 */
Eric Jeongb2dc6ff2020-06-05 17:00:26 -07001999 private void assignDefaultIcon(UserInfo userInfo) {
Anthony Hugh6fed1e92019-10-22 16:22:03 -07002000 int idForIcon = userInfo.isGuest() ? UserHandle.USER_NULL : userInfo.id;
2001 Bitmap bitmap = UserIcons.convertToBitmap(
2002 UserIcons.getDefaultUserIcon(mContext.getResources(), idForIcon, false));
2003 mUserManager.setUserIcon(userInfo.id, bitmap);
Anthony Hugh6fed1e92019-10-22 16:22:03 -07002004 }
2005
Eric Jeong1545f3b2019-09-16 13:56:52 -07002006 private interface UserFilter {
2007 boolean isEligibleUser(UserInfo user);
2008 }
2009
2010 /** Returns all users who are matched by the given filter. */
2011 private List<UserInfo> getUsers(UserFilter filter) {
Colin Cross0df71ea2020-08-27 04:12:26 +00002012 List<UserInfo> users = mUserManager.getAliveUsers();
Eric Jeong1545f3b2019-09-16 13:56:52 -07002013
2014 for (Iterator<UserInfo> iterator = users.iterator(); iterator.hasNext(); ) {
2015 UserInfo user = iterator.next();
2016 if (!filter.isEligibleUser(user)) {
2017 iterator.remove();
2018 }
2019 }
2020 return users;
2021 }
2022
felipeal2d0483c2019-11-02 14:07:22 -07002023 private static void checkManageUsersOrDumpPermission(String message) {
Felipe Leme55236722020-10-16 16:54:32 -07002024 checkHasAtLeastOnePermissionGranted(message,
felipeal2d0483c2019-11-02 14:07:22 -07002025 android.Manifest.permission.MANAGE_USERS,
2026 android.Manifest.permission.DUMP);
2027 }
2028
Felipe Leme5528ff72020-02-10 19:05:14 -08002029 private void checkInteractAcrossUsersPermission(String message) {
Felipe Leme55236722020-10-16 16:54:32 -07002030 checkHasAtLeastOnePermissionGranted(message,
2031 android.Manifest.permission.INTERACT_ACROSS_USERS,
Felipe Leme5528ff72020-02-10 19:05:14 -08002032 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
2033 }
2034
Eric Jeongc91f9452019-08-30 15:04:21 -07002035 private int getNumberOfManagedProfiles(@UserIdInt int userId) {
Colin Cross0df71ea2020-08-27 04:12:26 +00002036 List<UserInfo> users = mUserManager.getAliveUsers();
Eric Jeongc91f9452019-08-30 15:04:21 -07002037 // Count all users that are managed profiles of the given user.
2038 int managedProfilesCount = 0;
2039 for (UserInfo user : users) {
2040 if (user.isManagedProfile() && user.profileGroupId == userId) {
2041 managedProfilesCount++;
2042 }
2043 }
2044 return managedProfilesCount;
2045 }
2046
2047 /**
2048 * Starts the first passenger of the given driver and assigns the passenger to the front
2049 * passenger zone.
2050 *
2051 * @param driverId User id of the driver.
2052 * @return whether it succeeds.
2053 */
2054 private boolean startFirstPassenger(@UserIdInt int driverId) {
2055 int zoneId = getAvailablePassengerZone();
2056 if (zoneId == OccupantZoneInfo.INVALID_ZONE_ID) {
2057 Log.w(TAG_USER, "passenger occupant zone is not found");
2058 return false;
2059 }
2060 List<UserInfo> passengers = getPassengers(driverId);
2061 if (passengers.size() < 1) {
2062 Log.w(TAG_USER, "passenger is not found");
2063 return false;
2064 }
2065 // Only one passenger is supported. If there are two or more passengers, the first passenger
2066 // is chosen.
2067 int passengerId = passengers.get(0).id;
2068 if (!startPassenger(passengerId, zoneId)) {
2069 Log.w(TAG_USER, "cannot start passenger " + passengerId);
2070 return false;
2071 }
2072 return true;
2073 }
2074
2075 private int getAvailablePassengerZone() {
2076 int[] occupantTypes = new int[] {CarOccupantZoneManager.OCCUPANT_TYPE_FRONT_PASSENGER,
2077 CarOccupantZoneManager.OCCUPANT_TYPE_REAR_PASSENGER};
2078 for (int occupantType : occupantTypes) {
2079 int zoneId = getZoneId(occupantType);
2080 if (zoneId != OccupantZoneInfo.INVALID_ZONE_ID) {
2081 return zoneId;
2082 }
2083 }
2084 return OccupantZoneInfo.INVALID_ZONE_ID;
2085 }
2086
2087 /**
2088 * Creates a new passenger user when there is no passenger user.
2089 */
2090 private void setupPassengerUser() {
2091 int currentUser = ActivityManager.getCurrentUser();
2092 int profileCount = getNumberOfManagedProfiles(currentUser);
2093 if (profileCount > 0) {
2094 Log.w(TAG_USER, "max profile of user" + currentUser
2095 + " is exceeded: current profile count is " + profileCount);
2096 return;
2097 }
2098 // TODO(b/140311342): Use resource string for the default passenger name.
2099 UserInfo passenger = createPassenger("Passenger", currentUser);
2100 if (passenger == null) {
2101 // Couldn't create user, most likely because there are too many.
2102 Log.w(TAG_USER, "cannot create a passenger user");
2103 return;
2104 }
2105 }
2106
2107 @NonNull
2108 private List<OccupantZoneInfo> getOccupantZones(@OccupantTypeEnum int occupantType) {
2109 ZoneUserBindingHelper helper = null;
2110 synchronized (mLockHelper) {
2111 if (mZoneUserBindingHelper == null) {
2112 Log.w(TAG_USER, "implementation is not delegated");
2113 return new ArrayList<OccupantZoneInfo>();
2114 }
2115 helper = mZoneUserBindingHelper;
2116 }
2117 return helper.getOccupantZones(occupantType);
2118 }
2119
2120 private boolean assignUserToOccupantZone(@UserIdInt int userId, int zoneId) {
2121 ZoneUserBindingHelper helper = null;
2122 synchronized (mLockHelper) {
2123 if (mZoneUserBindingHelper == null) {
2124 Log.w(TAG_USER, "implementation is not delegated");
2125 return false;
2126 }
2127 helper = mZoneUserBindingHelper;
2128 }
2129 return helper.assignUserToOccupantZone(userId, zoneId);
2130 }
2131
2132 private boolean unassignUserFromOccupantZone(@UserIdInt int userId) {
2133 ZoneUserBindingHelper helper = null;
2134 synchronized (mLockHelper) {
2135 if (mZoneUserBindingHelper == null) {
2136 Log.w(TAG_USER, "implementation is not delegated");
2137 return false;
2138 }
2139 helper = mZoneUserBindingHelper;
2140 }
2141 return helper.unassignUserFromOccupantZone(userId);
2142 }
2143
2144 private boolean isPassengerDisplayAvailable() {
2145 ZoneUserBindingHelper helper = null;
2146 synchronized (mLockHelper) {
2147 if (mZoneUserBindingHelper == null) {
2148 Log.w(TAG_USER, "implementation is not delegated");
2149 return false;
2150 }
2151 helper = mZoneUserBindingHelper;
2152 }
2153 return helper.isPassengerDisplayAvailable();
2154 }
2155
2156 /**
2157 * Gets the zone id of the given occupant type. If there are two or more zones, the first found
2158 * zone is returned.
2159 *
2160 * @param occupantType The type of an occupant.
2161 * @return The zone id of the given occupant type. {@link OccupantZoneInfo.INVALID_ZONE_ID},
2162 * if not found.
2163 */
2164 private int getZoneId(@OccupantTypeEnum int occupantType) {
2165 List<OccupantZoneInfo> zoneInfos = getOccupantZones(occupantType);
2166 return (zoneInfos.size() > 0) ? zoneInfos.get(0).zoneId : OccupantZoneInfo.INVALID_ZONE_ID;
2167 }
Mayank Garg9732d602020-08-09 21:02:40 -07002168
2169 /**
2170 * Manages the required number of pre-created users.
2171 */
2172 public void preCreateUsers() {
2173 mUserPreCreator.managePreCreatedUsers();
2174 }
Felipe Leme17799202020-09-03 12:55:53 -07002175
2176 // TODO(b/167698977): members below were copied from UserManagerService; it would be better to
2177 // move them to some internal android.os class instead.
2178
2179 private static final int ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION =
2180 UserInfo.FLAG_MANAGED_PROFILE
2181 | UserInfo.FLAG_PROFILE
2182 | UserInfo.FLAG_EPHEMERAL
2183 | UserInfo.FLAG_RESTRICTED
2184 | UserInfo.FLAG_GUEST
2185 | UserInfo.FLAG_DEMO
2186 | UserInfo.FLAG_FULL;
2187
2188 private static void checkManageUsersPermission(String message) {
2189 if (!hasManageUsersPermission()) {
2190 throw new SecurityException("You need " + MANAGE_USERS + " permission to: " + message);
2191 }
2192 }
2193
2194 private static void checkManageOrCreateUsersPermission(String message) {
2195 if (!hasManageOrCreateUsersPermission()) {
2196 throw new SecurityException(
2197 "You either need " + MANAGE_USERS + " or " + CREATE_USERS + " permission to: "
2198 + message);
2199 }
2200 }
2201
2202 private static void checkManageOrCreateUsersPermission(int creationFlags) {
2203 if ((creationFlags & ~ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION) == 0) {
2204 if (!hasManageOrCreateUsersPermission()) {
2205 throw new SecurityException("You either need " + MANAGE_USERS + " or "
2206 + CREATE_USERS + "permission to create a user with flags "
2207 + creationFlags);
2208 }
2209 } else if (!hasManageUsersPermission()) {
2210 throw new SecurityException("You need " + MANAGE_USERS + " permission to create a user"
2211 + " with flags " + creationFlags);
2212 }
2213 }
2214
2215 private static boolean hasManageUsersPermission() {
2216 final int callingUid = Binder.getCallingUid();
2217 return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
2218 || callingUid == Process.ROOT_UID
2219 || hasPermissionGranted(MANAGE_USERS, callingUid);
2220 }
2221
2222 private static boolean hasManageUsersOrPermission(String alternativePermission) {
2223 final int callingUid = Binder.getCallingUid();
2224 return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
2225 || callingUid == Process.ROOT_UID
2226 || hasPermissionGranted(MANAGE_USERS, callingUid)
2227 || hasPermissionGranted(alternativePermission, callingUid);
2228 }
2229
2230 private static boolean hasManageOrCreateUsersPermission() {
2231 return hasManageUsersOrPermission(CREATE_USERS);
2232 }
2233
2234 private static boolean hasPermissionGranted(String permission, int uid) {
2235 return ActivityManager.checkComponentPermission(permission, uid, /* owningUid= */ -1,
2236 /* exported= */ true) == PackageManager.PERMISSION_GRANTED;
2237 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002238}