Merge "More APIs for encryption-aware apps."
diff --git a/api/current.txt b/api/current.txt
index d330dad..5eb08da 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9062,6 +9062,7 @@
     field public android.content.pm.ApplicationInfo applicationInfo;
     field public int descriptionRes;
     field public boolean enabled;
+    field public boolean encryptionAware;
     field public boolean exported;
     field public java.lang.String processName;
   }
@@ -9483,6 +9484,7 @@
     field public static final int GET_CONFIGURATIONS = 16384; // 0x4000
     field public static final int GET_DISABLED_COMPONENTS = 512; // 0x200
     field public static final int GET_DISABLED_UNTIL_USED_COMPONENTS = 32768; // 0x8000
+    field public static final int GET_ENCRYPTION_UNAWARE_COMPONENTS = 262144; // 0x40000
     field public static final int GET_GIDS = 256; // 0x100
     field public static final int GET_INSTRUMENTATION = 16; // 0x10
     field public static final int GET_INTENT_FILTERS = 32; // 0x20
diff --git a/api/system-current.txt b/api/system-current.txt
index f101856..dd2e67d 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -9322,6 +9322,7 @@
     field public android.content.pm.ApplicationInfo applicationInfo;
     field public int descriptionRes;
     field public boolean enabled;
+    field public boolean encryptionAware;
     field public boolean exported;
     field public java.lang.String processName;
   }
@@ -9780,6 +9781,7 @@
     field public static final int GET_CONFIGURATIONS = 16384; // 0x4000
     field public static final int GET_DISABLED_COMPONENTS = 512; // 0x200
     field public static final int GET_DISABLED_UNTIL_USED_COMPONENTS = 32768; // 0x8000
+    field public static final int GET_ENCRYPTION_UNAWARE_COMPONENTS = 262144; // 0x40000
     field public static final int GET_GIDS = 256; // 0x100
     field public static final int GET_INSTRUMENTATION = 16; // 0x10
     field public static final int GET_INTENT_FILTERS = 32; // 0x20
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index b809baa..ac54960 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2952,6 +2952,11 @@
         }
     }
 
+    /** {@hide} */
+    public static final int FLAG_OR_STOPPED = 1 << 0;
+    /** {@hide} */
+    public static final int FLAG_WITH_AMNESIA = 1 << 1;
+
     /**
      * Return whether the given user is actively running.  This means that
      * the user is in the "started" state, not "stopped" -- it is currently
@@ -2963,7 +2968,7 @@
      */
     public boolean isUserRunning(int userid) {
         try {
-            return ActivityManagerNative.getDefault().isUserRunning(userid, false);
+            return ActivityManagerNative.getDefault().isUserRunning(userid, 0);
         } catch (RemoteException e) {
             return false;
         }
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 2ac6cf9..4449e4f 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1984,8 +1984,8 @@
         case IS_USER_RUNNING_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             int userid = data.readInt();
-            boolean orStopping = data.readInt() != 0;
-            boolean result = isUserRunning(userid, orStopping);
+            int _flags = data.readInt();
+            boolean result = isUserRunning(userid, _flags);
             reply.writeNoException();
             reply.writeInt(result ? 1 : 0);
             return true;
@@ -5265,12 +5265,12 @@
         return userInfo;
     }
 
