Implemented CarService.getInitialUserInfo().

Test: atest CarServiceUnitTest#testGetUserInfo*

Bug: 146207078
Change-Id: Ib708f48a9ea1bd45ffe7329f7386e760bba16a2a
diff --git a/service/src/com/android/car/user/CarUserService.java b/service/src/com/android/car/user/CarUserService.java
index e2f21b5..5ec0933 100644
--- a/service/src/com/android/car/user/CarUserService.java
+++ b/service/src/com/android/car/user/CarUserService.java
@@ -34,6 +34,9 @@
 import android.content.Context;
 import android.content.pm.UserInfo;
 import android.graphics.Bitmap;
+import android.hardware.automotive.vehicle.V2_0.InitialUserInfoResponseAction;
+import android.hardware.automotive.vehicle.V2_0.UserFlags;
+import android.hardware.automotive.vehicle.V2_0.UsersInfo;
 import android.location.LocationManager;
 import android.os.Binder;
 import android.os.Bundle;
@@ -52,6 +55,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.IResultReceiver;
+import com.android.internal.util.Preconditions;
 import com.android.internal.util.UserIcons;
 
 import java.io.PrintWriter;
@@ -74,6 +78,12 @@
  */
 public final class CarUserService extends ICarUserService.Stub implements CarServiceBase {
 
+    /** Extra used to represent a user id in a {@link IResultReceiver} response. */
+    public static final String BUNDLE_USER_ID = "user.id";
+    /** Extra used to represent user flags in a {@link IResultReceiver} response. */
+    public static final String BUNDLE_USER_FLAGS = "user.flags";
+    /** Extra used to represent a user name in a {@link IResultReceiver} response. */
+    public static final String BUNDLE_USER_NAME = "user.name";
 
     private final Context mContext;
     private final CarUserManagerHelper mCarUserManagerHelper;
@@ -466,6 +476,75 @@
         mLifecycleListeners.remove(uid);
     }
 
+    @Override
+    public void getInitialUserInfo(int requestType, int timeoutMs,
+            @NonNull UserInfo[] existingUsers, @UserIdInt int currentUserId,
+            @NonNull IResultReceiver receiver) {
+
+        // TODO(b/144120654): use helper to generate USerInfo
+        UsersInfo usersInfo = new UsersInfo();
+        usersInfo.numberUsers = existingUsers.length;
+        boolean foundCurrentUser = false;
+        for (int i = 0; i < existingUsers.length; i++) {
+            UserInfo user = existingUsers[i];
+            android.hardware.automotive.vehicle.V2_0.UserInfo halUser =
+                    new android.hardware.automotive.vehicle.V2_0.UserInfo();
+            halUser.userId = user.id;
+            int flags = UserFlags.NONE;
+            if (user.id == UserHandle.USER_SYSTEM) {
+                flags |= UserFlags.SYSTEM;
+            }
+            if (user.isAdmin()) {
+                flags |= UserFlags.ADMIN;
+            }
+            if (user.isGuest()) {
+                flags |= UserFlags.GUEST;
+            }
+            if (user.isEphemeral()) {
+                flags |= UserFlags.EPHEMERAL;
+            }
+            halUser.flags = flags;
+            usersInfo.existingUsers.add(halUser);
+            if (user.id == currentUserId) {
+                // TODO(b/144120654): unit test for when it isn't there (on helper method), or
+                // change signature so the currentUser argument is a UserInfo)
+                foundCurrentUser = true;
+                usersInfo.currentUser.userId = currentUserId;
+                usersInfo.currentUser.flags = flags;
+            }
+        }
+        Preconditions.checkArgument(foundCurrentUser,
+                "no user with id " + currentUserId + " on " + existingUsers);
+
+        mHal.getInitialUserInfo(requestType, timeoutMs, usersInfo, (status, resp) -> {
+            try {
+                Bundle resultData = null;
+                if (resp != null) {
+                    switch (resp.action) {
+                        case InitialUserInfoResponseAction.SWITCH:
+                            resultData = new Bundle();
+                            resultData.putInt(BUNDLE_USER_ID, resp.userToSwitchOrCreate.userId);
+                            break;
+                        case InitialUserInfoResponseAction.CREATE:
+                            resultData = new Bundle();
+                            resultData.putInt(BUNDLE_USER_FLAGS, resp.userToSwitchOrCreate.flags);
+                            resultData.putString(BUNDLE_USER_NAME, resp.userNameToCreate);
+                            break;
+                        case InitialUserInfoResponseAction.DEFAULT:
+                            // do nothing
+                            break;
+                        default:
+                            // That's ok, it will be the same as DEFAULT...
+                            Log.w(TAG_USER, "invalid response action on " + resp);
+                    }
+                }
+                receiver.send(status, resultData);
+            } catch (RemoteException e) {
+                Log.w(TAG_USER, "Could not send result back to receiver", e);
+            }
+        });
+    }
+
     /** Returns whether the given user is a system user. */
     private static boolean isSystemUser(@UserIdInt int userId) {
         return userId == UserHandle.USER_SYSTEM;