Wire up lifecycle, send unlocked broadcast.

When the correct lock pattern is presented, ask the system to also
unlock credential-encrypted storage, if enabled.  The token passed
along is empty for now, but can be wired up to gatekeeper in the
future.

During each system boot, ask vold to lock all users keys to give us
a known starting state.  This also has the effect of chmod'ing away
any CE data when in emulation mode.

Define and send a new foreground broadcast when the CE storage is
unlocked for the first time.  Add stronger last-ditch checking for
encryption-awareness before starting an app.

Bug: 22358539
Change-Id: Id1f1bece96a2b4e6f061214d565d51c7396ab521
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index b30905e..9c29149 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -624,6 +624,23 @@
             throw new SecurityException(msg);
         }
 
+        final long binderToken = Binder.clearCallingIdentity();
+        try {
+            return unlockUserCleared(userId, token);
+        } finally {
+            Binder.restoreCallingIdentity(binderToken);
+        }
+    }
+
+    boolean unlockUserCleared(final int userId, byte[] token) {
+        synchronized (mService) {
+            final UserState uss = mStartedUsers.get(userId);
+            if (uss.unlocked) {
+                // Bail early when already unlocked
+                return true;
+            }
+        }
+
         final UserInfo userInfo = getUserInfo(userId);
         final IMountService mountService = IMountService.Stub
                 .asInterface(ServiceManager.getService("mount"));
@@ -631,7 +648,7 @@
             mountService.unlockUserKey(userId, userInfo.serialNumber, token);
         } catch (RemoteException e) {
             Slog.w(TAG, "Failed to unlock: " + e.getMessage());
-            throw e.rethrowAsRuntimeException();
+            return false;
         }
 
         synchronized (mService) {
@@ -639,6 +656,11 @@
             updateUserUnlockedState(uss);
         }
 
+        final Intent intent = new Intent(Intent.ACTION_USER_UNLOCKED);
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
+        mService.broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
+                AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID, userId);
+
         return true;
     }
 
@@ -1011,7 +1033,7 @@
         if ((flags & ActivityManager.FLAG_OR_STOPPED) != 0) {
             return true;
         }
-        if ((flags & ActivityManager.FLAG_WITH_AMNESIA) != 0) {
+        if ((flags & ActivityManager.FLAG_AND_LOCKED) != 0) {
             // If user is currently locked, we fall through to default "running"
             // behavior below
             if (state.unlocked) {