Add new feature for running services in "isolated" sandbox processes.

This reserves a range of uids (for each user) in which these processes
run.  These uids are not associated with an application, so they
effectively run with no permissions.  When a Service requests to
run in such a process through android:isolatedProcess="true", each
time it is brought up a new isolated process is started with its
own unique uid.

What we have so far gives us the basic infrastructure; more work
remains to further lock down what these uids have access to.

Change-Id: Ibfd27c75619cba61f528f46ede9113f98dc5f45b
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index e4cfc99..bf632a9 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -134,7 +134,7 @@
     private static final boolean DEBUG_RESULTS = false;
     private static final boolean DEBUG_BACKUP = true;
     private static final boolean DEBUG_CONFIGURATION = false;
-    private static final boolean DEBUG_SERVICE = true;
+    private static final boolean DEBUG_SERVICE = false;
     private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
     private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";");
     private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003;
@@ -3764,13 +3764,17 @@
     }
 
     private void setupGraphicsSupport(LoadedApk info) {
+        if (Process.isIsolated()) {
+            // Isolated processes aren't going to do UI.
+            return;
+        }
         try {
             int uid = Process.myUid();
             String[] packages = getPackageManager().getPackagesForUid(uid);
 
             // If there are several packages in this application we won't
             // initialize the graphics disk caches 
-            if (packages.length == 1) {
+            if (packages != null && packages.length == 1) {
                 ContextImpl appContext = new ContextImpl();
                 appContext.init(info, null, this);
 
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index fcbcd81..d9bbb4a 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -119,7 +119,7 @@
         final int myUid = Process.myUid();
         mResDir = aInfo.uid == myUid ? aInfo.sourceDir
                 : aInfo.publicSourceDir;
-        if (!UserId.isSameUser(aInfo.uid, myUid)) {
+        if (!UserId.isSameUser(aInfo.uid, myUid) && !Process.isIsolated()) {
             aInfo.dataDir = PackageManager.getDataDirForUser(UserId.getUserId(myUid),
                     mPackageName);
         }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index faee873..2023f82 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2581,6 +2581,11 @@
                 false)) {
             s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
         }
+        if (sa.getBoolean(
+                com.android.internal.R.styleable.AndroidManifestService_isolatedProcess,
+                false)) {
+            s.info.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
+        }
 
         sa.recycle();
 
diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java
index 612e345..7ee84ab 100644
--- a/core/java/android/content/pm/ServiceInfo.java
+++ b/core/java/android/content/pm/ServiceInfo.java
@@ -42,10 +42,17 @@
     public static final int FLAG_STOP_WITH_TASK = 0x0001;
 
     /**
+     * Bit in {@link #flags}: If set, the service will run in its own
+     * isolated process.  Set from the
+     * {@link android.R.attr#isolatedProcess} attribute.
+     */
+    public static final int FLAG_ISOLATED_PROCESS = 0x0002;
+
+    /**
      * Options that have been set in the service declaration in the
      * manifest.
      * These include:
-     * {@link #FLAG_STOP_WITH_TASK}
+     * {@link #FLAG_STOP_WITH_TASK}, {@link #FLAG_ISOLATED_PROCESS}.
      */
     public int flags;
 
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index cdf235d..0746af8 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -119,7 +119,19 @@
      * Last of application-specific UIDs starting at
      * {@link #FIRST_APPLICATION_UID}.
      */
-    public static final int LAST_APPLICATION_UID = 99999;
+    public static final int LAST_APPLICATION_UID = 89999;
+
+    /**
+     * First uid used for fully isolated sandboxed processes (with no permissions of their own)
+     * @hide
+     */
+    public static final int FIRST_ISOLATED_UID = 99000;
+
+    /**
+     * Last uid used for fully isolated sandboxed processes (with no permissions of their own)
+     * @hide
+     */
+    public static final int LAST_ISOLATED_UID = 99999;
 
     /**
      * Defines a secondary group id for access to the bluetooth hardware.
@@ -576,6 +588,15 @@
     public static final native int myUid();
 
     /**
+     * Returns whether the current process is in an isolated sandbox.
+     * @hide
+     */
+    public static final boolean isIsolated() {
+        int uid = UserId.getAppId(myUid());
+        return uid >= FIRST_ISOLATED_UID && uid <= LAST_ISOLATED_UID;
+    }
+
+    /**
      * Returns the UID assigned to a particular user name, or -1 if there is
      * none.  If the given string consists of only numbers, it is converted
      * directly to a uid.
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index dbd49fb..92c59ab 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1235,6 +1235,10 @@
              when the user remove a task rooted in an activity owned by
              the application.  The default is false. -->
         <attr name="stopWithTask" format="boolean" />
+        <!-- If set to true, this service will run under a special process
+             that is isolated from the rest of the system.  The only communication
+             with it is through the Service API (binding and starting). -->
+        <attr name="isolatedProcess" format="boolean" />
     </declare-styleable>
     
     <!-- The <code>receiver</code> tag declares an
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index e3c2bd8..1b91643 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3482,4 +3482,10 @@
   <public type="color" name="holo_orange_dark" id="0x01060019" />
   <public type="color" name="holo_purple" id="0x0106001a" />
   <public type="color" name="holo_blue_bright" id="0x0106001b" />
+
+<!-- ===============================================================
+     Resources added in version 16 of the platform (Jelly Bean)
+     =============================================================== -->
+  <public type="attr" name="isolatedProcess" id="0x010103a7" />
+
 </resources>