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/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 72292be..b64261d 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -28,7 +28,9 @@
 import android.content.res.CompatibilityInfo;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.Process;
 import android.os.SystemClock;
+import android.os.UserId;
 import android.util.PrintWriterPrinter;
 import android.util.TimeUtils;
 
@@ -44,6 +46,9 @@
 class ProcessRecord {
     final BatteryStatsImpl.Uid.Proc batteryStats; // where to collect runtime statistics
     final ApplicationInfo info; // all about the first app in the process
+    final boolean isolated;     // true if this is a special isolated process
+    final int uid;              // uid of process; may be different from 'info' if isolated
+    final int userId;           // user of process.
     final String processName;   // name of the process
     // List of packages running in the process
     final HashSet<String> pkgList = new HashSet<String>();
@@ -147,6 +152,12 @@
     void dump(PrintWriter pw, String prefix) {
         final long now = SystemClock.uptimeMillis();
 
+        pw.print(prefix); pw.print("user #"); pw.print(userId);
+                pw.print(" uid="); pw.print(info.uid);
+        if (uid != info.uid) {
+            pw.print(" ISOLATED uid="); pw.print(uid);
+        }
+        pw.println();
         if (info.className != null) {
             pw.print(prefix); pw.print("class="); pw.println(info.className);
         }
@@ -267,9 +278,12 @@
     }
     
     ProcessRecord(BatteryStatsImpl.Uid.Proc _batteryStats, IApplicationThread _thread,
-            ApplicationInfo _info, String _processName) {
+            ApplicationInfo _info, String _processName, int _uid) {
         batteryStats = _batteryStats;
         info = _info;
+        isolated = _info.uid != _uid;
+        uid = _uid;
+        userId = UserId.getUserId(_uid);
         processName = _processName;
         pkgList.add(_info.packageName);
         thread = _thread;
@@ -343,7 +357,18 @@
         sb.append(':');
         sb.append(processName);
         sb.append('/');
-        sb.append(info.uid);
+        if (info.uid < Process.FIRST_APPLICATION_UID) {
+            sb.append(uid);
+        } else {
+            sb.append('u');
+            sb.append(userId);
+            sb.append('a');
+            sb.append(info.uid%Process.FIRST_APPLICATION_UID);
+            if (uid != info.uid) {
+                sb.append('i');
+                sb.append(UserId.getAppId(uid) - Process.FIRST_ISOLATED_UID);
+            }
+        }
     }
     
     public String toString() {