Do not skip user starting for user 0

- USER_SYSTEM is in special state and startUser call is skipped without changing
  it into running state.
- Force the whole process for user 0 while non-user 0 keep the same behavior
  as it should not happen for those users.

Bug: 124460424
Test: Test system bootup (for 1st boot and subsequent boot)

Change-Id: I7adc6766c0ac33f766e7ca8769f555973f533ba3
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 688020f..cc4116e 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -956,15 +956,26 @@
             final int oldUserId = getCurrentUserId();
             if (oldUserId == userId) {
                 final UserState state = getStartedUserState(userId);
-                if (state != null && state.state == STATE_RUNNING_UNLOCKED) {
-                    // We'll skip all later code, so we must tell listener it's already unlocked.
-                    try {
-                        unlockListener.onFinished(userId, null);
-                    } catch (RemoteException ignore) {
-                        // Ignore.
+                if (state == null) {
+                    Slog.wtf(TAG, "Current user has no UserState");
+                    // continue starting.
+                } else {
+                    if (userId == UserHandle.USER_SYSTEM && state.state == STATE_BOOTING) {
+                        // system user start explicitly requested. should continue starting as it
+                        // is not in running state.
+                    } else {
+                        if (state.state == STATE_RUNNING_UNLOCKED) {
+                            // We'll skip all later code, so we must tell listener it's already
+                            // unlocked.
+                            try {
+                                unlockListener.onFinished(userId, null);
+                            } catch (RemoteException ignore) {
+                                // Ignore.
+                            }
+                        }
+                        return true;
                     }
                 }
-                return true;
             }
 
             if (foreground) {
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index 04abeca1..f39c716 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -34,7 +34,9 @@
 import static com.google.common.truth.Truth.assertWithMessage;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyBoolean;
@@ -64,6 +66,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.os.UserManagerInternal;
 import android.platform.test.annotations.Presubmit;
 import android.util.Log;
@@ -321,6 +324,14 @@
         verify(mInjector.getWindowManager(), times(1)).setSwitchingUser(false);
     }
 
+    @Test
+    public void testExplicitSystenUserStartInBackground() {
+        setUpUser(UserHandle.USER_SYSTEM, 0);
+        assertFalse(mUserController.isSystemUserStarted());
+        assertTrue(mUserController.startUser(UserHandle.USER_SYSTEM, false, null));
+        assertTrue(mUserController.isSystemUserStarted());
+    }
+
     private void setUpUser(int userId, int flags) {
         UserInfo userInfo = new UserInfo(userId, "User" + userId, flags);
         when(mInjector.mUserManagerMock.getUserInfo(eq(userId))).thenReturn(userInfo);
@@ -417,6 +428,12 @@
         @Override
         void reportCurWakefulnessUsageEvent() {
         }
+
+        @Override
+        boolean isRuntimeRestarted() {
+            // to pass all metrics related calls
+            return true;
+        }
     }
 
     private static class TestHandler extends Handler {