Expose initial user as a Shell command.

Test: atest InitialUserSetterTest CarHelperServiceTest
Test: adb shell dumpsys car_service --services CarUserService \
      |grep 'Initial user'
Test: adb shell cmd car_service get-initial-user

Bug: 153104923
Bug: 153104378

Change-Id: I616bf02098bdde410ccae1bf18476088aec253b4
diff --git a/service/src/com/android/car/user/CarUserService.java b/service/src/com/android/car/user/CarUserService.java
index 95cc200..64e9ec4 100644
--- a/service/src/com/android/car/user/CarUserService.java
+++ b/service/src/com/android/car/user/CarUserService.java
@@ -140,6 +140,10 @@
     private final CopyOnWriteArrayList<PassengerCallback> mPassengerCallbacks =
             new CopyOnWriteArrayList<>();
 
+    @Nullable
+    @GuardedBy("mLockUser")
+    private UserInfo mInitialUser;
+
     /** Interface for callbaks related to passenger activities. */
     public interface PassengerCallback {
         /** Called when passenger is started at a certain zone. */
@@ -237,9 +241,10 @@
                 }
                 writer.println();
             }
-            writer.println("EnablePassengerSupport: " + mEnablePassengerSupport);
-            writer.println("User HAL timeout: " + mHalTimeoutMs + "ms");
-            writer.println("Relevant overlayable  properties");
+            writer.printf("EnablePassengerSupport: %s\n", mEnablePassengerSupport);
+            writer.printf("User HAL timeout: %dms\n",  mHalTimeoutMs);
+            writer.printf("Initial user: %s\n", mInitialUser);
+            writer.println("Relevant overlayable properties");
             Resources res = mContext.getResources();
             writer.printf("%sowner_name=%s\n", indent,
                     res.getString(com.android.internal.R.string.owner_name));
@@ -527,6 +532,57 @@
     }
 
     /**
+     * Gets the initial foreground user after the device boots or resumes from suspension.
+     *
+     * <p>When the OEM supports the User HAL, the initial user won't be available until the HAL
+     * returns the initial value to {@code CarService} - if HAL takes too long or times out, this
+     * method returns {@code null}.
+     *
+     * <p>If the HAL eventually times out, {@code CarService} will fallback to its default behavior
+     * (like switching to the last active user), and this method will return the result of such
+     * operation.
+     *
+     * <p>Notice that if {@code CarService} crashes, subsequent calls to this method will return
+     * {@code null}.
+     *
+     * @hide
+     */
+    @Nullable
+    public UserInfo getInitialUser() {
+        checkInteractAcrossUsersPermission("getInitialUser");
+        synchronized (mLockUser) {
+            return mInitialUser;
+        }
+    }
+
+    // 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.
+     */
+    public void setInitialUser(@Nullable UserInfo user) {
+        Log.i(TAG_USER, "setInitialUser: " + user);
+        synchronized (mLockUser) {
+            mInitialUser = user;
+        }
+        if (user == null) {
+            // This mean InitialUserSetter failed and could not fallback, so the initial user was
+            // not switched (and most likely is SYSTEM_USER).
+            // TODO(b/153104378): should we set it to ActivityManager.getCurrentUser() instead?
+            Log.wtf(TAG_USER, "Initial user set to null");
+        }
+    }
+
+    /**
      * Calls the User HAL to get the initial user info.
      *
      * @param requestType type as defined by {@code InitialUserInfoRequestType}.