Moved Initial User setter logic from CarServiceHelperService to CarUserService

Bug: 158026653
Bug: 160819016
Test: atest CarServiceUnitTest:com.android.car.user.CarUserServiceTest
      atest CarServicesTest:com.android.internal.car.CarHelperServiceTest
Change-Id: I3799f75f3d24bb8b3e9cab277a5dae5920ab6726
diff --git a/service/src/com/android/car/user/CarUserService.java b/service/src/com/android/car/user/CarUserService.java
index e4aeea8..8c2634c 100644
--- a/service/src/com/android/car/user/CarUserService.java
+++ b/service/src/com/android/car/user/CarUserService.java
@@ -40,6 +40,8 @@
 import android.car.userlib.CarUserManagerHelper;
 import android.car.userlib.CommonConstants.CarUserServiceConstants;
 import android.car.userlib.HalCallback;
+import android.car.userlib.InitialUserSetter;
+import android.car.userlib.InitialUserSetter.InitialUserInfo;
 import android.car.userlib.UserHalHelper;
 import android.car.userlib.UserHelper;
 import android.content.ComponentName;
@@ -52,6 +54,7 @@
 import android.graphics.Bitmap;
 import android.hardware.automotive.vehicle.V2_0.CreateUserRequest;
 import android.hardware.automotive.vehicle.V2_0.CreateUserStatus;
+import android.hardware.automotive.vehicle.V2_0.InitialUserInfoRequestType;
 import android.hardware.automotive.vehicle.V2_0.InitialUserInfoResponse;
 import android.hardware.automotive.vehicle.V2_0.InitialUserInfoResponseAction;
 import android.hardware.automotive.vehicle.V2_0.RemoveUserRequest;
@@ -141,6 +144,7 @@
     private final IActivityManager mAm;
     private final UserManager mUserManager;
     private final int mMaxRunningUsers;
+    private final InitialUserSetter mInitialUserSetter;
     private final boolean mEnablePassengerSupport;
 
     private final Object mLockUser = new Object();
@@ -234,13 +238,14 @@
             @NonNull CarUserManagerHelper carUserManagerHelper, @NonNull UserManager userManager,
             @NonNull IActivityManager am, int maxRunningUsers) {
         this(context, hal, carUserManagerHelper, userManager, am, maxRunningUsers,
-                new UserMetrics());
+                new UserMetrics(), /* initialUserSetter= */ null);
     }
 
     @VisibleForTesting
     CarUserService(@NonNull Context context, @NonNull UserHalService hal,
             @NonNull CarUserManagerHelper carUserManagerHelper, @NonNull UserManager userManager,
-            @NonNull IActivityManager am, int maxRunningUsers, UserMetrics userMetrics) {
+            @NonNull IActivityManager am, int maxRunningUsers, @NonNull UserMetrics userMetrics,
+            @Nullable InitialUserSetter initialUserSetter) {
         if (Log.isLoggable(TAG_USER, Log.DEBUG)) {
             Log.d(TAG_USER, "constructed");
         }
@@ -253,6 +258,11 @@
         mLastPassengerId = UserHandle.USER_NULL;
         mEnablePassengerSupport = context.getResources().getBoolean(R.bool.enablePassengerSupport);
         mUserMetrics = userMetrics;
+        if (initialUserSetter == null) {
+            mInitialUserSetter = new InitialUserSetter(context, (u) -> setInitialUser(u));
+        } else {
+            mInitialUserSetter = initialUserSetter;
+        }
     }
 
     @Override
@@ -695,17 +705,6 @@
         }
     }
 
-    // TODO(b/150413515): temporary method called by ICarImpl.setInitialUser(int userId), as for
-    // some reason passing the whole UserInfo through a raw binder transaction  is not working.
-    /**
-     * Sets the initial foreground user after the device boots or resumes from suspension.
-     */
-    public void setInitialUser(@UserIdInt int userId) {
-        UserInfo initialUser = userId == UserHandle.USER_NULL ? null
-                : mUserManager.getUserInfo(userId);
-        setInitialUser(initialUser);
-    }
-
     /**
      * Sets the initial foreground user after the device boots or resumes from suspension.
      */
