Merge "Push sharedUserIds info to config/sdcardfs."
diff --git a/core/tests/packagemanagertests/src/android/content/pm/KernelPackageMappingTests.java b/core/tests/packagemanagertests/src/android/content/pm/KernelPackageMappingTests.java
index 1097bc7..01382aa 100644
--- a/core/tests/packagemanagertests/src/android/content/pm/KernelPackageMappingTests.java
+++ b/core/tests/packagemanagertests/src/android/content/pm/KernelPackageMappingTests.java
@@ -17,14 +17,9 @@
 package android.content.pm;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 import android.content.Context;
 import android.os.FileUtils;
-import android.os.Process;
 import android.os.ServiceManager;
 import android.os.UserManager;
 import android.support.test.InstrumentationRegistry;
@@ -32,7 +27,6 @@
 import android.util.Log;
 
 import org.junit.After;
-import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -86,12 +80,23 @@
     }
 
     @Test
+    public void testSharedInstalledPrimary() throws Exception {
+        assertEquals("1001", getContent(getKernelPackageFile("shared:android.uid.phone", "appid")));
+    }
+
+    @Test
     public void testInstalledAll() throws Exception {
         assertEquals("", getContent(getKernelPackageFile("com.android.settings",
                 "excluded_userids")));
     }
 
     @Test
+    public void testSharedInstalledAll() throws Exception {
+        assertEquals("", getContent(getKernelPackageFile("shared:android.uid.phone",
+                "excluded_userids")));
+    }
+
+    @Test
     public void testNotInstalledSecondary() throws Exception {
         mSecondaryUser = getUserManager().createUser("Secondary", 0);
         assertEquals(Integer.toString(mSecondaryUser.id),
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 6a7e654..e2818b7 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -2634,6 +2634,10 @@
             writeKernelMappingLPr(ps);
         }
 
+        for (final SharedUserSetting sus : mSharedUsers.values()) {
+            knownSet.remove(sus.getSandboxName());
+        }
+
         // Remove any unclaimed mappings
         for (int i = 0; i < knownSet.size(); i++) {
             final String name = knownSet.valueAt(i);
@@ -2644,30 +2648,42 @@
         }
     }
 
+    void writeKernelMappingLPr(SharedUserSetting sus) {
+        if (mKernelMappingFilename == null || sus == null || sus.name == null) return;
+
+        writeKernelMappingLPr(sus.getSandboxName(), sus.userId, sus.getNotInstalledUserIds());
+    }
+
     void writeKernelMappingLPr(PackageSetting ps) {
         if (mKernelMappingFilename == null || ps == null || ps.name == null) return;
 
-        KernelPackageState cur = mKernelMapping.get(ps.name);
+        writeKernelMappingLPr(ps.name, ps.appId, ps.getNotInstalledUserIds());
+        if (ps.sharedUser != null) {
+            writeKernelMappingLPr(ps.sharedUser);
+        }
+    }
+
+    void writeKernelMappingLPr(String name, int appId, int[] excludedUserIds) {
+        KernelPackageState cur = mKernelMapping.get(name);
         final boolean firstTime = cur == null;
-        int[] excludedUserIds = ps.getNotInstalledUserIds();
         final boolean userIdsChanged = firstTime
                 || !Arrays.equals(excludedUserIds, cur.excludedUserIds);
 
         // Package directory
-        final File dir = new File(mKernelMappingFilename, ps.name);
+        final File dir = new File(mKernelMappingFilename, name);
 
         if (firstTime) {
             dir.mkdir();
             // Create a new mapping state
             cur = new KernelPackageState();
-            mKernelMapping.put(ps.name, cur);
+            mKernelMapping.put(name, cur);
         }
 
         // If mapping is incorrect or non-existent, write the appid file
-        if (cur.appId != ps.appId) {
+        if (cur.appId != appId) {
             final File appIdFile = new File(dir, "appid");
-            writeIntToFile(appIdFile, ps.appId);
-            if (DEBUG_KERNEL) Slog.d(TAG, "Mapping " + ps.name + " to " + ps.appId);
+            writeIntToFile(appIdFile, appId);
+            if (DEBUG_KERNEL) Slog.d(TAG, "Mapping " + name + " to " + appId);
         }
 
         if (userIdsChanged) {
@@ -2677,7 +2693,7 @@
                         excludedUserIds[i])) {
                     writeIntToFile(new File(dir, "excluded_userids"), excludedUserIds[i]);
                     if (DEBUG_KERNEL) Slog.d(TAG, "Writing " + excludedUserIds[i] + " to "
-                            + ps.name + "/excluded_userids");
+                            + name + "/excluded_userids");
                 }
             }
             // Build the inclusion list -- the ids to remove from the exclusion list
@@ -2687,7 +2703,7 @@
                         writeIntToFile(new File(dir, "clear_userid"),
                                 cur.excludedUserIds[i]);
                         if (DEBUG_KERNEL) Slog.d(TAG, "Writing " + cur.excludedUserIds[i] + " to "
-                                + ps.name + "/clear_userid");
+                                + name + "/clear_userid");
 
                     }
                 }
diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
index 1a8b2af..32826e5 100644
--- a/services/core/java/com/android/server/pm/SharedUserSetting.java
+++ b/services/core/java/com/android/server/pm/SharedUserSetting.java
@@ -23,6 +23,10 @@
 import android.util.ArraySet;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.internal.util.ArrayUtils;
+
+import libcore.util.EmptyArray;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -144,6 +148,28 @@
         }
     }
 
+    /** Returns userIds which doesn't have any packages with this sharedUserId */
+    public int[] getNotInstalledUserIds() {
+        int[] excludedUserIds = null;
+        for (PackageSetting ps : packages) {
+            final int[] userIds = ps.getNotInstalledUserIds();
+            if (excludedUserIds == null) {
+                excludedUserIds = userIds;
+            } else {
+                for (int userId : excludedUserIds) {
+                    if (!ArrayUtils.contains(userIds, userId)) {
+                        excludedUserIds = ArrayUtils.removeInt(excludedUserIds, userId);
+                    }
+                }
+            }
+        }
+        return excludedUserIds == null ? EmptyArray.INT : excludedUserIds;
+    }
+
+    public String getSandboxName() {
+        return "shared:" + name;
+    }
+
     /** Updates all fields in this shared user setting from another. */
     public SharedUserSetting updateFrom(SharedUserSetting sharedUser) {
         copyFrom(sharedUser);