Update PRE_BOOT_COMPLETED for FBE.

Now that CE data isn't available until after a user is unlocked, we
need to delay the PRE_BOOT_COMPLETED broadcasts.  This is done by
adding a new RUNNING_UNLOCKING user state to the UserController
lifecycle.

We now track the last fingerprint a user was logged in under, and we
dispatch PRE_BOOT receivers when that fingerprint changes.  To work
around battery pull issues, we only persist the updated fingerprint
once all PRE_BOOT receivers have finished.  This is less granular
than the original solution, but it's still correct.  We only consider
a user as "logged in" once it transitions into the RUNNING_UNLOCKED
state.

When starting a process, track if the user was "unlocked" when
started, so that we only spin up unaware providers in processes
started before user unlock.

Add generic IProgressListener to communicate PRE_BOOT progress and
strings up to lock screen.  For now, LockSettingsService just blocks
until finished, but it could display these strings in the future.

Bug: 27220885
Change-Id: I349439776b885acd32f6a578d8951ffd95640be2
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index ac19e24..5263c37 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -20,6 +20,7 @@
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UserIdInt;
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
@@ -37,6 +38,7 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.Environment;
@@ -122,6 +124,7 @@
     private static final String ATTR_ID = "id";
     private static final String ATTR_CREATION_TIME = "created";
     private static final String ATTR_LAST_LOGGED_IN_TIME = "lastLoggedIn";
+    private static final String ATTR_LAST_LOGGED_IN_FINGERPRINT = "lastLoggedInFingerprint";
     private static final String ATTR_SERIAL_NO = "serialNumber";
     private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber";
     private static final String ATTR_PARTIAL = "partial";
@@ -380,8 +383,6 @@
             removeUserState(ui.id);
         }
 
-        onUserForeground(UserHandle.USER_SYSTEM);
-
         mAppOpsService = IAppOpsService.Stub.asInterface(
                 ServiceManager.getService(Context.APP_OPS_SERVICE));
 
@@ -1541,6 +1542,8 @@
             serializer.attribute(null, ATTR_CREATION_TIME, Long.toString(userInfo.creationTime));
             serializer.attribute(null, ATTR_LAST_LOGGED_IN_TIME,
                     Long.toString(userInfo.lastLoggedInTime));
+            serializer.attribute(null, ATTR_LAST_LOGGED_IN_FINGERPRINT,
+                    userInfo.lastLoggedInFingerprint);
             if (userInfo.iconPath != null) {
                 serializer.attribute(null,  ATTR_ICON_PATH, userInfo.iconPath);
             }
@@ -1671,6 +1674,7 @@
         String iconPath = null;
         long creationTime = 0L;
         long lastLoggedInTime = 0L;
+        String lastLoggedInFingerprint = null;
         int profileGroupId = UserInfo.NO_PROFILE_GROUP_ID;
         int restrictedProfileParentId = UserInfo.NO_PROFILE_GROUP_ID;
         boolean partial = false;
@@ -1711,6 +1715,8 @@
                 iconPath = parser.getAttributeValue(null, ATTR_ICON_PATH);
                 creationTime = readLongAttribute(parser, ATTR_CREATION_TIME, 0);
                 lastLoggedInTime = readLongAttribute(parser, ATTR_LAST_LOGGED_IN_TIME, 0);
+                lastLoggedInFingerprint = parser.getAttributeValue(null,
+                        ATTR_LAST_LOGGED_IN_FINGERPRINT);
                 profileGroupId = readIntAttribute(parser, ATTR_PROFILE_GROUP_ID,
                         UserInfo.NO_PROFILE_GROUP_ID);
                 restrictedProfileParentId = readIntAttribute(parser,
@@ -1763,6 +1769,7 @@
             userInfo.serialNumber = serialNumber;
             userInfo.creationTime = creationTime;
             userInfo.lastLoggedInTime = lastLoggedInTime;
+            userInfo.lastLoggedInFingerprint = lastLoggedInFingerprint;
             userInfo.partial = partial;
             userInfo.guestToRemove = guestToRemove;
             userInfo.profileGroupId = profileGroupId;
@@ -2553,7 +2560,7 @@
      * Called right before a user is unlocked. This gives us a chance to prepare
      * app storage.
      */
-    public void onBeforeUnlockUser(int userId) {
+    public void onBeforeUnlockUser(@UserIdInt int userId) {
         final int userSerial = getUserSerialNumber(userId);
         prepareUserStorage(userId, userSerial, StorageManager.FLAG_STORAGE_CE);
         mPm.reconcileAppsData(userId, StorageManager.FLAG_STORAGE_CE);
@@ -2563,17 +2570,19 @@
      * Make a note of the last started time of a user and do some cleanup.
      * @param userId the user that was just foregrounded
      */
-    public void onUserForeground(int userId) {
+    public void onUserLoggedIn(@UserIdInt int userId) {
         UserData userData = getUserDataNoChecks(userId);
         if (userData == null || userData.info.partial) {
             Slog.w(LOG_TAG, "userForeground: unknown user #" + userId);
             return;
         }
-        long now = System.currentTimeMillis();
+
+        final long now = System.currentTimeMillis();
         if (now > EPOCH_PLUS_30_YEARS) {
             userData.info.lastLoggedInTime = now;
-            scheduleWriteUser(userData);
         }
+        userData.info.lastLoggedInFingerprint = Build.FINGERPRINT;
+        scheduleWriteUser(userData);
     }
 
     /**
@@ -2838,6 +2847,8 @@
                         sb.append(" ago");
                         pw.println(sb);
                     }
+                    pw.print("    Last logged in fingerprint: ");
+                    pw.println(userInfo.lastLoggedInFingerprint);
                     pw.print("    Has profile owner: ");
                     pw.println(mIsUserManaged.get(userId));
                     pw.println("    Restrictions:");