-    public boolean isUserRunning(int userid, boolean orStopping) throws RemoteException {
+    public boolean isUserRunning(int userid, int flags) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeInt(userid);
-        data.writeInt(orStopping ? 1 : 0);
+        data.writeInt(flags);
         mRemote.transact(IS_USER_RUNNING_TRANSACTION, data, reply, 0);
         reply.readException();
         boolean result = reply.readInt() != 0;
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index fcc040b..b69a480 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -392,7 +392,7 @@
     public boolean startUserInBackground(int userid) throws RemoteException;
     public int stopUser(int userid, IStopUserCallback callback) throws RemoteException;
     public UserInfo getCurrentUser() throws RemoteException;
-    public boolean isUserRunning(int userid, boolean orStopping) throws RemoteException;
+    public boolean isUserRunning(int userid, int flags) throws RemoteException;
     public int[] getRunningUserIds() throws RemoteException;
 
     public boolean removeTask(int taskId) throws RemoteException;
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 6bc2ac3..52c2f9b 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -466,7 +466,7 @@
      *
      * @hide
      */
-    public static final int PRIVATE_FLAG_DEVICE_ENCRYPTED = 1 << 5;
+    public static final int PRIVATE_FLAG_FORCE_DEVICE_ENCRYPTED = 1 << 5;
 
     /**
      * Private/hidden flags. See {@code PRIVATE_FLAG_...} constants.
@@ -963,7 +963,7 @@
                 .getDataUserCredentialEncryptedPackageDirectory(volumeUuid, userId, packageName)
                 .getAbsolutePath();
 
-        if ((privateFlags & PRIVATE_FLAG_DEVICE_ENCRYPTED) != 0) {
+        if ((privateFlags & PRIVATE_FLAG_FORCE_DEVICE_ENCRYPTED) != 0) {
             dataDir = deviceEncryptedDataDir;
         } else {
             dataDir = credentialEncryptedDataDir;
diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java
index f27fc2a..ad7ebe5 100644
--- a/core/java/android/content/pm/ComponentInfo.java
+++ b/core/java/android/content/pm/ComponentInfo.java
@@ -63,7 +63,14 @@
      * &lt;provider&gt; tag.
      */
     public boolean exported = false;
-    
+
+    /**
+     * Indicate if this component is aware of encryption lifecycle, and can be
+     * safely run before the user has entered their credentials (such as a lock
+     * pattern or PIN).
+     */
+    public boolean encryptionAware = false;
+
     public ComponentInfo() {
     }
 
@@ -74,6 +81,7 @@
         descriptionRes = orig.descriptionRes;
         enabled = orig.enabled;
         exported = orig.exported;
+        encryptionAware = orig.encryptionAware;
     }
 
     @Override public CharSequence loadLabel(PackageManager pm) {
@@ -143,7 +151,7 @@
     protected void dumpFront(Printer pw, String prefix) {
         super.dumpFront(pw, prefix);
         pw.println(prefix + "enabled=" + enabled + " exported=" + exported
-                + " processName=" + processName);
+                + " encryptionAware=" + encryptionAware + " processName=" + processName);
         if (descriptionRes != 0) {
             pw.println(prefix + "description=" + descriptionRes);
         }
@@ -171,6 +179,7 @@
         dest.writeInt(descriptionRes);
         dest.writeInt(enabled ? 1 : 0);
         dest.writeInt(exported ? 1 : 0);
+        dest.writeInt(encryptionAware ? 1 : 0);
     }
     
     protected ComponentInfo(Parcel source) {
@@ -183,6 +192,7 @@
         descriptionRes = source.readInt();
         enabled = (source.readInt() != 0);
         exported = (source.readInt() != 0);
+        encryptionAware = (source.readInt() != 0);
     }
     
     /**
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index c57fc89..566de4e 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -234,6 +234,24 @@
     public static final int MATCH_ALL = 0x00020000;
 
     /**
+     * {@link PackageInfo} flag: include components which aren't encryption
+     * aware in the returned info, regardless of the current user state.
+     */
+    public static final int GET_ENCRYPTION_UNAWARE_COMPONENTS = 0x00040000;
+
+    /**
+     * {@link PackageInfo} flag: return components as if the given user is
+     * running with amnesia. This typically limits the component to only those
+     * marked as {@link ComponentInfo#encryptionAware}, unless
+     * {@link #GET_ENCRYPTION_UNAWARE_COMPONENTS} is also specified.
+     * <p>
+     * This flag is for internal use only.
+     *
+     * @hide
+     */
+    public static final int FLAG_USER_RUNNING_WITH_AMNESIA = 0x00080000;
+
+    /**
      * Flag for {@link addCrossProfileIntentFilter}: if this flag is set:
      * when resolving an intent that matches the {@link CrossProfileIntentFilter}, the current
      * profile will be skipped.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 20e76d6..f176d89 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2632,6 +2632,11 @@
             ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
         }
 
+        if (sa.getBoolean(R.styleable.AndroidManifestApplication_forceDeviceEncrypted, false)
+                && (flags & PARSE_IS_SYSTEM) != 0) {
+            ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORCE_DEVICE_ENCRYPTED;
+        }
+
         String str;
         str = sa.getNonConfigurationString(
                 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
@@ -3229,6 +3234,9 @@
 
             a.info.lockTaskLaunchMode =
                     sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
+
+            a.info.encryptionAware = sa.getBoolean(
+                    R.styleable.AndroidManifestActivity_encryptionAware, false);
         } else {
             a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
             a.info.configChanges = 0;
@@ -3243,6 +3251,9 @@
                     setExported = true;
                 }
             }
+
+            a.info.encryptionAware = sa.getBoolean(
+                    R.styleable.AndroidManifestActivity_encryptionAware, false);
         }
 
         sa.recycle();
@@ -3643,6 +3654,9 @@
             }
         }
 
+        p.info.encryptionAware = sa.getBoolean(
+                R.styleable.AndroidManifestProvider_encryptionAware, false);
+
         sa.recycle();
 
         if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
@@ -3923,6 +3937,9 @@
             }
         }
 
+        s.info.encryptionAware = sa.getBoolean(
+                R.styleable.AndroidManifestService_encryptionAware, false);
+
         sa.recycle();
 
         if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index e892349..aff90b7 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -718,7 +718,7 @@
     public boolean isUserRunning(UserHandle user) {
         try {
             return ActivityManagerNative.getDefault().isUserRunning(
-                    user.getIdentifier(), false);
+                    user.getIdentifier(), 0);
         } catch (RemoteException e) {
             return false;
         }
@@ -733,8 +733,9 @@
      */
     public boolean isUserRunningOrStopping(UserHandle user) {
         try {
+            // TODO: reconcile stopped vs stopping?
             return ActivityManagerNative.getDefault().isUserRunning(
-                    user.getIdentifier(), true);
+                    user.getIdentifier(), ActivityManager.FLAG_OR_STOPPED);
         } catch (RemoteException e) {
             return false;
         }
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 07ac471..184f2ab 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -571,6 +571,11 @@
          single integer, with higher numbers considered to be better. -->
     <attr name="priority" format="integer" />
 