@@ -724,6 +723,90 @@
     }
 
     /**
+     * Call to start user at the android startup.
+     */
+    public void initBootUser() {
+        int requestType = getInitialUserInfoRequestType();
+        EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_REQ, requestType,
+                mHalTimeoutMs);
+        checkManageUsersPermission("startInitialUser");
+
+        if (!isUserHalSupported()) {
+            fallbackToDefaultInitialUserBehavior(/* userLocales= */ null);
+            return;
+        }
+
+        UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager);
+        mHal.getInitialUserInfo(requestType, mHalTimeoutMs, usersInfo, (status, resp) -> {
+            if (resp != null) {
+                EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_RESP,
+                        status, resp.action, resp.userToSwitchOrCreate.userId,
+                        resp.userToSwitchOrCreate.flags, resp.userNameToCreate, resp.userLocales);
+
+                String userLocales = resp.userLocales;
+                InitialUserInfo info;
+                switch (resp.action) {
+                    case InitialUserInfoResponseAction.SWITCH:
+                        int userId = resp.userToSwitchOrCreate.userId;
+                        if (userId <= 0) {
+                            Log.w(TAG, "invalid (or missing) user id sent by HAL: " + userId);
+                            fallbackToDefaultInitialUserBehavior(userLocales);
+                            break;
+                        }
+                        info = new InitialUserSetter.Builder(InitialUserSetter.TYPE_SWITCH)
+                                .setUserLocales(userLocales)
+                                .setSwitchUserId(userId)
+                                .build();
+                        mInitialUserSetter.set(info);
+                        break;
+
+                    case InitialUserInfoResponseAction.CREATE:
+                        int halFlags = resp.userToSwitchOrCreate.flags;
+                        String userName =  resp.userNameToCreate;
+                        info = new InitialUserSetter.Builder(InitialUserSetter.TYPE_CREATE)
+                                .setUserLocales(userLocales)
+                                .setNewUserName(userName)
+                                .setNewUserFlags(halFlags)
+                                .build();
+                        mInitialUserSetter.set(info);
+                        break;
+
+                    case InitialUserInfoResponseAction.DEFAULT:
+                        fallbackToDefaultInitialUserBehavior(userLocales);
+                        break;
+                    default:
+                        Log.w(TAG_USER, "invalid response action on " + resp);
+                        fallbackToDefaultInitialUserBehavior(/* user locale */ null);
+                        break;
+
+                }
+            } else {
+                EventLog.writeEvent(EventLogTags.CAR_USER_SVC_INITIAL_USER_INFO_RESP, status);
+                fallbackToDefaultInitialUserBehavior(/* user locale */ null);
+            }
+        });
+    }
+
+    private void fallbackToDefaultInitialUserBehavior(String userLocales) {
+        InitialUserInfo info = new InitialUserSetter.Builder(
+                InitialUserSetter.TYPE_DEFAULT_BEHAVIOR)
+                .setUserLocales(userLocales)
+                .build();
+        mInitialUserSetter.set(info);
+    }
+
+    @VisibleForTesting
+    int getInitialUserInfoRequestType() {
+        if (!mCarUserManagerHelper.hasInitialUser()) {
+            return InitialUserInfoRequestType.FIRST_BOOT;
+        }
+        if (mContext.getPackageManager().isDeviceUpgrading()) {
+            return InitialUserInfoRequestType.FIRST_BOOT_AFTER_OTA;
+        }
+        return InitialUserInfoRequestType.COLD_BOOT;
+    }
+
+    /**
      * Calls the User HAL to get the initial user info.
      *
      * @param requestType type as defined by {@code InitialUserInfoRequestType}.