blob: 5ffb96ed8dcfa710699f3e88c9012a7f30d61355 [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;
21
Eric Jeong1545f3b2019-09-16 13:56:52 -070022import static com.android.car.CarLog.TAG_USER;
23
24import android.annotation.NonNull;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070025import android.annotation.Nullable;
Eric Jeong1545f3b2019-09-16 13:56:52 -070026import android.annotation.UserIdInt;
Keun young Parkfb656372019-03-12 18:37:55 -070027import android.app.ActivityManager;
Louis Chang3bf2f202020-08-18 13:04:28 +080028import android.app.ActivityTaskManager.RootTaskInfo;
Keun young Parkfb656372019-03-12 18:37:55 -070029import android.app.IActivityManager;
Eric Jeongc91f9452019-08-30 15:04:21 -070030import android.car.CarOccupantZoneManager;
31import android.car.CarOccupantZoneManager.OccupantTypeEnum;
32import android.car.CarOccupantZoneManager.OccupantZoneInfo;
Eric Jeong1545f3b2019-09-16 13:56:52 -070033import android.car.ICarUserService;
jovanak24470652018-09-11 17:51:57 -070034import android.car.settings.CarSettings;
Felipe Leme5528ff72020-02-10 19:05:14 -080035import android.car.user.CarUserManager;
Antonio Kantekc8114752020-03-05 21:37:39 -080036import android.car.user.CarUserManager.UserLifecycleEvent;
37import android.car.user.CarUserManager.UserLifecycleListener;
felipealdfdf8512020-06-01 09:35:45 -070038import android.car.user.UserCreationResult;
felipeal159a2a42020-05-08 10:32:11 -070039import android.car.user.UserIdentificationAssociationResponse;
Mayank Garga55c3092020-05-28 03:19:24 -070040import android.car.user.UserRemovalResult;
felipeale5bf0322020-04-16 15:10:57 -070041import android.car.user.UserSwitchResult;
felipeal19e3d732020-03-18 12:07:32 -070042import android.car.userlib.HalCallback;
43import android.car.userlib.UserHalHelper;
Mayank Garge90a4082020-09-30 12:57:34 -070044import android.car.userlib.UserHelper;
Felipe Leme6b34fc32020-10-26 15:49:17 -070045import android.content.BroadcastReceiver;
Mayank Garga480dd92020-05-14 03:14:57 -070046import android.content.ComponentName;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070047import android.content.Context;
Felipe Leme6b34fc32020-10-26 15:49:17 -070048import android.content.Intent;
49import android.content.IntentFilter;
Mayank Garga480dd92020-05-14 03:14:57 -070050import android.content.pm.PackageManager;
51import android.content.pm.PackageManager.NameNotFoundException;
Eric Jeong1545f3b2019-09-16 13:56:52 -070052import android.content.pm.UserInfo;
felipealdfdf8512020-06-01 09:35:45 -070053import android.content.pm.UserInfo.UserInfoFlag;
Felipe Leme315a53b2020-03-12 10:51:04 -070054import android.content.res.Resources;
Anthony Hugh6fed1e92019-10-22 16:22:03 -070055import android.graphics.Bitmap;
felipealdfdf8512020-06-01 09:35:45 -070056import android.hardware.automotive.vehicle.V2_0.CreateUserRequest;
57import android.hardware.automotive.vehicle.V2_0.CreateUserStatus;
Mayank Garg70732a82020-08-05 20:17:47 -070058import android.hardware.automotive.vehicle.V2_0.InitialUserInfoRequestType;
Felipe Lemec6e3c2a2020-02-19 16:53:57 -080059import android.hardware.automotive.vehicle.V2_0.InitialUserInfoResponseAction;
Mayank Garga55c3092020-05-28 03:19:24 -070060import android.hardware.automotive.vehicle.V2_0.RemoveUserRequest;
Mayank Gargeb37d092020-06-02 14:37:57 -070061import android.hardware.automotive.vehicle.V2_0.SwitchUserRequest;
Mayank Garg59f22192020-03-27 00:51:45 -070062import android.hardware.automotive.vehicle.V2_0.SwitchUserStatus;
felipeal5e3ede42020-04-23 18:04:07 -070063import android.hardware.automotive.vehicle.V2_0.UserIdentificationGetRequest;
64import android.hardware.automotive.vehicle.V2_0.UserIdentificationResponse;
felipeal159a2a42020-05-08 10:32:11 -070065import android.hardware.automotive.vehicle.V2_0.UserIdentificationSetAssociation;
66import android.hardware.automotive.vehicle.V2_0.UserIdentificationSetRequest;
Felipe Lemec6e3c2a2020-02-19 16:53:57 -080067import android.hardware.automotive.vehicle.V2_0.UsersInfo;
Ying Zheng1ab32b62018-06-26 12:47:26 -070068import android.location.LocationManager;
Eric Jeong1545f3b2019-09-16 13:56:52 -070069import android.os.Binder;
Felipe Leme5528ff72020-02-10 19:05:14 -080070import android.os.Bundle;
Antonio Kantek7236a5b2020-04-06 19:53:55 -070071import android.os.Handler;
72import android.os.HandlerThread;
Felipe Leme17799202020-09-03 12:55:53 -070073import android.os.Process;
Keun young Parkfb656372019-03-12 18:37:55 -070074import android.os.RemoteException;
Mayank Garg31e73042020-01-23 00:10:38 -080075import android.os.Trace;
Ying Zhengcf20f442018-06-22 16:54:51 -070076import android.os.UserHandle;
Ying Zheng8f90edb2018-06-13 12:42:31 -070077import android.os.UserManager;
jovanak24470652018-09-11 17:51:57 -070078import android.provider.Settings;
Felipe Lemee3cab982020-03-12 11:39:29 -070079import android.sysprop.CarProperties;
felipeal159a2a42020-05-08 10:32:11 -070080import android.text.TextUtils;
felipeal312416a2020-04-14 12:28:24 -070081import android.util.EventLog;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070082import android.util.Log;
Felipe Leme5528ff72020-02-10 19:05:14 -080083import android.util.SparseArray;
Felipe Leme6b34fc32020-10-26 15:49:17 -070084import android.util.SparseBooleanArray;
Mayank Garg31e73042020-01-23 00:10:38 -080085import android.util.TimingsTraceLog;
Ying Zhengd3cb98e2018-05-11 11:42:48 -070086
87import com.android.car.CarServiceBase;
Keun young Parkb241d022020-04-20 20:31:34 -070088import com.android.car.CarServiceUtils;
Eric Jeongc91f9452019-08-30 15:04:21 -070089import com.android.car.R;
Felipe Leme58412202020-01-09 13:45:33 -080090import com.android.car.hal.UserHalService;
Mayank Gargf59f95b2020-10-01 14:55:11 -070091import com.android.car.internal.common.CommonConstants.UserLifecycleEventType;
Mayank Garg801ea6a2020-09-29 15:43:49 -070092import com.android.car.internal.common.EventLogTags;
93import com.android.car.internal.common.UserHelperLite;
Mayank Garg4bdfbf72020-08-06 13:27:43 -070094import com.android.car.power.CarPowerManagementService;
Mayank Garg665c20b2020-08-07 16:19:28 -070095import com.android.car.user.InitialUserSetter.InitialUserInfo;
Keun-young Parkd462a912019-02-11 08:53:42 -080096import com.android.internal.annotations.GuardedBy;
Keun young Parkf3523cd2019-04-08 10:09:17 -070097import com.android.internal.annotations.VisibleForTesting;
felipeale5bf0322020-04-16 15:10:57 -070098import com.android.internal.infra.AndroidFuture;
Felipe Leme5528ff72020-02-10 19:05:14 -080099import com.android.internal.os.IResultReceiver;
felipeal5e3ede42020-04-23 18:04:07 -0700100import com.android.internal.util.ArrayUtils;
felipeal2a84d512020-04-06 18:52:15 -0700101import com.android.internal.util.FunctionalUtils;
Mayank Garge19c2922020-03-30 18:05:53 -0700102import com.android.internal.util.Preconditions;
Anthony Hugh6fed1e92019-10-22 16:22:03 -0700103import com.android.internal.util.UserIcons;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700104
105import java.io.PrintWriter;
Keun-young Parkd462a912019-02-11 08:53:42 -0800106import java.util.ArrayList;
felipeal2d0483c2019-11-02 14:07:22 -0700107import java.util.Arrays;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700108import java.util.Iterator;
109import java.util.List;
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +0000110import java.util.Objects;
Pavel Maltsev17e81832019-04-04 14:38:41 -0700111import java.util.concurrent.CopyOnWriteArrayList;
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700112import java.util.concurrent.CountDownLatch;
113import java.util.concurrent.TimeUnit;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700114
115/**
116 * User service for cars. Manages users at boot time. Including:
117 *
118 * <ol>
Eric Jeong1545f3b2019-09-16 13:56:52 -0700119 * <li> Creates a user used as driver.
120 * <li> Creates a user used as passenger.
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700121 * <li> Creates a secondary admin user on first run.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700122 * <li> Switch drivers.
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700123 * <ol/>
124 */
Eric Jeong1545f3b2019-09-16 13:56:52 -0700125public final class CarUserService extends ICarUserService.Stub implements CarServiceBase {
Felipe Leme5528ff72020-02-10 19:05:14 -0800126
felipealf7368962020-04-16 12:55:19 -0700127 private static final String TAG = TAG_USER;
128
Felipe Lemeabbf2da2020-02-24 18:25:29 -0800129 /** {@code int} extra used to represent a user id in a {@link IResultReceiver} response. */
Mayank Garg8f932822020-09-17 16:09:12 -0700130 public static final String BUNDLE_USER_ID = "user.id";
Felipe Lemeabbf2da2020-02-24 18:25:29 -0800131 /** {@code int} extra used to represent user flags in a {@link IResultReceiver} response. */
Mayank Garg8f932822020-09-17 16:09:12 -0700132 public static final String BUNDLE_USER_FLAGS = "user.flags";
Felipe Lemeabbf2da2020-02-24 18:25:29 -0800133 /** {@code String} extra used to represent a user name in a {@link IResultReceiver} response. */
Mayank Garg8f932822020-09-17 16:09:12 -0700134 public static final String BUNDLE_USER_NAME = "user.name";
felipeala68ecef2020-05-19 12:46:08 -0700135 /**
136 * {@code int} extra used to represent the user locales in a {@link IResultReceiver} response.
137 */
Mayank Garg8f932822020-09-17 16:09:12 -0700138 public static final String BUNDLE_USER_LOCALES = "user.locales";
felipeala68ecef2020-05-19 12:46:08 -0700139 /**
140 * {@code int} extra used to represent the info action in a {@link IResultReceiver} response.
141 */
Mayank Garg8f932822020-09-17 16:09:12 -0700142 public static final String BUNDLE_INITIAL_INFO_ACTION = "initial_info.action";
Felipe Leme5528ff72020-02-10 19:05:14 -0800143
Mayank Garg9ed099e2020-06-04 16:05:20 -0700144 public static final String VEHICLE_HAL_NOT_SUPPORTED = "Vehicle Hal not supported.";
145
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700146 private final Context mContext;
Keun young Parkfb656372019-03-12 18:37:55 -0700147 private final IActivityManager mAm;
Anthony Hugh9932a252019-06-12 16:19:56 -0700148 private final UserManager mUserManager;
149 private final int mMaxRunningUsers;
Mayank Garg70732a82020-08-05 20:17:47 -0700150 private final InitialUserSetter mInitialUserSetter;
Eric Jeongc91f9452019-08-30 15:04:21 -0700151 private final boolean mEnablePassengerSupport;
Mayank Garg9732d602020-08-09 21:02:40 -0700152 private final UserPreCreator mUserPreCreator;
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700153
Eric Jeongc91f9452019-08-30 15:04:21 -0700154 private final Object mLockUser = new Object();
155 @GuardedBy("mLockUser")
Keun-young Parkd462a912019-02-11 08:53:42 -0800156 private boolean mUser0Unlocked;
Eric Jeongc91f9452019-08-30 15:04:21 -0700157 @GuardedBy("mLockUser")
Keun-young Parkd462a912019-02-11 08:53:42 -0800158 private final ArrayList<Runnable> mUser0UnlockTasks = new ArrayList<>();
Eric Jeongc91f9452019-08-30 15:04:21 -0700159 // Only one passenger is supported.
160 @GuardedBy("mLockUser")
161 private @UserIdInt int mLastPassengerId;
Keun young Parkf3523cd2019-04-08 10:09:17 -0700162 /**
163 * Background users that will be restarted in garage mode. This list can include the
Mayank Garg31e73042020-01-23 00:10:38 -0800164 * current foreground user but the current foreground user should not be restarted.
Keun young Parkf3523cd2019-04-08 10:09:17 -0700165 */
Eric Jeongc91f9452019-08-30 15:04:21 -0700166 @GuardedBy("mLockUser")
Keun young Parkf3523cd2019-04-08 10:09:17 -0700167 private final ArrayList<Integer> mBackgroundUsersToRestart = new ArrayList<>();
168 /**
169 * Keep the list of background users started here. This is wholly for debugging purpose.
170 */
Eric Jeongc91f9452019-08-30 15:04:21 -0700171 @GuardedBy("mLockUser")
Keun young Parkf3523cd2019-04-08 10:09:17 -0700172 private final ArrayList<Integer> mBackgroundUsersRestartedHere = new ArrayList<>();
173
Felipe Leme58412202020-01-09 13:45:33 -0800174 private final UserHalService mHal;
175
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700176 // HandlerThread and Handler used when notifying app listeners (mAppLifecycleListeners).
Keun young Parkb241d022020-04-20 20:31:34 -0700177 private final HandlerThread mHandlerThread = CarServiceUtils.getHandlerThread(
178 getClass().getSimpleName());
179 private final Handler mHandler = new Handler(mHandlerThread.getLooper());
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700180
Felipe Leme5528ff72020-02-10 19:05:14 -0800181 /**
Antonio Kantekc8114752020-03-05 21:37:39 -0800182 * List of listeners to be notified on new user activities events.
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700183 * This collection should be accessed and manipulated by mHandlerThread only.
Antonio Kantekc8114752020-03-05 21:37:39 -0800184 */
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700185 private final List<UserLifecycleListener> mUserLifecycleListeners = new ArrayList<>();
Antonio Kantekc8114752020-03-05 21:37:39 -0800186
187 /**
Felipe Leme5528ff72020-02-10 19:05:14 -0800188 * List of lifecycle listeners by uid.
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700189 * This collection should be accessed and manipulated by mHandlerThread only.
Felipe Leme5528ff72020-02-10 19:05:14 -0800190 */
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700191 private final SparseArray<IResultReceiver> mAppLifecycleListeners = new SparseArray<>();
Felipe Leme5528ff72020-02-10 19:05:14 -0800192
Mayank Garg7a114c82020-04-08 21:25:06 -0700193 /**
194 * User Id for the user switch in process, if any.
195 */
196 @GuardedBy("mLockUser")
felipealf7368962020-04-16 12:55:19 -0700197 private int mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
Mayank Garg7a114c82020-04-08 21:25:06 -0700198 /**
199 * Request Id for the user switch in process, if any.
200 */
201 @GuardedBy("mLockUser")
felipealf7368962020-04-16 12:55:19 -0700202 private int mRequestIdForUserSwitchInProcess;
Felipe Lemee3cab982020-03-12 11:39:29 -0700203 private final int mHalTimeoutMs = CarProperties.user_hal_timeout().orElse(5_000);
204
Eric Jeongc91f9452019-08-30 15:04:21 -0700205 private final CopyOnWriteArrayList<PassengerCallback> mPassengerCallbacks =
206 new CopyOnWriteArrayList<>();
207
Mayank Garg7e1450b2020-08-07 18:15:15 -0700208 // TODO(b/163566866): Use mSwitchGuestUserBeforeSleep for new create guest request
209 private final boolean mSwitchGuestUserBeforeSleep;
210
felipeal61ce3732020-04-03 11:01:00 -0700211 @Nullable
212 @GuardedBy("mLockUser")
213 private UserInfo mInitialUser;
214
Mayank Garg587f1942020-05-06 01:41:34 -0700215 private IResultReceiver mUserSwitchUiReceiver;
216
Eric Jeongc91f9452019-08-30 15:04:21 -0700217 /** Interface for callbaks related to passenger activities. */
218 public interface PassengerCallback {
219 /** Called when passenger is started at a certain zone. */
220 void onPassengerStarted(@UserIdInt int passengerId, int zoneId);
221 /** Called when passenger is stopped. */
222 void onPassengerStopped(@UserIdInt int passengerId);
223 }
224
225 /** Interface for delegating zone-related implementation to CarOccupantZoneService. */
226 public interface ZoneUserBindingHelper {
227 /** Gets occupant zones corresponding to the occupant type. */
228 @NonNull
229 List<OccupantZoneInfo> getOccupantZones(@OccupantTypeEnum int occupantType);
230 /** Assigns the user to the occupant zone. */
231 boolean assignUserToOccupantZone(@UserIdInt int userId, int zoneId);
232 /** Makes the occupant zone unoccupied. */
233 boolean unassignUserFromOccupantZone(@UserIdInt int userId);
234 /** Returns whether there is a passenger display. */
235 boolean isPassengerDisplayAvailable();
236 }
237
238 private final Object mLockHelper = new Object();
239 @GuardedBy("mLockHelper")
240 private ZoneUserBindingHelper mZoneUserBindingHelper;
241
Felipe Leme6b34fc32020-10-26 15:49:17 -0700242 private final BroadcastReceiver mUserLifecycleReceiver = new BroadcastReceiver() {
243 @Override
244 public void onReceive(Context context, Intent intent) {
245 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
246 Log.d(TAG_USER, "onReceive: " + intent);
247 }
248 switch(intent.getAction()) {
249 case Intent.ACTION_USER_REMOVED:
250 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
251 notifyHalUserRemoved(userId);
252 break;
253 default:
254 Log.w(TAG, "received unexpected intent: " + intent);
255 }
256 }
257 };
258
259 /** Map used to avoid calling UserHAL when a user was removed because HAL creation failed. */
260 @GuardedBy("mLockUser")
261 private final SparseBooleanArray mFailedToCreateUserIds = new SparseBooleanArray(1);
262
Felipe Leme58412202020-01-09 13:45:33 -0800263 public CarUserService(@NonNull Context context, @NonNull UserHalService hal,
Mayank Garge90a4082020-09-30 12:57:34 -0700264 @NonNull UserManager userManager,
Mayank Garg71661ea2020-04-29 01:25:03 -0700265 @NonNull IActivityManager am, int maxRunningUsers) {
Mayank Garge90a4082020-09-30 12:57:34 -0700266 this(context, hal, userManager, am, maxRunningUsers,
Mayank Garg1bb1c382020-09-03 17:11:11 -0700267 /* initialUserSetter= */ null, /* userPreCreator= */ null);
Mayank Garg71661ea2020-04-29 01:25:03 -0700268 }
269
270 @VisibleForTesting
271 CarUserService(@NonNull Context context, @NonNull UserHalService hal,
Mayank Garge90a4082020-09-30 12:57:34 -0700272 @NonNull UserManager userManager,
Mayank Gargccad8062020-08-30 15:05:10 -0700273 @NonNull IActivityManager am, int maxRunningUsers,
Mayank Garg1bb1c382020-09-03 17:11:11 -0700274 @Nullable InitialUserSetter initialUserSetter,
275 @Nullable UserPreCreator userPreCreator) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700276 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
277 Log.d(TAG_USER, "constructed");
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700278 }
279 mContext = context;
Felipe Leme58412202020-01-09 13:45:33 -0800280 mHal = hal;
Keun young Parkf3523cd2019-04-08 10:09:17 -0700281 mAm = am;
282 mMaxRunningUsers = maxRunningUsers;
Anthony Hugh9932a252019-06-12 16:19:56 -0700283 mUserManager = userManager;
Eric Jeongc91f9452019-08-30 15:04:21 -0700284 mLastPassengerId = UserHandle.USER_NULL;
Mayank Garg1bb1c382020-09-03 17:11:11 -0700285 mInitialUserSetter =
286 initialUserSetter == null ? new InitialUserSetter(context, (u) -> setInitialUser(u))
287 : initialUserSetter;
288 mUserPreCreator =
289 userPreCreator == null ? new UserPreCreator(mUserManager) : userPreCreator;
Mayank Garg7e1450b2020-08-07 18:15:15 -0700290 Resources resources = context.getResources();
291 mEnablePassengerSupport = resources.getBoolean(R.bool.enablePassengerSupport);
292 mSwitchGuestUserBeforeSleep = resources.getBoolean(
293 R.bool.config_switchGuestUserBeforeGoingSleep);
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700294 }
295
296 @Override
297 public void init() {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700298 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
299 Log.d(TAG_USER, "init");
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700300 }
Felipe Leme6b34fc32020-10-26 15:49:17 -0700301 mContext.registerReceiver(mUserLifecycleReceiver,
302 new IntentFilter(Intent.ACTION_USER_REMOVED));
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700303 }
304
305 @Override
306 public void release() {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700307 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
308 Log.d(TAG_USER, "release");
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700309 }
Felipe Leme6b34fc32020-10-26 15:49:17 -0700310 mContext.unregisterReceiver(mUserLifecycleReceiver);
Ying Zhengd3cb98e2018-05-11 11:42:48 -0700311 }
312
313 @Override
Eric Jeong1545f3b2019-09-16 13:56:52 -0700314 public void dump(@NonNull PrintWriter writer) {
felipeal2d0483c2019-11-02 14:07:22 -0700315 checkAtLeastOnePermission("dump()", android.Manifest.permission.DUMP);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700316 writer.println("*CarUserService*");
Felipe Leme5528ff72020-02-10 19:05:14 -0800317 String indent = " ";
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700318 handleDumpListeners(writer, indent);
Mayank Garg587f1942020-05-06 01:41:34 -0700319 writer.printf("User switch UI receiver %s\n", mUserSwitchUiReceiver);
Eric Jeongc91f9452019-08-30 15:04:21 -0700320 synchronized (mLockUser) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700321 writer.println("User0Unlocked: " + mUser0Unlocked);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700322 writer.println("BackgroundUsersToRestart: " + mBackgroundUsersToRestart);
323 writer.println("BackgroundUsersRestarted: " + mBackgroundUsersRestartedHere);
Felipe Leme6b34fc32020-10-26 15:49:17 -0700324 if (mFailedToCreateUserIds.size() > 0) {
325 writer.println("FailedToCreateUserIds: " + mFailedToCreateUserIds);
326 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700327 }
328 writer.println("MaxRunningUsers: " + mMaxRunningUsers);
329 List<UserInfo> allDrivers = getAllDrivers();
330 int driversSize = allDrivers.size();
331 writer.println("NumberOfDrivers: " + driversSize);
332 for (int i = 0; i < driversSize; i++) {
333 int driverId = allDrivers.get(i).id;
334 writer.print(indent + "#" + i + ": id=" + driverId);
335 List<UserInfo> passengers = getPassengers(driverId);
336 int passengersSize = passengers.size();
337 writer.print(" NumberPassengers: " + passengersSize);
338 if (passengersSize > 0) {
339 writer.print(" [");
340 for (int j = 0; j < passengersSize; j++) {
341 writer.print(passengers.get(j).id);
342 if (j < passengersSize - 1) {
343 writer.print(" ");
felipeal2d0483c2019-11-02 14:07:22 -0700344 }
felipeal2d0483c2019-11-02 14:07:22 -0700345 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700346 writer.print("]");
felipeal2d0483c2019-11-02 14:07:22 -0700347 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700348 writer.println();
349 }
350 writer.printf("EnablePassengerSupport: %s\n", mEnablePassengerSupport);
351 writer.printf("User HAL timeout: %dms\n", mHalTimeoutMs);
352 writer.printf("Initial user: %s\n", mInitialUser);
felipealbf327652020-06-03 11:33:29 -0700353
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700354 writer.println("Relevant overlayable properties");
355 Resources res = mContext.getResources();
356 writer.printf("%sowner_name=%s\n", indent,
357 res.getString(com.android.internal.R.string.owner_name));
358 writer.printf("%sdefault_guest_name=%s\n", indent,
359 res.getString(R.string.default_guest_name));
felipealf7368962020-04-16 12:55:19 -0700360 writer.printf("User switch in process=%d\n", mUserIdForUserSwitchInProcess);
Mayank Garg7a114c82020-04-08 21:25:06 -0700361 writer.printf("Request Id for the user switch in process=%d\n ",
362 mRequestIdForUserSwitchInProcess);
Mayank Garga480dd92020-05-14 03:14:57 -0700363 writer.printf("System UI package name=%s\n", getSystemUiPackageName());
felipeale8c5dce2020-04-15 11:27:06 -0700364
felipealbf327652020-06-03 11:33:29 -0700365 writer.println("Relevant Global settings");
366 dumpGlobalProperty(writer, indent, CarSettings.Global.LAST_ACTIVE_USER_ID);
367 dumpGlobalProperty(writer, indent, CarSettings.Global.LAST_ACTIVE_PERSISTENT_USER_ID);
368
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700369 mInitialUserSetter.dump(writer);
felipeale8c5dce2020-04-15 11:27:06 -0700370 }
371
felipealbf327652020-06-03 11:33:29 -0700372 private void dumpGlobalProperty(PrintWriter writer, String indent, String property) {
373 String value = Settings.Global.getString(mContext.getContentResolver(), property);
374 writer.printf("%s%s=%s\n", indent, property, value);
375 }
376
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700377 private void handleDumpListeners(@NonNull PrintWriter writer, String indent) {
378 CountDownLatch latch = new CountDownLatch(1);
379 mHandler.post(() -> {
felipealde1e16d2020-06-03 13:20:48 -0700380 handleDumpServiceLifecycleListeners(writer);
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700381 handleDumpAppLifecycleListeners(writer, indent);
382 latch.countDown();
383 });
384 int timeout = 5;
385 try {
386 if (!latch.await(timeout, TimeUnit.SECONDS)) {
387 writer.printf("Handler thread didn't respond in %ds when dumping listeners\n",
388 timeout);
389 }
390 } catch (InterruptedException e) {
391 Thread.currentThread().interrupt();
392 writer.println("Interrupted waiting for handler thread to dump app and user listeners");
393 }
394 }
395
felipealde1e16d2020-06-03 13:20:48 -0700396 private void handleDumpServiceLifecycleListeners(@NonNull PrintWriter writer) {
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700397 if (mUserLifecycleListeners.isEmpty()) {
felipealde1e16d2020-06-03 13:20:48 -0700398 writer.println("No lifecycle listeners for internal services");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700399 return;
400 }
felipealde1e16d2020-06-03 13:20:48 -0700401 int size = mUserLifecycleListeners.size();
402 writer.printf("%d lifecycle listener%s for services\n", size, size == 1 ? "" : "s");
403 String indent = " ";
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700404 for (UserLifecycleListener listener : mUserLifecycleListeners) {
felipealde1e16d2020-06-03 13:20:48 -0700405 writer.printf("%s%s\n", indent, FunctionalUtils.getLambdaName(listener));
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700406 }
407 }
408
409 private void handleDumpAppLifecycleListeners(@NonNull PrintWriter writer, String indent) {
felipealde1e16d2020-06-03 13:20:48 -0700410 int size = mAppLifecycleListeners.size();
411 if (size == 0) {
412 writer.println("No lifecycle listeners for apps");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700413 return;
414 }
felipealde1e16d2020-06-03 13:20:48 -0700415 writer.printf("%d lifecycle listener%s for apps \n", size, size == 1 ? "" : "s");
416 for (int i = 0; i < size; i++) {
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700417 int uid = mAppLifecycleListeners.keyAt(i);
418 IResultReceiver listener = mAppLifecycleListeners.valueAt(i);
felipealde1e16d2020-06-03 13:20:48 -0700419 writer.printf("%suid: %d\n", indent, uid);
Keun-young Parkd462a912019-02-11 08:53:42 -0800420 }
Eric Jeong1545f3b2019-09-16 13:56:52 -0700421 }
422
423 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700424 * @see ExperimentalCarUserManager.createDriver
Eric Jeong1545f3b2019-09-16 13:56:52 -0700425 */
426 @Override
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700427 public AndroidFuture<UserCreationResult> createDriver(@NonNull String name, boolean admin) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700428 checkManageUsersPermission("createDriver");
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +0000429 Objects.requireNonNull(name, "name cannot be null");
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700430
431 AndroidFuture<UserCreationResult> future = new AndroidFuture<UserCreationResult>() {
432 @Override
433 protected void onCompleted(UserCreationResult result, Throwable err) {
434 if (result == null) {
435 Log.w(TAG, "createDriver(" + name + "," + admin + ") failed: " + err);
436 } else {
437 if (result.getStatus() == UserCreationResult.STATUS_SUCCESSFUL) {
438 assignDefaultIcon(result.getUser());
439 }
440 }
441 super.onCompleted(result, err);
442 };
443 };
444 int flags = 0;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700445 if (admin) {
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700446 if (!(mUserManager.isAdminUser() || mUserManager.isSystemUser())) {
447 Log.e(TAG_USER, "Only admin users and system user can create other admins.");
448 sendUserCreationResultFailure(future, UserCreationResult.STATUS_INVALID_REQUEST);
449 return future;
450 }
451 flags = UserInfo.FLAG_ADMIN;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700452 }
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700453 createUser(name, UserInfo.getDefaultUserType(flags), flags, mHalTimeoutMs, future);
454 return future;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700455 }
456
457 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700458 * @see ExperimentalCarUserManager.createPassenger
Eric Jeong1545f3b2019-09-16 13:56:52 -0700459 */
460 @Override
461 @Nullable
462 public UserInfo createPassenger(@NonNull String name, @UserIdInt int driverId) {
463 checkManageUsersPermission("createPassenger");
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +0000464 Objects.requireNonNull(name, "name cannot be null");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700465 UserInfo driver = mUserManager.getUserInfo(driverId);
466 if (driver == null) {
467 Log.w(TAG_USER, "the driver is invalid");
468 return null;
469 }
470 if (driver.isGuest()) {
471 Log.w(TAG_USER, "a guest driver cannot create a passenger");
472 return null;
473 }
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700474 // createPassenger doesn't use user HAL because user HAL doesn't support profile user yet.
Bookatz42fb1a62019-10-30 11:45:01 -0700475 UserInfo user = mUserManager.createProfileForUser(name,
476 UserManager.USER_TYPE_PROFILE_MANAGED, /* flags */ 0, driverId);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700477 if (user == null) {
478 // Couldn't create user, most likely because there are too many.
479 Log.w(TAG_USER, "can't create a profile for user" + driverId);
480 return null;
481 }
482 // Passenger user should be a non-admin user.
Mayank Garge90a4082020-09-30 12:57:34 -0700483 UserHelper.setDefaultNonAdminRestrictions(mContext, user, /* enable= */ true);
Anthony Hugh6fed1e92019-10-22 16:22:03 -0700484 assignDefaultIcon(user);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700485 return user;
486 }
487
488 /**
Eric Jeongb2dc6ff2020-06-05 17:00:26 -0700489 * @see ExperimentalCarUserManager.switchDriver
Eric Jeong1545f3b2019-09-16 13:56:52 -0700490 */
491 @Override
Eric Jeong25666cf2020-05-14 15:16:27 -0700492 public void switchDriver(@UserIdInt int driverId, AndroidFuture<UserSwitchResult> receiver) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700493 checkManageUsersPermission("switchDriver");
Mayank Garg94f3eb92020-08-12 12:38:58 -0700494 if (UserHelperLite.isHeadlessSystemUser(driverId)) {
Eric Jeong1545f3b2019-09-16 13:56:52 -0700495 // System user doesn't associate with real person, can not be switched to.
496 Log.w(TAG_USER, "switching to system user in headless system user mode is not allowed");
felipealdfdf8512020-06-01 09:35:45 -0700497 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_INVALID_REQUEST);
Eric Jeong25666cf2020-05-14 15:16:27 -0700498 return;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700499 }
500 int userSwitchable = mUserManager.getUserSwitchability();
501 if (userSwitchable != UserManager.SWITCHABILITY_STATUS_OK) {
502 Log.w(TAG_USER, "current process is not allowed to switch user");
felipealdfdf8512020-06-01 09:35:45 -0700503 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_INVALID_REQUEST);
Eric Jeong25666cf2020-05-14 15:16:27 -0700504 return;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700505 }
Eric Jeong25666cf2020-05-14 15:16:27 -0700506 switchUser(driverId, mHalTimeoutMs, receiver);
Eric Jeong1545f3b2019-09-16 13:56:52 -0700507 }
508
509 /**
Eric Jeonge7916fc2019-12-20 14:03:34 -0800510 * Returns all drivers who can occupy the driving zone. Guest users are included in the list.
511 *
512 * @return the list of {@link UserInfo} who can be a driver on the device.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700513 */
514 @Override
515 @NonNull
516 public List<UserInfo> getAllDrivers() {
felipeal2d0483c2019-11-02 14:07:22 -0700517 checkManageUsersOrDumpPermission("getAllDrivers");
Mayank Garg94f3eb92020-08-12 12:38:58 -0700518 return getUsers((user) -> !UserHelperLite.isHeadlessSystemUser(user.id) && user.isEnabled()
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700519 && !user.isManagedProfile() && !user.isEphemeral());
Eric Jeong1545f3b2019-09-16 13:56:52 -0700520 }
521
522 /**
Eric Jeonge7916fc2019-12-20 14:03:34 -0800523 * Returns all passengers under the given driver.
524 *
525 * @param driverId User id of a driver.
526 * @return the list of {@link UserInfo} who is a passenger under the given driver.
Eric Jeong1545f3b2019-09-16 13:56:52 -0700527 */
528 @Override
529 @NonNull
530 public List<UserInfo> getPassengers(@UserIdInt int driverId) {
felipeal2d0483c2019-11-02 14:07:22 -0700531 checkManageUsersOrDumpPermission("getPassengers");
Eric Jeong1545f3b2019-09-16 13:56:52 -0700532 return getUsers((user) -> {
Mayank Garg94f3eb92020-08-12 12:38:58 -0700533 return !UserHelperLite.isHeadlessSystemUser(user.id) && user.isEnabled()
Eric Jeong40f8fa32020-05-12 12:23:33 -0700534 && user.isManagedProfile() && user.profileGroupId == driverId;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700535 });
536 }
537
538 /**
539 * @see CarUserManager.startPassenger
540 */
541 @Override
542 public boolean startPassenger(@UserIdInt int passengerId, int zoneId) {
543 checkManageUsersPermission("startPassenger");
Eric Jeongc91f9452019-08-30 15:04:21 -0700544 synchronized (mLockUser) {
545 try {
546 if (!mAm.startUserInBackgroundWithListener(passengerId, null)) {
547 Log.w(TAG_USER, "could not start passenger");
548 return false;
549 }
550 } catch (RemoteException e) {
551 // ignore
552 Log.w(TAG_USER, "error while starting passenger", e);
553 return false;
554 }
555 if (!assignUserToOccupantZone(passengerId, zoneId)) {
556 Log.w(TAG_USER, "could not assign passenger to zone");
557 return false;
558 }
559 mLastPassengerId = passengerId;
560 }
561 for (PassengerCallback callback : mPassengerCallbacks) {
562 callback.onPassengerStarted(passengerId, zoneId);
563 }
564 return true;
Eric Jeong1545f3b2019-09-16 13:56:52 -0700565 }
566
567 /**
568 * @see CarUserManager.stopPassenger
569 */
570 @Override
571 public boolean stopPassenger(@UserIdInt int passengerId) {
572 checkManageUsersPermission("stopPassenger");
Eric Jeongc91f9452019-08-30 15:04:21 -0700573 return stopPassengerInternal(passengerId, true);
574 }
575
576 private boolean stopPassengerInternal(@UserIdInt int passengerId, boolean checkCurrentDriver) {
577 synchronized (mLockUser) {
578 UserInfo passenger = mUserManager.getUserInfo(passengerId);
579 if (passenger == null) {
580 Log.w(TAG_USER, "passenger " + passengerId + " doesn't exist");
581 return false;
582 }
583 if (mLastPassengerId != passengerId) {
584 Log.w(TAG_USER, "passenger " + passengerId + " hasn't been started");
585 return true;
586 }
587 if (checkCurrentDriver) {
588 int currentUser = ActivityManager.getCurrentUser();
589 if (passenger.profileGroupId != currentUser) {
590 Log.w(TAG_USER, "passenger " + passengerId
591 + " is not a profile of the current user");
592 return false;
593 }
594 }
595 // Passenger is a profile, so cannot be stopped through activity manager.
596 // Instead, activities started by the passenger are stopped and the passenger is
597 // unassigned from the zone.
598 stopAllTasks(passengerId);
599 if (!unassignUserFromOccupantZone(passengerId)) {
600 Log.w(TAG_USER, "could not unassign user from occupant zone");
601 return false;
602 }
603 mLastPassengerId = UserHandle.USER_NULL;
604 }
605 for (PassengerCallback callback : mPassengerCallbacks) {
606 callback.onPassengerStopped(passengerId);
607 }
608 return true;
609 }
610
611 private void stopAllTasks(@UserIdInt int userId) {
612 try {
Louis Chang3bf2f202020-08-18 13:04:28 +0800613 for (RootTaskInfo info : mAm.getAllRootTaskInfos()) {
614 for (int i = 0; i < info.childTaskIds.length; i++) {
615 if (info.childTaskUserIds[i] == userId) {
616 int taskId = info.childTaskIds[i];
Eric Jeongc91f9452019-08-30 15:04:21 -0700617 if (!mAm.removeTask(taskId)) {
618 Log.w(TAG_USER, "could not remove task " + taskId);
619 }
620 }
621 }
622 }
623 } catch (RemoteException e) {
624 Log.e(TAG_USER, "could not get stack info", e);
625 }
Eric Jeong1545f3b2019-09-16 13:56:52 -0700626 }
627
Felipe Leme5528ff72020-02-10 19:05:14 -0800628 @Override
629 public void setLifecycleListenerForUid(IResultReceiver listener) {
630 int uid = Binder.getCallingUid();
felipeal312416a2020-04-14 12:28:24 -0700631 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SET_LIFECYCLE_LISTENER, uid);
Felipe Leme5528ff72020-02-10 19:05:14 -0800632 checkInteractAcrossUsersPermission("setLifecycleListenerForUid" + uid);
633
634 try {
635 listener.asBinder().linkToDeath(() -> onListenerDeath(uid), 0);
636 } catch (RemoteException e) {
637 Log.wtf(TAG_USER, "Cannot listen to death of " + uid);
638 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700639 mHandler.post(() -> mAppLifecycleListeners.append(uid, listener));
Felipe Leme5528ff72020-02-10 19:05:14 -0800640 }
641
642 private void onListenerDeath(int uid) {
643 Log.i(TAG_USER, "Removing listeners for uid " + uid + " on binder death");
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700644 mHandler.post(() -> mAppLifecycleListeners.remove(uid));
Felipe Leme5528ff72020-02-10 19:05:14 -0800645 }
646
647 @Override
648 public void resetLifecycleListenerForUid() {
649 int uid = Binder.getCallingUid();
felipeal312416a2020-04-14 12:28:24 -0700650 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_RESET_LIFECYCLE_LISTENER, uid);
Felipe Leme5528ff72020-02-10 19:05:14 -0800651 checkInteractAcrossUsersPermission("resetLifecycleListenerForUid-" + uid);
Antonio Kantek7236a5b2020-04-06 19:53:55 -0700652 mHandler.post(() -> mAppLifecycleListeners.remove(uid));
Felipe Leme5528ff72020-02-10 19:05:14 -0800653 }
654
Felipe Lemee3cab982020-03-12 11:39:29 -0700655 /**
felipeal61ce3732020-04-03 11:01:00 -0700656 * Gets the initial foreground user after the device boots or resumes from suspension.
657 *
658 * <p>When the OEM supports the User HAL, the initial user won't be available until the HAL
659 * returns the initial value to {@code CarService} - if HAL takes too long or times out, this
660 * method returns {@code null}.
661 *
662 * <p>If the HAL eventually times out, {@code CarService} will fallback to its default behavior
663 * (like switching to the last active user), and this method will return the result of such
664 * operation.
665 *
666 * <p>Notice that if {@code CarService} crashes, subsequent calls to this method will return
667 * {@code null}.
668 *
669 * @hide
670 */
671 @Nullable
672 public UserInfo getInitialUser() {
673 checkInteractAcrossUsersPermission("getInitialUser");
674 synchronized (mLockUser) {
675 return mInitialUser;
676 }
677 }
678
felipeal61ce3732020-04-03 11:01:00 -0700679 /**
680 * Sets the initial foreground user after the device boots or resumes from suspension.
681 */
682 public void setInitialUser(@Nullable UserInfo user) {
felipeal312416a2020-04-14 12:28:24 -0700683 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SET_INITIAL_USER,
684 user == null ? UserHandle.USER_NULL : user.id);
felipeal61ce3732020-04-03 11:01:00 -0700685 synchronized (mLockUser) {
686 mInitialUser = user;
687 }
688 if (user == null) {
689 // This mean InitialUserSetter failed and could not fallback, so the initial user was
690 // not switched (and most likely is SYSTEM_USER).
691 // TODO(b/153104378): should we set it to ActivityManager.getCurrentUser() instead?
692 Log.wtf(TAG_USER, "Initial user set to null");
693 }
694 }
695
Mayank Garg7e1450b2020-08-07 18:15:15 -0700696 private void initResumeReplaceGuest() {
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700697 int currentUserId = ActivityManager.getCurrentUser();
698 UserInfo currentUser = mUserManager.getUserInfo(currentUserId);
699
700 if (!mInitialUserSetter.canReplaceGuestUser(currentUser)) return; // Not a guest
701
702 InitialUserInfo info =
703 new InitialUserSetter.Builder(InitialUserSetter.TYPE_REPLACE_GUEST).build();
704
705 mInitialUserSetter.set(info);
706 }
707
708 /**
Mayank Garg0baf88a2020-08-30 21:57:36 -0700709 * Calls to switch user at the power suspend.
Mayank Garg7e1450b2020-08-07 18:15:15 -0700710 *
711 * <p><b>Note:</b> Should be used only by {@link CarPowerManagementService}
712 *
Mayank Garg7e1450b2020-08-07 18:15:15 -0700713 */
Mayank Garg0baf88a2020-08-30 21:57:36 -0700714 public void onSuspend() {
Mayank Garg7e1450b2020-08-07 18:15:15 -0700715 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
Mayank Garg0baf88a2020-08-30 21:57:36 -0700716 Log.d(TAG_USER, "onSuspend called.");
Mayank Garg7e1450b2020-08-07 18:15:15 -0700717 }
718
Mayank Garg0baf88a2020-08-30 21:57:36 -0700719 if (mSwitchGuestUserBeforeSleep) {
720 initResumeReplaceGuest();
Mayank Garg7e1450b2020-08-07 18:15:15 -0700721 }
Mayank Garg1bb1c382020-09-03 17:11:11 -0700722
723 preCreateUsers();
Mayank Garg7e1450b2020-08-07 18:15:15 -0700724 }
725
726 /**
Mayank Garg0baf88a2020-08-30 21:57:36 -0700727 * Calls to switch user at the power resume.
728 *
729 * <p>
730 * <b>Note:</b> Should be used only by {@link CarPowerManagementService}
731 *
732 */
733 public void onResume() {
734 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
735 Log.d(TAG_USER, "onResume called.");
736 }
737
738 initBootUser(InitialUserInfoRequestType.RESUME);
739 }
740
741 /**
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700742 * Calls to start user at the android startup.
Mayank Garg70732a82020-08-05 20:17:47 -0700743 */
744 public void initBootUser() {
745 int requestType = getInitialUserInfoRequestType();
Mayank Garg7e1450b2020-08-07 18:15:15 -0700746 initBootUser(requestType);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700747 }
748
Mayank Garg7e1450b2020-08-07 18:15:15 -0700749 private void initBootUser(int requestType) {
750 boolean replaceGuest =
751 requestType == InitialUserInfoRequestType.RESUME && !mSwitchGuestUserBeforeSleep;
Mayank Garg70732a82020-08-05 20:17:47 -0700752 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_REQ, requestType,
753 mHalTimeoutMs);
754 checkManageUsersPermission("startInitialUser");
755
756 if (!isUserHalSupported()) {
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700757 fallbackToDefaultInitialUserBehavior(/* userLocales= */ null, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700758 return;
759 }
760
761 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
762 mHal.getInitialUserInfo(requestType, mHalTimeoutMs, usersInfo, (status, resp) -> {
763 if (resp != null) {
764 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_RESP,
765 status, resp.action, resp.userToSwitchOrCreate.userId,
766 resp.userToSwitchOrCreate.flags, resp.userNameToCreate, resp.userLocales);
767
768 String userLocales = resp.userLocales;
769 InitialUserInfo info;
770 switch (resp.action) {
771 case InitialUserInfoResponseAction.SWITCH:
772 int userId = resp.userToSwitchOrCreate.userId;
773 if (userId <= 0) {
774 Log.w(TAG, "invalid (or missing) user id sent by HAL: " + userId);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700775 fallbackToDefaultInitialUserBehavior(userLocales, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700776 break;
777 }
778 info = new InitialUserSetter.Builder(InitialUserSetter.TYPE_SWITCH)
779 .setUserLocales(userLocales)
780 .setSwitchUserId(userId)
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700781 .setReplaceGuest(replaceGuest)
Mayank Garg70732a82020-08-05 20:17:47 -0700782 .build();
783 mInitialUserSetter.set(info);
784 break;
785
786 case InitialUserInfoResponseAction.CREATE:
787 int halFlags = resp.userToSwitchOrCreate.flags;
788 String userName = resp.userNameToCreate;
789 info = new InitialUserSetter.Builder(InitialUserSetter.TYPE_CREATE)
790 .setUserLocales(userLocales)
791 .setNewUserName(userName)
792 .setNewUserFlags(halFlags)
793 .build();
794 mInitialUserSetter.set(info);
795 break;
796
797 case InitialUserInfoResponseAction.DEFAULT:
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700798 fallbackToDefaultInitialUserBehavior(userLocales, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700799 break;
800 default:
801 Log.w(TAG_USER, "invalid response action on " + resp);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700802 fallbackToDefaultInitialUserBehavior(/* user locale */ null, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700803 break;
804
805 }
806 } else {
807 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_RESP, status);
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700808 fallbackToDefaultInitialUserBehavior(/* user locale */ null, replaceGuest);
Mayank Garg70732a82020-08-05 20:17:47 -0700809 }
810 });
811 }
812
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700813 private void fallbackToDefaultInitialUserBehavior(String userLocales, boolean replaceGuest) {
Mayank Garg70732a82020-08-05 20:17:47 -0700814 InitialUserInfo info = new InitialUserSetter.Builder(
815 InitialUserSetter.TYPE_DEFAULT_BEHAVIOR)
816 .setUserLocales(userLocales)
Mayank Garg4bdfbf72020-08-06 13:27:43 -0700817 .setReplaceGuest(replaceGuest)
Mayank Garg70732a82020-08-05 20:17:47 -0700818 .build();
819 mInitialUserSetter.set(info);
820 }
821
822 @VisibleForTesting
823 int getInitialUserInfoRequestType() {
Mayank Garge90a4082020-09-30 12:57:34 -0700824 if (!mInitialUserSetter.hasInitialUser()) {
Mayank Garg70732a82020-08-05 20:17:47 -0700825 return InitialUserInfoRequestType.FIRST_BOOT;
826 }
827 if (mContext.getPackageManager().isDeviceUpgrading()) {
828 return InitialUserInfoRequestType.FIRST_BOOT_AFTER_OTA;
829 }
830 return InitialUserInfoRequestType.COLD_BOOT;
831 }
832
833 /**
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700834 * Calls the {@link UserHalService} and {@link IActivityManager} for user switch.
835 *
836 * <p>
Mayank Gargb08f6772020-05-01 18:06:48 -0700837 * When everything works well, the workflow is:
838 * <ol>
839 * <li> {@link UserHalService} is called for HAL user switch with ANDROID_SWITCH request
840 * type, current user id, target user id, and a callback.
841 * <li> HAL called back with SUCCESS.
842 * <li> {@link IActivityManager} is called for Android user switch.
843 * <li> Receiver would receive {@code STATUS_SUCCESSFUL}.
844 * <li> Once user is unlocked, {@link UserHalService} is again called with ANDROID_POST_SWITCH
845 * request type, current user id, and target user id. In this case, the current and target
846 * user IDs would be same.
847 * <ol/>
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700848 *
849 * <p>
Mayank Gargb08f6772020-05-01 18:06:48 -0700850 * Corner cases:
851 * <ul>
852 * <li> If target user is already the current user, no user switch is performed and receiver
Mayank Gargef1b9332020-06-11 17:36:56 -0700853 * would receive {@code STATUS_OK_USER_ALREADY_IN_FOREGROUND} right away.
Mayank Gargb08f6772020-05-01 18:06:48 -0700854 * <li> If HAL user switch call fails, no Android user switch. Receiver would receive
855 * {@code STATUS_HAL_INTERNAL_FAILURE}.
856 * <li> If HAL user switch call is successful, but android user switch call fails,
857 * {@link UserHalService} is again called with request type POST_SWITCH, current user id, and
858 * target user id, but in this case the current and target user IDs would be different.
859 * <li> If another user switch request for the same target user is received while previous
860 * request is in process, receiver would receive
861 * {@code STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO} for the new request right away.
862 * <li> If a user switch request is received while another user switch request for different
863 * target user is in process, the previous request would be abandoned and new request will be
864 * processed. No POST_SWITCH would be sent for the previous request.
865 * <ul/>
Mayank Garg59f22192020-03-27 00:51:45 -0700866 *
Mayank Garge19c2922020-03-30 18:05:53 -0700867 * @param targetUserId - target user Id
Mayank Garg59f22192020-03-27 00:51:45 -0700868 * @param timeoutMs - timeout for HAL to wait
869 * @param receiver - receiver for the results
870 */
Mayank Garge19c2922020-03-30 18:05:53 -0700871 @Override
872 public void switchUser(@UserIdInt int targetUserId, int timeoutMs,
felipeale5bf0322020-04-16 15:10:57 -0700873 @NonNull AndroidFuture<UserSwitchResult> receiver) {
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700874 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_REQ, targetUserId, timeoutMs);
Felipe Leme17799202020-09-03 12:55:53 -0700875 checkManageOrCreateUsersPermission("switchUser");
Mayank Garge19c2922020-03-30 18:05:53 -0700876 Objects.requireNonNull(receiver);
877 UserInfo targetUser = mUserManager.getUserInfo(targetUserId);
felipealf7368962020-04-16 12:55:19 -0700878 Preconditions.checkArgument(targetUser != null, "Target user doesn't exist");
Mayank Garg7a114c82020-04-08 21:25:06 -0700879
felipealf7368962020-04-16 12:55:19 -0700880 int currentUser = ActivityManager.getCurrentUser();
881 if (currentUser == targetUserId) {
Mayank Garg0e239142020-04-14 19:16:31 -0700882 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
883 Log.d(TAG_USER, "Current user is same as requested target user: " + targetUserId);
884 }
Mayank Gargef1b9332020-06-11 17:36:56 -0700885 int resultStatus = UserSwitchResult.STATUS_OK_USER_ALREADY_IN_FOREGROUND;
felipealdfdf8512020-06-01 09:35:45 -0700886 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg0e239142020-04-14 19:16:31 -0700887 return;
888 }
889
Mayank Garg9ed099e2020-06-04 16:05:20 -0700890 // If User Hal is not supported, just android user switch.
891 if (!isUserHalSupported()) {
892 try {
893 if (mAm.switchUser(targetUserId)) {
894 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_SUCCESSFUL);
895 return;
896 }
897 } catch (RemoteException e) {
898 // ignore
899 Log.w(TAG_USER,
900 "error while switching user " + targetUser.toFullString(), e);
901 }
902 sendUserSwitchResult(receiver, UserSwitchResult.STATUS_ANDROID_FAILURE);
903 return;
904 }
905
Mayank Garg7a114c82020-04-08 21:25:06 -0700906 synchronized (mLockUser) {
felipealf7368962020-04-16 12:55:19 -0700907 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
908 Log.d(TAG_USER, "switchUser(" + targetUserId + "): currentuser=" + currentUser
909 + ", mUserIdForUserSwitchInProcess=" + mUserIdForUserSwitchInProcess);
910 }
911
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700912 // If there is another request for the same target user, return another request in
913 // process, else {@link mUserIdForUserSwitchInProcess} is updated and {@link
914 // mRequestIdForUserSwitchInProcess} is reset. It is possible that there may be another
915 // user switch request in process for different target user, but that request is now
916 // ignored.
felipealf7368962020-04-16 12:55:19 -0700917 if (mUserIdForUserSwitchInProcess == targetUserId) {
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700918 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
919 Log.d(TAG_USER,
920 "Another user switch request in process for the requested target user: "
921 + targetUserId);
922 }
923
924 int resultStatus = UserSwitchResult.STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO;
felipealdfdf8512020-06-01 09:35:45 -0700925 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg7a114c82020-04-08 21:25:06 -0700926 return;
927 }
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700928 else {
929 mUserIdForUserSwitchInProcess = targetUserId;
930 mRequestIdForUserSwitchInProcess = 0;
931 }
Mayank Garg7a114c82020-04-08 21:25:06 -0700932 }
933
felipealdfdf8512020-06-01 09:35:45 -0700934 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
Mayank Gargeb37d092020-06-02 14:37:57 -0700935 SwitchUserRequest request = createUserSwitchRequest(targetUserId, usersInfo);
936
937 mHal.switchUser(request, timeoutMs, (status, resp) -> {
felipealf7368962020-04-16 12:55:19 -0700938 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
939 Log.d(TAG, "switch response: status="
940 + UserHalHelper.halCallbackStatusToString(status) + ", resp=" + resp);
941 }
942
felipeale5bf0322020-04-16 15:10:57 -0700943 int resultStatus = UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE;
felipealf7368962020-04-16 12:55:19 -0700944
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700945 synchronized (mLockUser) {
946 if (status != HalCallback.STATUS_OK) {
947 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_RESP, status);
948 Log.w(TAG, "invalid callback status ("
949 + UserHalHelper.halCallbackStatusToString(status) + ") for response "
950 + resp);
felipealdfdf8512020-06-01 09:35:45 -0700951 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700952 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
953 return;
954 }
felipealf7368962020-04-16 12:55:19 -0700955
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700956 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_RESP, status, resp.status,
957 resp.errorMessage);
958
959 if (mUserIdForUserSwitchInProcess != targetUserId) {
960 // Another user switch request received while HAL responded. No need to process
961 // this request further
962 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
963 Log.d(TAG_USER, "Another user switch received while HAL responsed. Request "
964 + "abondoned for : " + targetUserId + ". Current user in process: "
965 + mUserIdForUserSwitchInProcess);
felipealf7368962020-04-16 12:55:19 -0700966 }
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700967 resultStatus =
968 UserSwitchResult.STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST;
felipealdfdf8512020-06-01 09:35:45 -0700969 sendUserSwitchResult(receiver, resultStatus);
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700970 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
971 return;
972 }
973
974 switch (resp.status) {
975 case SwitchUserStatus.SUCCESS:
976 boolean switched;
977 try {
978 switched = mAm.switchUser(targetUserId);
979 if (switched) {
Mayank Garg587f1942020-05-06 01:41:34 -0700980 sendUserSwitchUiCallback(targetUserId);
Mayank Garg1f20dcd2020-04-22 17:46:01 -0700981 resultStatus = UserSwitchResult.STATUS_SUCCESSFUL;
982 mRequestIdForUserSwitchInProcess = resp.requestId;
983 } else {
984 resultStatus = UserSwitchResult.STATUS_ANDROID_FAILURE;
985 postSwitchHalResponse(resp.requestId, targetUserId);
986 }
987 } catch (RemoteException e) {
988 // ignore
989 Log.w(TAG_USER,
990 "error while switching user " + targetUser.toFullString(), e);
991 }
992 break;
993 case SwitchUserStatus.FAILURE:
994 // HAL failed to switch user
995 resultStatus = UserSwitchResult.STATUS_HAL_FAILURE;
996 break;
felipealdfdf8512020-06-01 09:35:45 -0700997 default:
998 // Shouldn't happen because UserHalService validates the status
999 Log.wtf(TAG, "Received invalid user switch status from HAL: " + resp);
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001000 }
1001
1002 if (mRequestIdForUserSwitchInProcess == 0) {
1003 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
1004 }
Mayank Garg59f22192020-03-27 00:51:45 -07001005 }
felipealdfdf8512020-06-01 09:35:45 -07001006 sendUserSwitchResult(receiver, resultStatus, resp.errorMessage);
Mayank Garg59f22192020-03-27 00:51:45 -07001007 });
1008 }
1009
Mayank Garga55c3092020-05-28 03:19:24 -07001010 @Override
1011 public UserRemovalResult removeUser(@UserIdInt int userId) {
Felipe Leme17799202020-09-03 12:55:53 -07001012 checkManageOrCreateUsersPermission("removeUser");
Mayank Garga55c3092020-05-28 03:19:24 -07001013 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_REMOVE_USER_REQ, userId);
1014 // If the requested user is the current user, return error.
1015 if (ActivityManager.getCurrentUser() == userId) {
1016 return logAndGetResults(userId,
1017 UserRemovalResult.STATUS_TARGET_USER_IS_CURRENT_USER);
1018 }
1019
1020 // If requested user is the only admin user, return error.
1021 UserInfo userInfo = mUserManager.getUserInfo(userId);
1022 if (userInfo == null) {
1023 return logAndGetResults(userId, UserRemovalResult.STATUS_USER_DOES_NOT_EXIST);
1024 }
1025
1026 android.hardware.automotive.vehicle.V2_0.UserInfo halUser =
1027 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1028 halUser.userId = userInfo.id;
1029 halUser.flags = UserHalHelper.convertFlags(userInfo);
1030 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1031
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001032 // check if the user is last admin user.
1033 boolean isLastAdmin = false;
Mayank Garga55c3092020-05-28 03:19:24 -07001034 if (UserHalHelper.isAdmin(halUser.flags)) {
1035 int size = usersInfo.existingUsers.size();
1036 int totalAdminUsers = 0;
1037 for (int i = 0; i < size; i++) {
1038 if (UserHalHelper.isAdmin(usersInfo.existingUsers.get(i).flags)) {
1039 totalAdminUsers++;
1040 }
1041 }
1042 if (totalAdminUsers == 1) {
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001043 isLastAdmin = true;
Mayank Garga55c3092020-05-28 03:19:24 -07001044 }
1045 }
1046
1047 // First remove user from android and then remove from HAL because HAL remove user is one
1048 // way call.
1049 if (!mUserManager.removeUser(userId)) {
1050 return logAndGetResults(userId, UserRemovalResult.STATUS_ANDROID_FAILURE);
1051 }
1052
Mayank Garge9b7d2c2020-09-15 12:36:06 -07001053 if (isLastAdmin) {
1054 Log.w(TAG_USER, "Last admin user successfully removed. User Id: " + userId);
1055 }
1056
1057 return logAndGetResults(userId,
1058 isLastAdmin ? UserRemovalResult.STATUS_SUCCESSFUL_LAST_ADMIN_REMOVED
1059 : UserRemovalResult.STATUS_SUCCESSFUL);
Mayank Garga55c3092020-05-28 03:19:24 -07001060 }
1061
Felipe Leme6b34fc32020-10-26 15:49:17 -07001062 private void notifyHalUserRemoved(@UserIdInt int userId) {
1063 if (!isUserHalSupported()) return;
1064
1065 if (userId == UserHandle.USER_NULL) {
1066 Log.wtf(TAG, "notifyHalUserRemoved() Called for UserHandle.USER_NULL");
1067 return;
1068 }
1069
1070 synchronized (mLockUser) {
1071 if (mFailedToCreateUserIds.get(userId)) {
1072 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1073 Log.d(TAG, "notifyHalUserRemoved(): skipping " + userId);
1074 }
1075 mFailedToCreateUserIds.delete(userId);
1076 return;
1077 }
1078 }
1079
1080 android.hardware.automotive.vehicle.V2_0.UserInfo halUser =
1081 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1082 halUser.userId = userId;
1083 // TODO(b/155913815): per the REMOVE_USER API, the userFlags should be set as well, but it's
1084 // gone. We'll need to either update the documentation, or if that's not possible (as it's
1085 // breaking the contract), either change the intent to contain the flags, or keep track of
1086 // the flags internally.
1087
1088 RemoveUserRequest request = new RemoveUserRequest();
1089 request.removedUserInfo = halUser;
1090 request.usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1091 mHal.removeUser(request);
1092 }
1093
Mayank Garga55c3092020-05-28 03:19:24 -07001094 private UserRemovalResult logAndGetResults(@UserIdInt int userId,
1095 @UserRemovalResult.Status int result) {
1096 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_REMOVE_USER_RESP, userId, result);
1097 return new UserRemovalResult(result);
1098 }
1099
Mayank Garg587f1942020-05-06 01:41:34 -07001100 private void sendUserSwitchUiCallback(@UserIdInt int targetUserId) {
1101 if (mUserSwitchUiReceiver == null) {
1102 Log.w(TAG_USER, "No User switch UI receiver.");
1103 return;
1104 }
1105
felipealdfdf8512020-06-01 09:35:45 -07001106 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_UI_REQ, targetUserId);
Mayank Garg587f1942020-05-06 01:41:34 -07001107 try {
Mayank Garg587f1942020-05-06 01:41:34 -07001108 mUserSwitchUiReceiver.send(targetUserId, null);
1109 } catch (RemoteException e) {
1110 Log.e(TAG_USER, "Error calling user switch UI receiver.", e);
1111 }
1112 }
1113
felipeal5e3ede42020-04-23 18:04:07 -07001114 @Override
felipealdfdf8512020-06-01 09:35:45 -07001115 public void createUser(@Nullable String name, @NonNull String userType, @UserInfoFlag int flags,
1116 int timeoutMs, @NonNull AndroidFuture<UserCreationResult> receiver) {
1117 Objects.requireNonNull(userType, "user type cannot be null");
1118 Objects.requireNonNull(receiver, "receiver cannot be null");
Felipe Leme17799202020-09-03 12:55:53 -07001119 checkManageOrCreateUsersPermission(flags);
1120
Mayank Garg94f3eb92020-08-12 12:38:58 -07001121 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_REQ,
1122 UserHelperLite.safeName(name), userType, flags, timeoutMs);
felipealdfdf8512020-06-01 09:35:45 -07001123
1124 UserInfo newUser;
1125 try {
1126 newUser = mUserManager.createUser(name, userType, flags);
1127 if (newUser == null) {
1128 Log.w(TAG, "um.createUser() returned null for user of type " + userType
1129 + " and flags " + UserInfo.flagsToString(flags));
1130 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_ANDROID_FAILURE);
1131 return;
1132 }
1133 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1134 Log.d(TAG, "Created user: " + newUser.toFullString());
1135 }
1136 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_USER_CREATED, newUser.id,
Mayank Garg94f3eb92020-08-12 12:38:58 -07001137 UserHelperLite.safeName(newUser.name), newUser.userType, newUser.flags);
felipealdfdf8512020-06-01 09:35:45 -07001138 } catch (RuntimeException e) {
1139 Log.e(TAG_USER, "Error creating user of type " + userType + " and flags"
1140 + UserInfo.flagsToString(flags), e);
1141 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_ANDROID_FAILURE);
1142 return;
1143 }
1144
Mayank Garg9ed099e2020-06-04 16:05:20 -07001145 if (!isUserHalSupported()) {
1146 sendUserCreationResult(receiver, UserCreationResult.STATUS_SUCCESSFUL, newUser, null);
1147 return;
1148 }
1149
felipealdfdf8512020-06-01 09:35:45 -07001150 CreateUserRequest request = new CreateUserRequest();
1151 request.usersInfo = UserHalHelper.newUsersInfo(mUserManager);
1152 if (!TextUtils.isEmpty(name)) {
1153 request.newUserName = name;
1154 }
1155 request.newUserInfo.userId = newUser.id;
1156 request.newUserInfo.flags = UserHalHelper.convertFlags(newUser);
1157 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1158 Log.d(TAG, "Create user request: " + request);
1159 }
1160
1161 try {
1162 mHal.createUser(request, timeoutMs, (status, resp) -> {
1163 int resultStatus = UserCreationResult.STATUS_HAL_INTERNAL_FAILURE;
1164 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1165 Log.d(TAG, "createUserResponse: status="
1166 + UserHalHelper.halCallbackStatusToString(status) + ", resp=" + resp);
1167 }
1168 UserInfo user = null; // user returned in the result
1169 if (status != HalCallback.STATUS_OK) {
1170 Log.w(TAG, "invalid callback status ("
1171 + UserHalHelper.halCallbackStatusToString(status) + ") for response "
1172 + resp);
1173 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_RESP, status,
1174 resultStatus, resp.errorMessage);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001175 removeCreatedUser(newUser, "HAL call failed with "
felipealdfdf8512020-06-01 09:35:45 -07001176 + UserHalHelper.halCallbackStatusToString(status));
1177 sendUserCreationResult(receiver, resultStatus, user, /* errorMsg= */ null);
1178 return;
1179 }
1180
1181 switch (resp.status) {
1182 case CreateUserStatus.SUCCESS:
1183 resultStatus = UserCreationResult.STATUS_SUCCESSFUL;
1184 user = newUser;
1185 break;
1186 case CreateUserStatus.FAILURE:
1187 // HAL failed to switch user
1188 resultStatus = UserCreationResult.STATUS_HAL_FAILURE;
1189 break;
1190 default:
1191 // Shouldn't happen because UserHalService validates the status
1192 Log.wtf(TAG, "Received invalid user switch status from HAL: " + resp);
1193 }
1194 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_RESP, status,
1195 resultStatus, resp.errorMessage);
1196 if (user == null) {
Felipe Leme6b34fc32020-10-26 15:49:17 -07001197 removeCreatedUser(newUser, "HAL returned "
felipealdfdf8512020-06-01 09:35:45 -07001198 + UserCreationResult.statusToString(resultStatus));
1199 }
1200 sendUserCreationResult(receiver, resultStatus, user, resp.errorMessage);
1201 });
1202 } catch (Exception e) {
1203 Log.w(TAG, "mHal.createUser(" + request + ") failed", e);
Felipe Leme6b34fc32020-10-26 15:49:17 -07001204 removeCreatedUser(newUser, "mHal.createUser() failed");
felipealdfdf8512020-06-01 09:35:45 -07001205 sendUserCreationResultFailure(receiver, UserCreationResult.STATUS_HAL_INTERNAL_FAILURE);
1206 }
1207 }
1208
Felipe Leme6b34fc32020-10-26 15:49:17 -07001209 private void removeCreatedUser(@NonNull UserInfo user, @NonNull String reason) {
1210 int userId = user.id;
1211 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_CREATE_USER_USER_REMOVED, userId, reason);
1212
1213 synchronized (mLockUser) {
1214 mFailedToCreateUserIds.put(userId, true);
1215 }
1216
felipealdfdf8512020-06-01 09:35:45 -07001217 try {
Felipe Leme6b34fc32020-10-26 15:49:17 -07001218 if (!mUserManager.removeUser(userId)) {
felipealdfdf8512020-06-01 09:35:45 -07001219 Log.w(TAG, "Failed to remove user " + user.toFullString());
1220 }
1221 } catch (Exception e) {
1222 Log.e(TAG, "Failed to remove user " + user.toFullString(), e);
1223 }
1224 }
1225
1226 @Override
felipeal159a2a42020-05-08 10:32:11 -07001227 public UserIdentificationAssociationResponse getUserIdentificationAssociation(int[] types) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001228 if (!isUserHalUserAssociationSupported()) {
1229 return UserIdentificationAssociationResponse.forFailure(VEHICLE_HAL_NOT_SUPPORTED);
1230 }
1231
felipeal5e3ede42020-04-23 18:04:07 -07001232 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type");
Felipe Leme17799202020-09-03 12:55:53 -07001233 checkManageOrCreateUsersPermission("getUserIdentificationAssociation");
felipeal5e3ede42020-04-23 18:04:07 -07001234
1235 int uid = getCallingUid();
1236 int userId = UserHandle.getUserId(uid);
1237 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_GET_USER_AUTH_REQ, uid, userId);
1238
1239 UserIdentificationGetRequest request = new UserIdentificationGetRequest();
1240 request.userInfo.userId = userId;
1241 request.userInfo.flags = getHalUserInfoFlags(userId);
1242
1243 request.numberAssociationTypes = types.length;
1244 for (int i = 0; i < types.length; i++) {
1245 request.associationTypes.add(types[i]);
1246 }
1247
1248 UserIdentificationResponse halResponse = mHal.getUserAssociation(request);
1249 if (halResponse == null) {
1250 Log.w(TAG, "getUserIdentificationAssociation(): HAL returned null for "
1251 + Arrays.toString(types));
felipeal159a2a42020-05-08 10:32:11 -07001252 return UserIdentificationAssociationResponse.forFailure();
felipeal5e3ede42020-04-23 18:04:07 -07001253 }
1254
1255 int[] values = new int[halResponse.associations.size()];
1256 for (int i = 0; i < values.length; i++) {
1257 values[i] = halResponse.associations.get(i).value;
1258 }
1259 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_GET_USER_AUTH_RESP, values.length);
1260
felipeal159a2a42020-05-08 10:32:11 -07001261 return UserIdentificationAssociationResponse.forSuccess(values, halResponse.errorMessage);
1262 }
1263
1264 @Override
1265 public void setUserIdentificationAssociation(int timeoutMs, int[] types, int[] values,
1266 AndroidFuture<UserIdentificationAssociationResponse> result) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001267 if (!isUserHalUserAssociationSupported()) {
1268 result.complete(
1269 UserIdentificationAssociationResponse.forFailure(VEHICLE_HAL_NOT_SUPPORTED));
1270 return;
1271 }
1272
felipeal159a2a42020-05-08 10:32:11 -07001273 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type");
1274 Preconditions.checkArgument(!ArrayUtils.isEmpty(values), "must have at least one value");
1275 if (types.length != values.length) {
1276 throw new IllegalArgumentException("types (" + Arrays.toString(types) + ") and values ("
1277 + Arrays.toString(values) + ") should have the same length");
1278 }
Felipe Leme17799202020-09-03 12:55:53 -07001279 checkManageOrCreateUsersPermission("setUserIdentificationAssociation");
felipeal159a2a42020-05-08 10:32:11 -07001280
1281 int uid = getCallingUid();
1282 int userId = UserHandle.getUserId(uid);
1283 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_REQ, uid, userId, types.length);
1284
1285 UserIdentificationSetRequest request = new UserIdentificationSetRequest();
1286 request.userInfo.userId = userId;
1287 request.userInfo.flags = getHalUserInfoFlags(userId);
1288
1289 request.numberAssociations = types.length;
1290 for (int i = 0; i < types.length; i++) {
1291 UserIdentificationSetAssociation association = new UserIdentificationSetAssociation();
1292 association.type = types[i];
1293 association.value = values[i];
1294 request.associations.add(association);
1295 }
1296
1297 mHal.setUserAssociation(timeoutMs, request, (status, resp) -> {
1298 if (status != HalCallback.STATUS_OK) {
1299 Log.w(TAG, "setUserIdentificationAssociation(): invalid callback status ("
1300 + UserHalHelper.halCallbackStatusToString(status) + ") for response "
1301 + resp);
1302 if (resp == null || TextUtils.isEmpty(resp.errorMessage)) {
1303 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, 0);
1304 result.complete(UserIdentificationAssociationResponse.forFailure());
1305 return;
1306 }
1307 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, 0,
1308 resp.errorMessage);
1309 result.complete(
1310 UserIdentificationAssociationResponse.forFailure(resp.errorMessage));
1311 return;
1312 }
1313 int respSize = resp.associations.size();
1314 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, respSize,
1315 resp.errorMessage);
1316
1317 int[] responseTypes = new int[respSize];
1318 for (int i = 0; i < respSize; i++) {
1319 responseTypes[i] = resp.associations.get(i).value;
1320 }
1321 UserIdentificationAssociationResponse response = UserIdentificationAssociationResponse
1322 .forSuccess(responseTypes, resp.errorMessage);
1323 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1324 Log.d(TAG, "setUserIdentificationAssociation(): resp= " + resp
1325 + ", converted=" + response);
1326 }
1327 result.complete(response);
1328 });
felipeal5e3ede42020-04-23 18:04:07 -07001329 }
1330
1331 /**
1332 * Gets the User HAL flags for the given user.
1333 *
1334 * @throws IllegalArgumentException if the user does not exist.
1335 */
1336 private int getHalUserInfoFlags(@UserIdInt int userId) {
1337 UserInfo user = mUserManager.getUserInfo(userId);
1338 Preconditions.checkArgument(user != null, "no user for id %d", userId);
1339 return UserHalHelper.convertFlags(user);
1340 }
1341
Mayank Garg0e239142020-04-14 19:16:31 -07001342 private void sendResult(@NonNull IResultReceiver receiver, int resultCode,
1343 @Nullable Bundle resultData) {
1344 try {
1345 receiver.send(resultCode, resultData);
1346 } catch (RemoteException e) {
1347 // ignore
1348 Log.w(TAG_USER, "error while sending results", e);
1349 }
1350 }
1351
felipealdfdf8512020-06-01 09:35:45 -07001352 private void sendUserSwitchResult(@NonNull AndroidFuture<UserSwitchResult> receiver,
felipeale5bf0322020-04-16 15:10:57 -07001353 @UserSwitchResult.Status int status) {
felipealdfdf8512020-06-01 09:35:45 -07001354 sendUserSwitchResult(receiver, status, /* errorMessage= */ null);
felipeale5bf0322020-04-16 15:10:57 -07001355 }
1356
felipealdfdf8512020-06-01 09:35:45 -07001357 private void sendUserSwitchResult(@NonNull AndroidFuture<UserSwitchResult> receiver,
felipeale5bf0322020-04-16 15:10:57 -07001358 @UserSwitchResult.Status int status, @Nullable String errorMessage) {
1359 receiver.complete(new UserSwitchResult(status, errorMessage));
1360 }
1361
felipealdfdf8512020-06-01 09:35:45 -07001362 private void sendUserCreationResultFailure(@NonNull AndroidFuture<UserCreationResult> receiver,
1363 @UserCreationResult.Status int status) {
1364 sendUserCreationResult(receiver, status, /* user= */ null, /* errorMessage= */ null);
1365 }
1366
1367 private void sendUserCreationResult(@NonNull AndroidFuture<UserCreationResult> receiver,
1368 @UserCreationResult.Status int status, @NonNull UserInfo user,
1369 @Nullable String errorMessage) {
1370 if (TextUtils.isEmpty(errorMessage)) {
1371 errorMessage = null;
1372 }
1373 receiver.complete(new UserCreationResult(status, user, errorMessage));
1374 }
1375
Mayank Garg6307fe42020-04-15 23:09:03 -07001376 /**
1377 * Calls activity manager for user switch.
1378 *
1379 * <p><b>NOTE</b> This method is meant to be called just by UserHalService.
1380 *
1381 * @param requestId for the user switch request
1382 * @param targetUserId of the target user
1383 *
1384 * @hide
1385 */
1386 public void switchAndroidUserFromHal(int requestId, @UserIdInt int targetUserId) {
1387 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_SWITCH_USER_FROM_HAL_REQ, requestId,
1388 targetUserId);
1389 Log.i(TAG_USER, "User hal requested a user switch. Target user id " + targetUserId);
1390
1391 try {
1392 boolean result = mAm.switchUser(targetUserId);
1393 if (result) {
1394 updateUserSwitchInProcess(requestId, targetUserId);
1395 } else {
1396 postSwitchHalResponse(requestId, targetUserId);
1397 }
1398 } catch (RemoteException e) {
1399 // ignore
1400 Log.w(TAG_USER, "error while switching user " + targetUserId, e);
1401 }
1402 }
1403
1404 private void updateUserSwitchInProcess(int requestId, @UserIdInt int targetUserId) {
1405 synchronized (mLockUser) {
1406 if (mUserIdForUserSwitchInProcess != UserHandle.USER_NULL) {
1407 // Some other user switch is in process.
1408 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1409 Log.d(TAG_USER, "User switch for user: " + mUserIdForUserSwitchInProcess
1410 + " is in process. Abandoning it as a new user switch is requested"
1411 + " for the target user: " + targetUserId);
1412 }
1413 }
1414 mUserIdForUserSwitchInProcess = targetUserId;
1415 mRequestIdForUserSwitchInProcess = requestId;
1416 }
1417 }
Mayank Garg9ed099e2020-06-04 16:05:20 -07001418
Mayank Garg7a114c82020-04-08 21:25:06 -07001419 private void postSwitchHalResponse(int requestId, @UserIdInt int targetUserId) {
Mayank Garg9ed099e2020-06-04 16:05:20 -07001420 if (!isUserHalSupported()) return;
1421
felipealdfdf8512020-06-01 09:35:45 -07001422 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
Mayank Gargeb37d092020-06-02 14:37:57 -07001423 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_POST_SWITCH_USER_REQ, requestId,
1424 targetUserId, usersInfo.currentUser.userId);
1425 SwitchUserRequest request = createUserSwitchRequest(targetUserId, usersInfo);
1426 request.requestId = requestId;
1427 mHal.postSwitchResponse(request);
1428 }
1429
1430 private SwitchUserRequest createUserSwitchRequest(@UserIdInt int targetUserId,
1431 @NonNull UsersInfo usersInfo) {
1432 UserInfo targetUser = mUserManager.getUserInfo(targetUserId);
Mayank Garg7a114c82020-04-08 21:25:06 -07001433 android.hardware.automotive.vehicle.V2_0.UserInfo halTargetUser =
1434 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1435 halTargetUser.userId = targetUser.id;
1436 halTargetUser.flags = UserHalHelper.convertFlags(targetUser);
Mayank Gargeb37d092020-06-02 14:37:57 -07001437 SwitchUserRequest request = new SwitchUserRequest();
1438 request.targetUser = halTargetUser;
1439 request.usersInfo = usersInfo;
1440 return request;
Mayank Garg7a114c82020-04-08 21:25:06 -07001441 }
1442
Mayank Garg59f22192020-03-27 00:51:45 -07001443 /**
Felipe Lemee3cab982020-03-12 11:39:29 -07001444 * Checks if the User HAL is supported.
1445 */
1446 public boolean isUserHalSupported() {
1447 return mHal.isSupported();
1448 }
1449
Mayank Garg587f1942020-05-06 01:41:34 -07001450 /**
Mayank Garg9ed099e2020-06-04 16:05:20 -07001451 * Checks if the User HAL user association is supported.
1452 */
1453 @Override
1454 public boolean isUserHalUserAssociationSupported() {
1455 return mHal.isUserAssociationSupported();
1456 }
1457
1458 /**
Mayank Garg587f1942020-05-06 01:41:34 -07001459 * Sets a callback which is invoked before user switch.
1460 *
1461 * <p>
1462 * This method should only be called by the Car System UI. The purpose of this call is to notify
1463 * Car System UI to show the user switch UI before the user switch.
1464 */
1465 @Override
1466 public void setUserSwitchUiCallback(@NonNull IResultReceiver receiver) {
Yan Zhu67a383e2020-05-11 20:46:24 -07001467 checkManageUsersPermission("setUserSwitchUiCallback");
Mayank Garga480dd92020-05-14 03:14:57 -07001468
1469 // Confirm that caller is system UI.
1470 String systemUiPackageName = getSystemUiPackageName();
1471 if (systemUiPackageName == null) {
1472 throw new IllegalStateException("System UI package not found.");
1473 }
1474
1475 try {
1476 int systemUiUid = mContext
1477 .createContextAsUser(UserHandle.SYSTEM, /* flags= */ 0).getPackageManager()
1478 .getPackageUid(systemUiPackageName, PackageManager.MATCH_SYSTEM_ONLY);
1479 int callerUid = Binder.getCallingUid();
1480 if (systemUiUid != callerUid) {
1481 throw new SecurityException("Invalid caller. Only" + systemUiPackageName
1482 + " is allowed to make this call");
1483 }
1484 } catch (NameNotFoundException e) {
1485 throw new IllegalStateException("Package " + systemUiPackageName + " not found.");
1486 }
1487
Mayank Garg587f1942020-05-06 01:41:34 -07001488 mUserSwitchUiReceiver = receiver;
1489 }
1490
Mayank Garga480dd92020-05-14 03:14:57 -07001491 // TODO(157082995): This information can be taken from
1492 // PackageManageInternalImpl.getSystemUiServiceComponent
1493 @Nullable
1494 private String getSystemUiPackageName() {
1495 try {
1496 ComponentName componentName = ComponentName.unflattenFromString(mContext.getResources()
1497 .getString(com.android.internal.R.string.config_systemUIServiceComponent));
1498 return componentName.getPackageName();
1499 } catch (RuntimeException e) {
1500 Log.w(TAG_USER, "error while getting system UI package name.", e);
1501 return null;
1502 }
1503 }
1504
Keun young Park13a7a822019-04-04 15:53:08 -07001505 private void updateDefaultUserRestriction() {
1506 // We want to set restrictions on system and guest users only once. These are persisted
1507 // onto disk, so it's sufficient to do it once + we minimize the number of disk writes.
1508 if (Settings.Global.getInt(mContext.getContentResolver(),
Eric Jeong1545f3b2019-09-16 13:56:52 -07001509 CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, /* default= */ 0) != 0) {
1510 return;
Keun young Park13a7a822019-04-04 15:53:08 -07001511 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07001512 // Only apply the system user restrictions if the system user is headless.
1513 if (UserManager.isHeadlessSystemUserMode()) {
1514 setSystemUserRestrictions();
1515 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07001516 Settings.Global.putInt(mContext.getContentResolver(),
1517 CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, 1);
Keun young Park13a7a822019-04-04 15:53:08 -07001518 }
1519
Eric Jeong1545f3b2019-09-16 13:56:52 -07001520 private boolean isPersistentUser(@UserIdInt int userId) {
Anthony Hugh9932a252019-06-12 16:19:56 -07001521 return !mUserManager.getUserInfo(userId).isEphemeral();
1522 }
1523
Antonio Kantekc8114752020-03-05 21:37:39 -08001524 /**
Antonio Kantekc8114752020-03-05 21:37:39 -08001525 * Adds a new {@link UserLifecycleListener} to listen to user activity events.
1526 */
1527 public void addUserLifecycleListener(@NonNull UserLifecycleListener listener) {
1528 Objects.requireNonNull(listener, "listener cannot be null");
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001529 mHandler.post(() -> mUserLifecycleListeners.add(listener));
Antonio Kantekc8114752020-03-05 21:37:39 -08001530 }
1531
1532 /**
1533 * Removes previously added {@link UserLifecycleListener}.
1534 */
1535 public void removeUserLifecycleListener(@NonNull UserLifecycleListener listener) {
1536 Objects.requireNonNull(listener, "listener cannot be null");
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001537 mHandler.post(() -> mUserLifecycleListeners.remove(listener));
Antonio Kantekc8114752020-03-05 21:37:39 -08001538 }
1539
Eric Jeongc91f9452019-08-30 15:04:21 -07001540 /** Adds callback to listen to passenger activity events. */
1541 public void addPassengerCallback(@NonNull PassengerCallback callback) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00001542 Objects.requireNonNull(callback, "callback cannot be null");
Eric Jeongc91f9452019-08-30 15:04:21 -07001543 mPassengerCallbacks.add(callback);
1544 }
1545
1546 /** Removes previously added callback to listen passenger events. */
1547 public void removePassengerCallback(@NonNull PassengerCallback callback) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00001548 Objects.requireNonNull(callback, "callback cannot be null");
Eric Jeongc91f9452019-08-30 15:04:21 -07001549 mPassengerCallbacks.remove(callback);
1550 }
1551
1552 /** Sets the implementation of ZoneUserBindingHelper. */
1553 public void setZoneUserBindingHelper(@NonNull ZoneUserBindingHelper helper) {
1554 synchronized (mLockHelper) {
1555 mZoneUserBindingHelper = helper;
1556 }
1557 }
1558
felipeal98900c82020-04-09 09:05:02 -07001559 private void onUserUnlocked(@UserIdInt int userId) {
Keun-young Parkd462a912019-02-11 08:53:42 -08001560 ArrayList<Runnable> tasks = null;
Eric Jeongc91f9452019-08-30 15:04:21 -07001561 synchronized (mLockUser) {
Mayank Garg7a114c82020-04-08 21:25:06 -07001562 sendPostSwitchToHalLocked(userId);
Eric Jeong1545f3b2019-09-16 13:56:52 -07001563 if (userId == UserHandle.USER_SYSTEM) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001564 if (!mUser0Unlocked) { // user 0, unlocked, do this only once
1565 updateDefaultUserRestriction();
1566 tasks = new ArrayList<>(mUser0UnlockTasks);
1567 mUser0UnlockTasks.clear();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001568 mUser0Unlocked = true;
Keun young Parkf3523cd2019-04-08 10:09:17 -07001569 }
1570 } else { // none user0
Eric Jeong1545f3b2019-09-16 13:56:52 -07001571 Integer user = userId;
1572 if (isPersistentUser(userId)) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001573 // current foreground user should stay in top priority.
Anthony Hughfbb67762019-10-15 12:54:54 -07001574 if (userId == ActivityManager.getCurrentUser()) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001575 mBackgroundUsersToRestart.remove(user);
1576 mBackgroundUsersToRestart.add(0, user);
1577 }
1578 // -1 for user 0
1579 if (mBackgroundUsersToRestart.size() > (mMaxRunningUsers - 1)) {
Eric Jeong1545f3b2019-09-16 13:56:52 -07001580 int userToDrop = mBackgroundUsersToRestart.get(
Keun young Parkf3523cd2019-04-08 10:09:17 -07001581 mBackgroundUsersToRestart.size() - 1);
Eric Jeong1545f3b2019-09-16 13:56:52 -07001582 Log.i(TAG_USER, "New user unlocked:" + userId
Keun young Parkf3523cd2019-04-08 10:09:17 -07001583 + ", dropping least recently user from restart list:" + userToDrop);
1584 // Drop the least recently used user.
1585 mBackgroundUsersToRestart.remove(mBackgroundUsersToRestart.size() - 1);
1586 }
1587 }
Keun-young Parkd462a912019-02-11 08:53:42 -08001588 }
1589 }
1590 if (tasks != null && tasks.size() > 0) {
Eric Jeong1545f3b2019-09-16 13:56:52 -07001591 Log.d(TAG_USER, "User0 unlocked, run queued tasks:" + tasks.size());
Keun-young Parkd462a912019-02-11 08:53:42 -08001592 for (Runnable r : tasks) {
1593 r.run();
1594 }
1595 }
1596 }
1597
1598 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -07001599 * Starts all background users that were active in system.
1600 *
Keun young Parkfb656372019-03-12 18:37:55 -07001601 * @return list of background users started successfully.
1602 */
Eric Jeong1545f3b2019-09-16 13:56:52 -07001603 @NonNull
Keun young Parkfb656372019-03-12 18:37:55 -07001604 public ArrayList<Integer> startAllBackgroundUsers() {
1605 ArrayList<Integer> users;
Eric Jeongc91f9452019-08-30 15:04:21 -07001606 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001607 users = new ArrayList<>(mBackgroundUsersToRestart);
1608 mBackgroundUsersRestartedHere.clear();
1609 mBackgroundUsersRestartedHere.addAll(mBackgroundUsersToRestart);
Keun young Parkfb656372019-03-12 18:37:55 -07001610 }
1611 ArrayList<Integer> startedUsers = new ArrayList<>();
1612 for (Integer user : users) {
Anthony Hughfbb67762019-10-15 12:54:54 -07001613 if (user == ActivityManager.getCurrentUser()) {
Keun young Parkfb656372019-03-12 18:37:55 -07001614 continue;
1615 }
1616 try {
1617 if (mAm.startUserInBackground(user)) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001618 if (mUserManager.isUserUnlockingOrUnlocked(user)) {
1619 // already unlocked / unlocking. No need to unlock.
Keun young Parkfb656372019-03-12 18:37:55 -07001620 startedUsers.add(user);
Keun young Parkf3523cd2019-04-08 10:09:17 -07001621 } else if (mAm.unlockUser(user, null, null, null)) {
1622 startedUsers.add(user);
1623 } else { // started but cannot unlock
Eric Jeong1545f3b2019-09-16 13:56:52 -07001624 Log.w(TAG_USER, "Background user started but cannot be unlocked:" + user);
Keun young Parkf3523cd2019-04-08 10:09:17 -07001625 if (mUserManager.isUserRunning(user)) {
1626 // add to started list so that it can be stopped later.
1627 startedUsers.add(user);
1628 }
Keun young Parkfb656372019-03-12 18:37:55 -07001629 }
1630 }
1631 } catch (RemoteException e) {
1632 // ignore
Eric Jeong1545f3b2019-09-16 13:56:52 -07001633 Log.w(TAG_USER, "error while starting user in background", e);
Keun young Parkfb656372019-03-12 18:37:55 -07001634 }
1635 }
Keun young Parkf3523cd2019-04-08 10:09:17 -07001636 // Keep only users that were re-started in mBackgroundUsersRestartedHere
Eric Jeongc91f9452019-08-30 15:04:21 -07001637 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001638 ArrayList<Integer> usersToRemove = new ArrayList<>();
1639 for (Integer user : mBackgroundUsersToRestart) {
1640 if (!startedUsers.contains(user)) {
1641 usersToRemove.add(user);
1642 }
1643 }
1644 mBackgroundUsersRestartedHere.removeAll(usersToRemove);
1645 }
Keun young Parkfb656372019-03-12 18:37:55 -07001646 return startedUsers;
1647 }
1648
1649 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -07001650 * Stops all background users that were active in system.
1651 *
1652 * @return whether stopping succeeds.
Keun young Parkfb656372019-03-12 18:37:55 -07001653 */
Eric Jeong1545f3b2019-09-16 13:56:52 -07001654 public boolean stopBackgroundUser(@UserIdInt int userId) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001655 if (userId == UserHandle.USER_SYSTEM) {
1656 return false;
1657 }
Anthony Hughfbb67762019-10-15 12:54:54 -07001658 if (userId == ActivityManager.getCurrentUser()) {
Eric Jeong1545f3b2019-09-16 13:56:52 -07001659 Log.i(TAG_USER, "stopBackgroundUser, already a FG user:" + userId);
Keun young Parkfb656372019-03-12 18:37:55 -07001660 return false;
1661 }
1662 try {
Keun young Parked9e6282019-09-19 17:38:26 -07001663 int r = mAm.stopUserWithDelayedLocking(userId, true, null);
Keun young Parkf3523cd2019-04-08 10:09:17 -07001664 if (r == ActivityManager.USER_OP_SUCCESS) {
Eric Jeongc91f9452019-08-30 15:04:21 -07001665 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001666 Integer user = userId;
1667 mBackgroundUsersRestartedHere.remove(user);
1668 }
1669 } else if (r == ActivityManager.USER_OP_IS_CURRENT) {
1670 return false;
1671 } else {
Eric Jeong1545f3b2019-09-16 13:56:52 -07001672 Log.i(TAG_USER, "stopBackgroundUser failed, user:" + userId + " err:" + r);
Keun young Parkfb656372019-03-12 18:37:55 -07001673 return false;
1674 }
1675 } catch (RemoteException e) {
1676 // ignore
Eric Jeong1545f3b2019-09-16 13:56:52 -07001677 Log.w(TAG_USER, "error while stopping user", e);
Keun young Parkfb656372019-03-12 18:37:55 -07001678 }
1679 return true;
1680 }
1681
1682 /**
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001683 * Notifies all registered {@link UserLifecycleListener} with the event passed as argument.
Pavel Maltsev17e81832019-04-04 14:38:41 -07001684 */
Mayank Gargccad8062020-08-30 15:05:10 -07001685 public void onUserLifecycleEvent(@UserLifecycleEventType int eventType,
felipeale8c5dce2020-04-15 11:27:06 -07001686 @UserIdInt int fromUserId, @UserIdInt int toUserId) {
1687 int userId = toUserId;
felipeal98900c82020-04-09 09:05:02 -07001688
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001689 // Handle special cases first...
felipeal98900c82020-04-09 09:05:02 -07001690 if (eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING) {
Mayank Garge5de0f92020-04-23 21:38:38 -07001691 onUserSwitching(fromUserId, toUserId);
felipeal98900c82020-04-09 09:05:02 -07001692 } else if (eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_UNLOCKED) {
1693 onUserUnlocked(userId);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001694 }
1695
felipeale8c5dce2020-04-15 11:27:06 -07001696 // ...then notify listeners.
Yan Zhue7921522020-04-16 15:59:25 -07001697 UserLifecycleEvent event = new UserLifecycleEvent(eventType, fromUserId, userId);
felipeale8c5dce2020-04-15 11:27:06 -07001698
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001699 mHandler.post(() -> {
1700 handleNotifyServiceUserLifecycleListeners(event);
1701 handleNotifyAppUserLifecycleListeners(event);
1702 });
felipeale8c5dce2020-04-15 11:27:06 -07001703 }
1704
Mayank Garg7a114c82020-04-08 21:25:06 -07001705 private void sendPostSwitchToHalLocked(@UserIdInt int userId) {
felipealf7368962020-04-16 12:55:19 -07001706 if (mUserIdForUserSwitchInProcess == UserHandle.USER_NULL
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001707 || mUserIdForUserSwitchInProcess != userId
1708 || mRequestIdForUserSwitchInProcess == 0) {
Mayank Garg7a114c82020-04-08 21:25:06 -07001709 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1710 Log.d(TAG_USER, "No user switch request Id. No android post switch sent.");
1711 }
1712 return;
1713 }
felipealf7368962020-04-16 12:55:19 -07001714 postSwitchHalResponse(mRequestIdForUserSwitchInProcess, mUserIdForUserSwitchInProcess);
1715 mUserIdForUserSwitchInProcess = UserHandle.USER_NULL;
Mayank Garg1f20dcd2020-04-22 17:46:01 -07001716 mRequestIdForUserSwitchInProcess = 0;
Mayank Garg7a114c82020-04-08 21:25:06 -07001717 }
1718
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001719 private void handleNotifyAppUserLifecycleListeners(UserLifecycleEvent event) {
1720 int listenersSize = mAppLifecycleListeners.size();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001721 if (listenersSize == 0) {
felipeal2a84d512020-04-06 18:52:15 -07001722 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1723 Log.d(TAG_USER, "No app listener to be notified of " + event);
1724 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001725 return;
1726 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001727 // Must use a different TimingsTraceLog because it's another thread
1728 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1729 Log.d(TAG_USER, "Notifying " + listenersSize + " app listeners of " + event);
1730 }
felipeal2a84d512020-04-06 18:52:15 -07001731 int userId = event.getUserId();
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001732 TimingsTraceLog t = new TimingsTraceLog(TAG_USER, Trace.TRACE_TAG_SYSTEM_SERVER);
felipealde1e16d2020-06-03 13:20:48 -07001733 int eventType = event.getEventType();
1734 t.traceBegin("notify-app-listeners-user-" + userId + "-event-" + eventType);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001735 for (int i = 0; i < listenersSize; i++) {
1736 int uid = mAppLifecycleListeners.keyAt(i);
felipealde1e16d2020-06-03 13:20:48 -07001737
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001738 IResultReceiver listener = mAppLifecycleListeners.valueAt(i);
1739 Bundle data = new Bundle();
felipealde1e16d2020-06-03 13:20:48 -07001740 data.putInt(CarUserManager.BUNDLE_PARAM_ACTION, eventType);
Yan Zhue7921522020-04-16 15:59:25 -07001741
felipealde1e16d2020-06-03 13:20:48 -07001742 int fromUserId = event.getPreviousUserId();
1743 if (fromUserId != UserHandle.USER_NULL) {
1744 data.putInt(CarUserManager.BUNDLE_PARAM_PREVIOUS_USER_ID, fromUserId);
Yan Zhue7921522020-04-16 15:59:25 -07001745 }
1746
felipeal2a84d512020-04-06 18:52:15 -07001747 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001748 Log.d(TAG_USER, "Notifying listener for uid " + uid);
felipeal2a84d512020-04-06 18:52:15 -07001749 }
felipealde1e16d2020-06-03 13:20:48 -07001750 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_NOTIFY_APP_LIFECYCLE_LISTENER,
1751 uid, eventType, fromUserId, userId);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001752 try {
felipealde1e16d2020-06-03 13:20:48 -07001753 t.traceBegin("notify-app-listener-uid-" + uid);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001754 listener.send(userId, data);
1755 } catch (RemoteException e) {
1756 Log.e(TAG_USER, "Error calling lifecycle listener", e);
1757 } finally {
1758 t.traceEnd();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001759 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001760 }
1761 t.traceEnd(); // notify-app-listeners-user-USERID-event-EVENT_TYPE
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001762 }
1763
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001764 private void handleNotifyServiceUserLifecycleListeners(UserLifecycleEvent event) {
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001765 TimingsTraceLog t = new TimingsTraceLog(TAG_USER, Trace.TRACE_TAG_SYSTEM_SERVER);
1766 if (mUserLifecycleListeners.isEmpty()) {
felipeal2a84d512020-04-06 18:52:15 -07001767 Log.w(TAG_USER, "Not notifying internal UserLifecycleListeners");
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001768 return;
felipeal2a84d512020-04-06 18:52:15 -07001769 } else if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1770 Log.d(TAG_USER, "Notifying " + mUserLifecycleListeners.size() + " service listeners of "
1771 + event);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001772 }
felipeal2a84d512020-04-06 18:52:15 -07001773
felipealde1e16d2020-06-03 13:20:48 -07001774 int userId = event.getUserId();
1775 int eventType = event.getEventType();
1776 t.traceBegin("notify-listeners-user-" + userId + "-event-" + eventType);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001777 for (UserLifecycleListener listener : mUserLifecycleListeners) {
felipeal2a84d512020-04-06 18:52:15 -07001778 String listenerName = FunctionalUtils.getLambdaName(listener);
felipealde1e16d2020-06-03 13:20:48 -07001779 EventLog.writeEvent(EventLogTags.CAR_USER_SVC_NOTIFY_INTERNAL_LIFECYCLE_LISTENER,
1780 listenerName, eventType, event.getPreviousUserId(), userId);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001781 try {
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001782 t.traceBegin("notify-listener-" + listenerName);
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001783 listener.onEvent(event);
1784 } catch (RuntimeException e) {
1785 Log.e(TAG_USER,
felipeal2a84d512020-04-06 18:52:15 -07001786 "Exception raised when invoking onEvent for " + listenerName, e);
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001787 } finally {
1788 t.traceEnd();
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001789 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001790 }
Antonio Kantek7236a5b2020-04-06 19:53:55 -07001791 t.traceEnd(); // notify-listeners-user-USERID-event-EVENT_TYPE
Antonio Kantek4cf199d2020-03-27 15:56:13 -07001792 }
1793
Mayank Garge5de0f92020-04-23 21:38:38 -07001794 private void onUserSwitching(@UserIdInt int fromUserId, @UserIdInt int toUserId) {
Eric Jeong40f8fa32020-05-12 12:23:33 -07001795 Log.i(TAG_USER, "onUserSwitching() callback for user " + toUserId);
Felipe Leme5528ff72020-02-10 19:05:14 -08001796 TimingsTraceLog t = new TimingsTraceLog(TAG_USER, Trace.TRACE_TAG_SYSTEM_SERVER);
Mayank Garge5de0f92020-04-23 21:38:38 -07001797 t.traceBegin("onUserSwitching-" + toUserId);
Felipe Leme5528ff72020-02-10 19:05:14 -08001798
Mayank Garge5de0f92020-04-23 21:38:38 -07001799 // Switch HAL users if user switch is not requested by CarUserService
1800 notifyHalLegacySwitch(fromUserId, toUserId);
1801
Mayank Garge90a4082020-09-30 12:57:34 -07001802 mInitialUserSetter.setLastActiveUser(toUserId);
felipealbf327652020-06-03 11:33:29 -07001803
Eric Jeongc91f9452019-08-30 15:04:21 -07001804 if (mLastPassengerId != UserHandle.USER_NULL) {
1805 stopPassengerInternal(mLastPassengerId, false);
1806 }
1807 if (mEnablePassengerSupport && isPassengerDisplayAvailable()) {
1808 setupPassengerUser();
Mayank Garge5de0f92020-04-23 21:38:38 -07001809 startFirstPassenger(toUserId);
Eric Jeongc91f9452019-08-30 15:04:21 -07001810 }
felipeal98900c82020-04-09 09:05:02 -07001811 t.traceEnd();
Pavel Maltsev17e81832019-04-04 14:38:41 -07001812 }
1813
Mayank Garge5de0f92020-04-23 21:38:38 -07001814 private void notifyHalLegacySwitch(@UserIdInt int fromUserId, @UserIdInt int toUserId) {
1815 synchronized (mLockUser) {
felipeal7d12ee22020-06-05 09:30:19 -07001816 if (mUserIdForUserSwitchInProcess != UserHandle.USER_NULL) {
1817 if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
1818 Log.d(TAG, "notifyHalLegacySwitch(" + fromUserId + ", " + toUserId
1819 + "): not needed, normal switch for " + mUserIdForUserSwitchInProcess);
1820 }
1821 return;
1822 }
Mayank Garge5de0f92020-04-23 21:38:38 -07001823 }
1824
Mayank Garg9ed099e2020-06-04 16:05:20 -07001825 if (!isUserHalSupported()) return;
1826
Mayank Garge5de0f92020-04-23 21:38:38 -07001827 // switch HAL user
felipeal7d12ee22020-06-05 09:30:19 -07001828 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager, fromUserId);
Mayank Gargeb37d092020-06-02 14:37:57 -07001829 SwitchUserRequest request = createUserSwitchRequest(toUserId, usersInfo);
1830 mHal.legacyUserSwitch(request);
Mayank Garge5de0f92020-04-23 21:38:38 -07001831 }
1832
Pavel Maltsev17e81832019-04-04 14:38:41 -07001833 /**
Eric Jeong1545f3b2019-09-16 13:56:52 -07001834 * 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 -08001835 * run inside this call.
Eric Jeong1545f3b2019-09-16 13:56:52 -07001836 *
Keun-young Parkd462a912019-02-11 08:53:42 -08001837 * @param r Runnable to run.
1838 */
Eric Jeong1545f3b2019-09-16 13:56:52 -07001839 public void runOnUser0Unlock(@NonNull Runnable r) {
Daulet Zhanguzin4ded6782020-01-03 15:47:10 +00001840 Objects.requireNonNull(r, "runnable cannot be null");
Keun-young Parkd462a912019-02-11 08:53:42 -08001841 boolean runNow = false;
Eric Jeongc91f9452019-08-30 15:04:21 -07001842 synchronized (mLockUser) {
Keun-young Parkd462a912019-02-11 08:53:42 -08001843 if (mUser0Unlocked) {
1844 runNow = true;
1845 } else {
1846 mUser0UnlockTasks.add(r);
1847 }
1848 }
1849 if (runNow) {
1850 r.run();
1851 }
1852 }
1853
Keun young Parkf3523cd2019-04-08 10:09:17 -07001854 @VisibleForTesting
Eric Jeong1545f3b2019-09-16 13:56:52 -07001855 @NonNull
1856 ArrayList<Integer> getBackgroundUsersToRestart() {
1857 ArrayList<Integer> backgroundUsersToRestart = null;
Eric Jeongc91f9452019-08-30 15:04:21 -07001858 synchronized (mLockUser) {
Keun young Parkf3523cd2019-04-08 10:09:17 -07001859 backgroundUsersToRestart = new ArrayList<>(mBackgroundUsersToRestart);
1860 }
1861 return backgroundUsersToRestart;
1862 }
1863
Ying Zheng1ab32b62018-06-26 12:47:26 -07001864 private void setSystemUserRestrictions() {
Ying Zheng1ab32b62018-06-26 12:47:26 -07001865 // Disable Location service for system user.
1866 LocationManager locationManager =
1867 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
Anthony Hugh04ee04f2019-12-17 16:11:33 -08001868 locationManager.setLocationEnabledForUser(
1869 /* enabled= */ false, UserHandle.of(UserHandle.USER_SYSTEM));
Ying Zheng1ab32b62018-06-26 12:47:26 -07001870 }
Eric Jeong1545f3b2019-09-16 13:56:52 -07001871
1872 /**
Anthony Hugh6fed1e92019-10-22 16:22:03 -07001873 * Assigns a default icon to a user according to the user's id.
1874 *
1875 * @param userInfo User whose avatar is set to default icon.
Anthony Hugh6fed1e92019-10-22 16:22:03 -07001876 */
Eric Jeongb2dc6ff2020-06-05 17:00:26 -07001877 private void assignDefaultIcon(UserInfo userInfo) {
Anthony Hugh6fed1e92019-10-22 16:22:03 -07001878 int idForIcon = userInfo.isGuest() ? UserHandle.USER_NULL : userInfo.id;
1879 Bitmap bitmap = UserIcons.convertToBitmap(
1880 UserIcons.getDefaultUserIcon(mContext.getResources(), idForIcon, false));
1881 mUserManager.setUserIcon(userInfo.id, bitmap);
Anthony Hugh6fed1e92019-10-22 16:22:03 -07001882 }
1883
Eric Jeong1545f3b2019-09-16 13:56:52 -07001884 private interface UserFilter {
1885 boolean isEligibleUser(UserInfo user);
1886 }
1887
1888 /** Returns all users who are matched by the given filter. */
1889 private List<UserInfo> getUsers(UserFilter filter) {
Colin Cross0df71ea2020-08-27 04:12:26 +00001890 List<UserInfo> users = mUserManager.getAliveUsers();
Eric Jeong1545f3b2019-09-16 13:56:52 -07001891
1892 for (Iterator<UserInfo> iterator = users.iterator(); iterator.hasNext(); ) {
1893 UserInfo user = iterator.next();
1894 if (!filter.isEligibleUser(user)) {
1895 iterator.remove();
1896 }
1897 }
1898 return users;
1899 }
1900
felipeal2d0483c2019-11-02 14:07:22 -07001901 private static void checkManageUsersOrDumpPermission(String message) {
1902 checkAtLeastOnePermission(message,
1903 android.Manifest.permission.MANAGE_USERS,
1904 android.Manifest.permission.DUMP);
1905 }
1906
Felipe Leme5528ff72020-02-10 19:05:14 -08001907 private void checkInteractAcrossUsersPermission(String message) {
1908 checkAtLeastOnePermission(message, android.Manifest.permission.INTERACT_ACROSS_USERS,
1909 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
1910 }
1911
felipeal2d0483c2019-11-02 14:07:22 -07001912 private static void checkAtLeastOnePermission(String message, String...permissions) {
Eric Jeong1545f3b2019-09-16 13:56:52 -07001913 int callingUid = Binder.getCallingUid();
felipeal2d0483c2019-11-02 14:07:22 -07001914 if (!hasAtLeastOnePermissionGranted(callingUid, permissions)) {
1915 throw new SecurityException("You need one of " + Arrays.toString(permissions)
Felipe Leme5528ff72020-02-10 19:05:14 -08001916 + " to: " + message);
Eric Jeong1545f3b2019-09-16 13:56:52 -07001917 }
1918 }
1919
felipeal2d0483c2019-11-02 14:07:22 -07001920 private static boolean hasAtLeastOnePermissionGranted(int uid, String... permissions) {
1921 for (String permission : permissions) {
1922 if (ActivityManager.checkComponentPermission(permission, uid, /* owningUid = */-1,
1923 /* exported = */ true)
1924 == android.content.pm.PackageManager.PERMISSION_GRANTED) {
1925 return true;
1926 }
1927 }
1928 return false;
Eric Jeong1545f3b2019-09-16 13:56:52 -07001929 }
Eric Jeongc91f9452019-08-30 15:04:21 -07001930
1931 private int getNumberOfManagedProfiles(@UserIdInt int userId) {
Colin Cross0df71ea2020-08-27 04:12:26 +00001932 List<UserInfo> users = mUserManager.getAliveUsers();
Eric Jeongc91f9452019-08-30 15:04:21 -07001933 // Count all users that are managed profiles of the given user.
1934 int managedProfilesCount = 0;
1935 for (UserInfo user : users) {
1936 if (user.isManagedProfile() && user.profileGroupId == userId) {
1937 managedProfilesCount++;
1938 }
1939 }
1940 return managedProfilesCount;
1941 }
1942
1943 /**
1944 * Starts the first passenger of the given driver and assigns the passenger to the front
1945 * passenger zone.
1946 *
1947 * @param driverId User id of the driver.
1948 * @return whether it succeeds.
1949 */
1950 private boolean startFirstPassenger(@UserIdInt int driverId) {
1951 int zoneId = getAvailablePassengerZone();
1952 if (zoneId == OccupantZoneInfo.INVALID_ZONE_ID) {
1953 Log.w(TAG_USER, "passenger occupant zone is not found");
1954 return false;
1955 }
1956 List<UserInfo> passengers = getPassengers(driverId);
1957 if (passengers.size() < 1) {
1958 Log.w(TAG_USER, "passenger is not found");
1959 return false;
1960 }
1961 // Only one passenger is supported. If there are two or more passengers, the first passenger
1962 // is chosen.
1963 int passengerId = passengers.get(0).id;
1964 if (!startPassenger(passengerId, zoneId)) {
1965 Log.w(TAG_USER, "cannot start passenger " + passengerId);
1966 return false;
1967 }
1968 return true;
1969 }
1970
1971 private int getAvailablePassengerZone() {
1972 int[] occupantTypes = new int[] {CarOccupantZoneManager.OCCUPANT_TYPE_FRONT_PASSENGER,
1973 CarOccupantZoneManager.OCCUPANT_TYPE_REAR_PASSENGER};
1974 for (int occupantType : occupantTypes) {
1975 int zoneId = getZoneId(occupantType);
1976 if (zoneId != OccupantZoneInfo.INVALID_ZONE_ID) {
1977 return zoneId;
1978 }
1979 }
1980 return OccupantZoneInfo.INVALID_ZONE_ID;
1981 }
1982
1983 /**
1984 * Creates a new passenger user when there is no passenger user.
1985 */
1986 private void setupPassengerUser() {
1987 int currentUser = ActivityManager.getCurrentUser();
1988 int profileCount = getNumberOfManagedProfiles(currentUser);
1989 if (profileCount > 0) {
1990 Log.w(TAG_USER, "max profile of user" + currentUser
1991 + " is exceeded: current profile count is " + profileCount);
1992 return;
1993 }
1994 // TODO(b/140311342): Use resource string for the default passenger name.
1995 UserInfo passenger = createPassenger("Passenger", currentUser);
1996 if (passenger == null) {
1997 // Couldn't create user, most likely because there are too many.
1998 Log.w(TAG_USER, "cannot create a passenger user");
1999 return;
2000 }
2001 }
2002
2003 @NonNull
2004 private List<OccupantZoneInfo> getOccupantZones(@OccupantTypeEnum int occupantType) {
2005 ZoneUserBindingHelper helper = null;
2006 synchronized (mLockHelper) {
2007 if (mZoneUserBindingHelper == null) {
2008 Log.w(TAG_USER, "implementation is not delegated");
2009 return new ArrayList<OccupantZoneInfo>();
2010 }
2011 helper = mZoneUserBindingHelper;
2012 }
2013 return helper.getOccupantZones(occupantType);
2014 }
2015
2016 private boolean assignUserToOccupantZone(@UserIdInt int userId, int zoneId) {
2017 ZoneUserBindingHelper helper = null;
2018 synchronized (mLockHelper) {
2019 if (mZoneUserBindingHelper == null) {
2020 Log.w(TAG_USER, "implementation is not delegated");
2021 return false;
2022 }
2023 helper = mZoneUserBindingHelper;
2024 }
2025 return helper.assignUserToOccupantZone(userId, zoneId);
2026 }
2027
2028 private boolean unassignUserFromOccupantZone(@UserIdInt int userId) {
2029 ZoneUserBindingHelper helper = null;
2030 synchronized (mLockHelper) {
2031 if (mZoneUserBindingHelper == null) {
2032 Log.w(TAG_USER, "implementation is not delegated");
2033 return false;
2034 }
2035 helper = mZoneUserBindingHelper;
2036 }
2037 return helper.unassignUserFromOccupantZone(userId);
2038 }
2039
2040 private boolean isPassengerDisplayAvailable() {
2041 ZoneUserBindingHelper helper = null;
2042 synchronized (mLockHelper) {
2043 if (mZoneUserBindingHelper == null) {
2044 Log.w(TAG_USER, "implementation is not delegated");
2045 return false;
2046 }
2047 helper = mZoneUserBindingHelper;
2048 }
2049 return helper.isPassengerDisplayAvailable();
2050 }
2051
2052 /**
2053 * Gets the zone id of the given occupant type. If there are two or more zones, the first found
2054 * zone is returned.
2055 *
2056 * @param occupantType The type of an occupant.
2057 * @return The zone id of the given occupant type. {@link OccupantZoneInfo.INVALID_ZONE_ID},
2058 * if not found.
2059 */
2060 private int getZoneId(@OccupantTypeEnum int occupantType) {
2061 List<OccupantZoneInfo> zoneInfos = getOccupantZones(occupantType);
2062 return (zoneInfos.size() > 0) ? zoneInfos.get(0).zoneId : OccupantZoneInfo.INVALID_ZONE_ID;
2063 }
Mayank Garg9732d602020-08-09 21:02:40 -07002064
2065 /**
2066 * Manages the required number of pre-created users.
2067 */
2068 public void preCreateUsers() {
2069 mUserPreCreator.managePreCreatedUsers();
2070 }
Felipe Leme17799202020-09-03 12:55:53 -07002071
2072 // TODO(b/167698977): members below were copied from UserManagerService; it would be better to
2073 // move them to some internal android.os class instead.
2074
2075 private static final int ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION =
2076 UserInfo.FLAG_MANAGED_PROFILE
2077 | UserInfo.FLAG_PROFILE
2078 | UserInfo.FLAG_EPHEMERAL
2079 | UserInfo.FLAG_RESTRICTED
2080 | UserInfo.FLAG_GUEST
2081 | UserInfo.FLAG_DEMO
2082 | UserInfo.FLAG_FULL;
2083
2084 private static void checkManageUsersPermission(String message) {
2085 if (!hasManageUsersPermission()) {
2086 throw new SecurityException("You need " + MANAGE_USERS + " permission to: " + message);
2087 }
2088 }
2089
2090 private static void checkManageOrCreateUsersPermission(String message) {
2091 if (!hasManageOrCreateUsersPermission()) {
2092 throw new SecurityException(
2093 "You either need " + MANAGE_USERS + " or " + CREATE_USERS + " permission to: "
2094 + message);
2095 }
2096 }
2097
2098 private static void checkManageOrCreateUsersPermission(int creationFlags) {
2099 if ((creationFlags & ~ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION) == 0) {
2100 if (!hasManageOrCreateUsersPermission()) {
2101 throw new SecurityException("You either need " + MANAGE_USERS + " or "
2102 + CREATE_USERS + "permission to create a user with flags "
2103 + creationFlags);
2104 }
2105 } else if (!hasManageUsersPermission()) {
2106 throw new SecurityException("You need " + MANAGE_USERS + " permission to create a user"
2107 + " with flags " + creationFlags);
2108 }
2109 }
2110
2111 private static boolean hasManageUsersPermission() {
2112 final int callingUid = Binder.getCallingUid();
2113 return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
2114 || callingUid == Process.ROOT_UID
2115 || hasPermissionGranted(MANAGE_USERS, callingUid);
2116 }
2117
2118 private static boolean hasManageUsersOrPermission(String alternativePermission) {
2119 final int callingUid = Binder.getCallingUid();
2120 return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
2121 || callingUid == Process.ROOT_UID
2122 || hasPermissionGranted(MANAGE_USERS, callingUid)
2123 || hasPermissionGranted(alternativePermission, callingUid);
2124 }
2125
2126 private static boolean hasManageOrCreateUsersPermission() {
2127 return hasManageUsersOrPermission(CREATE_USERS);
2128 }
2129
2130 private static boolean hasPermissionGranted(String permission, int uid) {
2131 return ActivityManager.checkComponentPermission(permission, uid, /* owningUid= */ -1,
2132 /* exported= */ true) == PackageManager.PERMISSION_GRANTED;
2133 }
Antonio Kantek4cf199d2020-03-27 15:56:13 -07002134}