+    <!-- Indicate if this component is aware of encryption lifecycle, and can be
+         safely run before the user has entered their credentials (such as a lock
+         pattern or PIN). -->
+    <attr name="encryptionAware" format="boolean" />
+
     <!-- Specify how an activity should be launched.  See the
          <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back
          Stack</a> document for important information on how these options impact
@@ -1277,6 +1282,7 @@
         <attr name="usesCleartextTraffic" />
         <attr name="multiArch" />
         <attr name="extractNativeLibs" />
+        <attr name="forceDeviceEncrypted" format="boolean" />
     </declare-styleable>
     <!-- The <code>permission</code> tag declares a security permission that can be
          used to control access from other packages to specific components or
@@ -1652,6 +1658,7 @@
         <attr name="enabled" />
         <attr name="exported" />
         <attr name="singleUser" />
+        <attr name="encryptionAware" />
     </declare-styleable>
 
     <!-- Attributes that can be supplied in an AndroidManifest.xml
@@ -1735,6 +1742,7 @@
              with it is through the Service API (binding and starting). -->
         <attr name="isolatedProcess" format="boolean" />
         <attr name="singleUser" />
+        <attr name="encryptionAware" />
     </declare-styleable>
 
     <!-- The <code>receiver</code> tag declares an
@@ -1770,6 +1778,7 @@
         <attr name="enabled" />
         <attr name="exported" />
         <attr name="singleUser" />
+        <attr name="encryptionAware" />
     </declare-styleable>
 
     <!-- The <code>activity</code> tag declares an
@@ -1842,6 +1851,7 @@
         <attr name="supportsPictureInPicture" />
         <attr name="lockTaskMode" />
         <attr name="showForAllUsers" />
+        <attr name="encryptionAware" />
     </declare-styleable>
 
     <!-- The <code>activity-alias</code> tag declares a new
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 1ff13b2..9ac4ba3 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -980,7 +980,7 @@
             if (user.isRestricted() && (parentUserId == user.restrictedProfileParentId)) {
                 addSharedAccountAsUser(account, user.id);
                 try {
-                    if (ActivityManagerNative.getDefault().isUserRunning(user.id, false)) {
+                    if (ActivityManagerNative.getDefault().isUserRunning(user.id, 0)) {
                         mMessageHandler.sendMessage(mMessageHandler.obtainMessage(
                                 MESSAGE_COPY_SHARED_ACCOUNT, parentUserId, user.id, account));
                     }
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index befaaef..2820216 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -2334,7 +2334,7 @@
                         sr.userId, sr.crashCount, sr.shortName, app.pid);
                 bringDownServiceLocked(sr);
             } else if (!allowRestart
-                    || !mAm.mUserController.isUserRunningLocked(sr.userId, false)) {
+                    || !mAm.mUserController.isUserRunningLocked(sr.userId, 0)) {
                 bringDownServiceLocked(sr);
             } else {
                 boolean canceled = scheduleServiceRestartLocked(sr, true);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 13401cd..4998b57 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5328,7 +5328,7 @@
                         Slog.w(TAG, "Failed trying to unstop package "
                                 + packageName + ": " + e);
                     }
-                    if (mUserController.isUserRunningLocked(user, false)) {
+                    if (mUserController.isUserRunningLocked(user, 0)) {
                         forceStopPackageLocked(packageName, pkgUid, "from pid " + callingPid);
                     }
                 }
@@ -9812,7 +9812,7 @@
 
                 // Make sure that the user who owns this provider is running.  If not,
                 // we don't want to allow it to run.
-                if (!mUserController.isUserRunningLocked(userId, false)) {
+                if (!mUserController.isUserRunningLocked(userId, 0)) {
                     Slog.w(TAG, "Unable to launch app "
                             + cpi.applicationInfo.packageName + "/"
                             + cpi.applicationInfo.uid + " for provider "
@@ -16640,7 +16640,7 @@
         // If not, we will just skip it. Make an exception for shutdown broadcasts
         // and upgrade steps.
 
-        if (userId != UserHandle.USER_ALL && !mUserController.isUserRunningLocked(userId, false)) {
+        if (userId != UserHandle.USER_ALL && !mUserController.isUserRunningLocked(userId, 0)) {
             if ((callingUid != Process.SYSTEM_UID
                     || (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0)
                     && !Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
@@ -19991,7 +19991,7 @@
     }
 
     @Override
-    public boolean isUserRunning(int userId, boolean orStopped) {
+    public boolean isUserRunning(int userId, int flags) {
         if (checkCallingPermission(INTERACT_ACROSS_USERS)
                 != PackageManager.PERMISSION_GRANTED) {
             String msg = "Permission Denial: isUserRunning() from pid="
@@ -20002,7 +20002,7 @@
             throw new SecurityException(msg);
         }
         synchronized (this) {
-            return mUserController.isUserRunningLocked(userId, orStopped);
+            return mUserController.isUserRunningLocked(userId, flags);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 4085489..cbc13fe 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -947,14 +947,18 @@
         return mStartedUserArray;
     }
 
-    boolean isUserRunningLocked(int userId, boolean orStopped) {
+    boolean isUserRunningLocked(int userId, int flags) {
         UserState state = getStartedUserStateLocked(userId);
         if (state == null) {
             return false;
         }
-        if (orStopped) {
+        if ((flags & ActivityManager.FLAG_OR_STOPPED) != 0) {
             return true;
         }
+        if ((flags & ActivityManager.FLAG_WITH_AMNESIA) != 0) {
+            // TODO: add in amnesia lifecycle
+            return false;
+        }
         return state.mState != UserState.STATE_STOPPING
                 && state.mState != UserState.STATE_SHUTDOWN;
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 11fa38c..09efefa 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3053,15 +3053,40 @@
         }
     }
 
+    /**
+     * Augment the given flags depending on current user running state. This is
+     * purposefully done before acquiring {@link #mPackages} lock.
+     */
+    private int augmentFlagsForUser(int flags, int userId) {
+        final IActivityManager am = ActivityManagerNative.getDefault();
+        if (am == null) {
+            // We must be early in boot, so the best we can do is assume the
+            // user is fully running.
+            return flags;
+        }
+        final long token = Binder.clearCallingIdentity();
+        try {
+            if (am.isUserRunning(userId, ActivityManager.FLAG_WITH_AMNESIA)) {
+                flags |= PackageManager.FLAG_USER_RUNNING_WITH_AMNESIA;
+            }
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+        return flags;
+    }
+
     @Override
     public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        flags = augmentFlagsForUser(flags, userId);
         enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get activity info");
         synchronized (mPackages) {
             PackageParser.Activity a = mActivities.mActivities.get(component);
 
             if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a);
-            if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
+            if (a != null && mSettings.isEnabledAndVisibleLPr(a.info, flags, userId)) {
                 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                 if (ps == null) return null;
                 return PackageParser.generateActivityInfo(a, flags, ps.readUserState(userId),
@@ -3100,12 +3125,13 @@
     @Override
     public ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        flags = augmentFlagsForUser(flags, userId);
         enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get receiver info");
         synchronized (mPackages) {
             PackageParser.Activity a = mReceivers.mActivities.get(component);
             if (DEBUG_PACKAGE_INFO) Log.v(
                 TAG, "getReceiverInfo " + component + ": " + a);
-            if (a != null && mSettings.isEnabledLPr(a.info, flags, userId)) {
+            if (a != null && mSettings.isEnabledAndVisibleLPr(a.info, flags, userId)) {
                 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                 if (ps == null) return null;
                 return PackageParser.generateActivityInfo(a, flags, ps.readUserState(userId),
@@ -3118,12 +3144,13 @@
     @Override
     public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        flags = augmentFlagsForUser(flags, userId);
         enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get service info");
         synchronized (mPackages) {
             PackageParser.Service s = mServices.mServices.get(component);
             if (DEBUG_PACKAGE_INFO) Log.v(
                 TAG, "getServiceInfo " + component + ": " + s);
-            if (s != null && mSettings.isEnabledLPr(s.info, flags, userId)) {
+            if (s != null && mSettings.isEnabledAndVisibleLPr(s.info, flags, userId)) {
                 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                 if (ps == null) return null;
                 return PackageParser.generateServiceInfo(s, flags, ps.readUserState(userId),
@@ -3136,12 +3163,13 @@
     @Override
     public ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        flags = augmentFlagsForUser(flags, userId);
         enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get provider info");
         synchronized (mPackages) {
             PackageParser.Provider p = mProviders.mProviders.get(component);
             if (DEBUG_PACKAGE_INFO) Log.v(
                 TAG, "getProviderInfo " + component + ": " + p);
-            if (p != null && mSettings.isEnabledLPr(p.info, flags, userId)) {
+            if (p != null && mSettings.isEnabledAndVisibleLPr(p.info, flags, userId)) {
                 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                 if (ps == null) return null;
                 return PackageParser.generateProviderInfo(p, flags, ps.readUserState(userId),
@@ -4233,6 +4261,7 @@
     public ResolveInfo resolveIntent(Intent intent, String resolvedType,
             int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        flags = augmentFlagsForUser(flags, userId);
         enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "resolve intent");
         List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
         return chooseBestActivity(intent, resolvedType, flags, query, userId);
@@ -4374,10 +4403,12 @@
         return null;
     }
 
+    // TODO: handle preferred activities missing while user has amnesia
     ResolveInfo findPreferredActivity(Intent intent, String resolvedType, int flags,
             List<ResolveInfo> query, int priority, boolean always,
             boolean removeMatches, boolean debug, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        flags = augmentFlagsForUser(flags, userId);
         // writer
         synchronized (mPackages) {
             if (intent.getSelector() != null) {
@@ -4576,6 +4607,7 @@
     public List<ResolveInfo> queryIntentActivities(Intent intent,
             String resolvedType, int flags, int userId) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
+        flags = augmentFlagsForUser(flags, userId);
         enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "query intent activities");
         ComponentName comp = intent.getComponent();
         if (comp == null) {
@@ -5041,6 +5073,7 @@
             Intent[] specifics, String[] specificTypes, Intent intent,
             String resolvedType, int flags, int userId) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
+        flags = augmentFlagsForUser(flags, userId);
         enforceCrossUserPermission(Binder.getCallingUid(), userId, false,
                 false, "query intent activity options");
         final String resultsAction = intent.getAction();
@@ -5213,6 +5246,7 @@
     public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags,
             int userId) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
+        flags = augmentFlagsForUser(flags, userId);
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -5248,8 +5282,9 @@
 
     @Override
     public ResolveInfo resolveService(Intent intent, String resolvedType, int flags, int userId) {
-        List<ResolveInfo> query = queryIntentServices(intent, resolvedType, flags, userId);
         if (!sUserManager.exists(userId)) return null;
+        flags = augmentFlagsForUser(flags, userId);
+        List<ResolveInfo> query = queryIntentServices(intent, resolvedType, flags, userId);
         if (query != null) {
             if (query.size() >= 1) {
                 // If there is more than one service with the same priority,
@@ -5264,6 +5299,7 @@
     public List<ResolveInfo> queryIntentServices(Intent intent, String resolvedType, int flags,
             int userId) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
+        flags = augmentFlagsForUser(flags, userId);
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -5301,6 +5337,7 @@
     public List<ResolveInfo> queryIntentContentProviders(
             Intent intent, String resolvedType, int flags, int userId) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
+        flags = augmentFlagsForUser(flags, userId);
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
@@ -5417,6 +5454,7 @@
     public ParceledListSlice<PackageInfo> getPackagesHoldingPermissions(
             String[] permissions, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        flags = augmentFlagsForUser(flags, userId);
         final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
 
         // writer
@@ -5444,6 +5482,7 @@
     @Override
     public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        flags = augmentFlagsForUser(flags, userId);
         final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
 
         // writer
@@ -5510,6 +5549,7 @@
     @Override
     public ProviderInfo resolveContentProvider(String name, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        flags = augmentFlagsForUser(flags, userId);
         // reader
         synchronized (mPackages) {
             final PackageParser.Provider provider = mProvidersByAuthority.get(name);
@@ -5517,7 +5557,7 @@
                     ? mSettings.mPackages.get(provider.owner.packageName)
                     : null;
             return ps != null
-                    && mSettings.isEnabledLPr(provider.info, flags, userId)
+                    && mSettings.isEnabledAndVisibleLPr(provider.info, flags, userId)
                     && (!mSafeMode || (provider.info.applicationInfo.flags
                             &ApplicationInfo.FLAG_SYSTEM) != 0)
                     ? PackageParser.generateProviderInfo(provider, flags,
@@ -5558,12 +5598,15 @@
     @Override
     public ParceledListSlice<ProviderInfo> queryContentProviders(String processName,
             int uid, int flags) {
+        final int userId = processName != null ? UserHandle.getUserId(uid)
+                : UserHandle.getCallingUserId();
+        if (!sUserManager.exists(userId)) return null;
+        flags = augmentFlagsForUser(flags, userId);
+
         ArrayList<ProviderInfo> finalList = null;
         // reader
         synchronized (mPackages) {
             final Iterator<PackageParser.Provider> i = mProviders.mProviders.values().iterator();
-            final int userId = processName != null ?
-                    UserHandle.getUserId(uid) : UserHandle.getCallingUserId();
             while (i.hasNext()) {
                 final PackageParser.Provider p = i.next();
                 PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
@@ -5571,7 +5614,7 @@
                         && (processName == null
                                 || (p.info.processName.equals(processName)
                                         && UserHandle.isSameApp(p.info.applicationInfo.uid, uid)))
-                        && mSettings.isEnabledLPr(p.info, flags, userId)
+                        && mSettings.isEnabledAndVisibleLPr(p.info, flags, userId)
                         && (!mSafeMode
                                 || (p.info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0)) {
                     if (finalList == null) {
@@ -8975,7 +9018,7 @@
         protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
                 int match, int userId) {
             if (!sUserManager.exists(userId)) return null;
-            if (!mSettings.isEnabledLPr(info.activity.info, mFlags, userId)) {
+            if (!mSettings.isEnabledAndVisibleLPr(info.activity.info, mFlags, userId)) {
                 return null;
             }
             final PackageParser.Activity activity = info.activity;
@@ -9199,7 +9242,7 @@
                 int match, int userId) {
             if (!sUserManager.exists(userId)) return null;
             final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
-            if (!mSettings.isEnabledLPr(info.service.info, mFlags, userId)) {
+            if (!mSettings.isEnabledAndVisibleLPr(info.service.info, mFlags, userId)) {
                 return null;
             }
             final PackageParser.Service service = info.service;
@@ -9422,7 +9465,7 @@
             if (!sUserManager.exists(userId))
                 return null;
             final PackageParser.ProviderIntentInfo info = filter;
-            if (!mSettings.isEnabledLPr(info.provider.info, mFlags, userId)) {
+            if (!mSettings.isEnabledAndVisibleLPr(info.provider.info, mFlags, userId)) {
                 return null;
             }
             final PackageParser.Provider provider = info.provider;
@@ -9761,7 +9804,7 @@
             IActivityManager am = ActivityManagerNative.getDefault();
             final boolean isSystem =
                     isSystemApp(pkgSetting) || isUpdatedSystemApp(pkgSetting);
-            if (isSystem && am.isUserRunning(userId, false)) {
+            if (isSystem && am.isUserRunning(userId, 0)) {
                 // The just-installed/enabled app is bundled on the system, so presumed
                 // to be able to run automatically without needing an explicit launch.
                 // Send it a BOOT_COMPLETED if it would ordinarily have gotten one.
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 8b99305..de14739 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -2248,7 +2248,8 @@
 
             StringBuilder sb = new StringBuilder();
             for (final PackageSetting pkg : mPackages.values()) {
-                if (pkg.pkg == null || pkg.pkg.applicationInfo == null) {
+                if (pkg.pkg == null || pkg.pkg.applicationInfo == null
+                        || pkg.pkg.applicationInfo.dataDir == null) {
                     Slog.w(TAG, "Skipping " + pkg + " due to missing metadata");
                     continue;
                 }
@@ -3750,8 +3751,13 @@
     private String compToString(ArraySet<String> cmp) {
         return cmp != null ? Arrays.toString(cmp.toArray()) : "[]";
     }
- 
-    boolean isEnabledLPr(ComponentInfo componentInfo, int flags, int userId) {
+
+    boolean isEnabledAndVisibleLPr(ComponentInfo componentInfo, int flags, int userId) {
+        return isEnabledLPr(componentInfo, flags, userId)
+                && isVisibleLPr(componentInfo, flags);
+    }
+
+    private boolean isEnabledLPr(ComponentInfo componentInfo, int flags, int userId) {
         if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) {
             return true;
         }
@@ -3792,6 +3798,17 @@
         return componentInfo.enabled;
     }
 
+    private boolean isVisibleLPr(ComponentInfo componentInfo, int flags) {
+        if ((flags & PackageManager.GET_ENCRYPTION_UNAWARE_COMPONENTS) != 0) {
+            return true;
+        }
+        if ((flags & PackageManager.FLAG_USER_RUNNING_WITH_AMNESIA) != 0) {
+            // When running with amnesia, we can only run encryption-aware apps
+            return componentInfo.encryptionAware;
+        }
+        return true;
+    }
+
     String getInstallerPackageNameLPr(String packageName) {
         final PackageSetting pkg = mPackages.get(packageName);
         if (pkg == null) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 4929960..3eb2d11 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -2286,7 +2286,7 @@
         } else {
             pw.println("Users:");
             for (int i = 0; i < users.size(); i++) {
-                String running = am.isUserRunning(users.get(i).id, false) ? " running" : "";
+                String running = am.isUserRunning(users.get(i).id, 0) ? " running" : "";
                 pw.println("\t" + users.get(i).toString() + running);
             }
             return 0;