Merge "move away from MediaDebug and use ADebug instead for video editor engine"
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index 4ed2489..cfc2d16 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -90,6 +90,7 @@
     struct svcinfo *next;
     void *ptr;
     struct binder_death death;
+    int allow_isolated;
     unsigned len;
     uint16_t name[0];
 };
@@ -125,13 +126,21 @@
 };
   
 
-void *do_find_service(struct binder_state *bs, uint16_t *s, unsigned len)
+void *do_find_service(struct binder_state *bs, uint16_t *s, unsigned len, unsigned uid)
 {
     struct svcinfo *si;
     si = find_svc(s, len);
 
 //    ALOGI("check_service('%s') ptr = %p\n", str8(s), si ? si->ptr : 0);
     if (si && si->ptr) {
+        if (!si->allow_isolated) {
+            // If this service doesn't allow access from isolated processes,
+            // then check the uid to see if it is isolated.
+            unsigned appid = uid % AID_USER;
+            if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
+                return 0;
+            }
+        }
         return si->ptr;
     } else {
         return 0;
@@ -140,10 +149,11 @@
 
 int do_add_service(struct binder_state *bs,
                    uint16_t *s, unsigned len,
-                   void *ptr, unsigned uid)
+                   void *ptr, unsigned uid, int allow_isolated)
 {
     struct svcinfo *si;
-//    ALOGI("add_service('%s',%p) uid=%d\n", str8(s), ptr, uid);
+    //ALOGI("add_service('%s',%p,%s) uid=%d\n", str8(s), ptr,
+    //        allow_isolated ? "allow_isolated" : "!allow_isolated", uid);
 
     if (!ptr || (len == 0) || (len > 127))
         return -1;
@@ -175,6 +185,7 @@
         si->name[len] = '\0';
         si->death.func = svcinfo_death;
         si->death.ptr = si;
+        si->allow_isolated = allow_isolated;
         si->next = svclist;
         svclist = si;
     }
@@ -194,6 +205,7 @@
     unsigned len;
     void *ptr;
     uint32_t strict_policy;
+    int allow_isolated;
 
 //    ALOGI("target=%p code=%d pid=%d uid=%d\n",
 //         txn->target, txn->code, txn->sender_pid, txn->sender_euid);
@@ -217,7 +229,7 @@
     case SVC_MGR_GET_SERVICE:
     case SVC_MGR_CHECK_SERVICE:
         s = bio_get_string16(msg, &len);
-        ptr = do_find_service(bs, s, len);
+        ptr = do_find_service(bs, s, len, txn->sender_euid);
         if (!ptr)
             break;
         bio_put_ref(reply, ptr);
@@ -226,7 +238,8 @@
     case SVC_MGR_ADD_SERVICE:
         s = bio_get_string16(msg, &len);
         ptr = bio_get_ref(msg);
-        if (do_add_service(bs, s, len, ptr, txn->sender_euid))
+        allow_isolated = bio_get_uint32(msg) ? 1 : 0;
+        if (do_add_service(bs, s, len, ptr, txn->sender_euid, allow_isolated))
             return -1;
         break;
 
diff --git a/cmds/surfaceflinger/main_surfaceflinger.cpp b/cmds/surfaceflinger/main_surfaceflinger.cpp
index 78b1007..6dbcf5c 100644
--- a/cmds/surfaceflinger/main_surfaceflinger.cpp
+++ b/cmds/surfaceflinger/main_surfaceflinger.cpp
@@ -20,6 +20,6 @@
 using namespace android;
 
 int main(int argc, char** argv) {
-    SurfaceFlinger::publishAndJoinThreadPool();
+    SurfaceFlinger::publishAndJoinThreadPool(true);
     return 0;
 }
diff --git a/core/java/android/os/IServiceManager.java b/core/java/android/os/IServiceManager.java
index 9a5ff47..7b11c28 100644
--- a/core/java/android/os/IServiceManager.java
+++ b/core/java/android/os/IServiceManager.java
@@ -45,7 +45,8 @@
      * Place a new @a service called @a name into the service
      * manager.
      */
-    public void addService(String name, IBinder service) throws RemoteException;
+    public void addService(String name, IBinder service, boolean allowIsolated)
+                throws RemoteException;
 
     /**
      * Return a list of all currently running services.
diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java
index 1af24f4a..13b8b66 100644
--- a/core/java/android/os/ServiceManager.java
+++ b/core/java/android/os/ServiceManager.java
@@ -69,7 +69,24 @@
      */
     public static void addService(String name, IBinder service) {
         try {
-            getIServiceManager().addService(name, service);
+            getIServiceManager().addService(name, service, false);
+        } catch (RemoteException e) {
+            Log.e(TAG, "error in addService", e);
+        }
+    }
+
+    /**
+     * Place a new @a service called @a name into the service
+     * manager.
+     * 
+     * @param name the name of the new service
+     * @param service the service object
+     * @param allowIsolated set to true to allow isolated sandboxed processes
+     * to access this service
+     */
+    public static void addService(String name, IBinder service, boolean allowIsolated) {
+        try {
+            getIServiceManager().addService(name, service, allowIsolated);
         } catch (RemoteException e) {
             Log.e(TAG, "error in addService", e);
         }
diff --git a/core/java/android/os/ServiceManagerNative.java b/core/java/android/os/ServiceManagerNative.java
index 2aab0e6..43b5128 100644
--- a/core/java/android/os/ServiceManagerNative.java
+++ b/core/java/android/os/ServiceManagerNative.java
@@ -71,7 +71,8 @@
                 data.enforceInterface(IServiceManager.descriptor);
                 String name = data.readString();
                 IBinder service = data.readStrongBinder();
-                addService(name, service);
+                boolean allowIsolated = data.readInt() != 0;
+                addService(name, service, allowIsolated);
                 return true;
             }
     
@@ -136,13 +137,14 @@
         return binder;
     }
 
-    public void addService(String name, IBinder service)
+    public void addService(String name, IBinder service, boolean allowIsolated)
             throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IServiceManager.descriptor);
         data.writeString(name);
         data.writeStrongBinder(service);
+        data.writeInt(allowIsolated ? 1 : 0);
         mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
         reply.recycle();
         data.recycle();
diff --git a/core/java/android/os/UserId.java b/core/java/android/os/UserId.java
index 4124d51..286b674 100644
--- a/core/java/android/os/UserId.java
+++ b/core/java/android/os/UserId.java
@@ -56,6 +56,11 @@
         return getAppId(uid1) == getAppId(uid2);
     }
 
+    public static final boolean isIsolated(int uid) {
+        uid = getAppId(uid);
+        return uid >= Process.FIRST_ISOLATED_UID && uid <= Process.LAST_ISOLATED_UID;
+    }
+
     /**
      * Returns the user id for a given uid.
      * @hide
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 97658a1..1199cf7 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -717,6 +717,13 @@
         android:label="@string/permlab_removeTasks"
         android:description="@string/permdesc_removeTasks" />
 
+    <!-- @hide Change the screen compatibility mode of applications -->
+    <permission android:name="android.permission.SET_SCREEN_COMPATIBILITY"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="signature"
+        android:label="@string/permlab_setScreenCompatibility"
+        android:description="@string/permdesc_setScreenCompatibility" />
+
     <!-- Allows an application to modify the current configuration, such
          as locale. -->
     <permission android:name="android.permission.CHANGE_CONFIGURATION"
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index dc45c408..701782c 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -532,6 +532,13 @@
         tasks and kill their apps. Malicious apps may disrupt
         the behavior of other apps.</string>
 
+    <!-- Title of an application permission, allowing control of app screen compatibility mode -->
+    <string name="permlab_setScreenCompatibility">set screen compatibility</string>
+    <!-- Description of an application permission, allowing control of app screen compatibility mode -->
+    <string name="permdesc_setScreenCompatibility">Allows the app to control the
+        screen compatibility mode of other applications.  Malicious applications may
+        break the behavior of other applications.</string>
+
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_setDebugApp">enable app debugging</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
diff --git a/include/binder/BinderService.h b/include/binder/BinderService.h
index 2316fef..ca594d3 100644
--- a/include/binder/BinderService.h
+++ b/include/binder/BinderService.h
@@ -34,15 +34,15 @@
 class BinderService
 {
 public:
-    static status_t publish() {
+    static status_t publish(bool allowIsolated = false) {
         sp<IServiceManager> sm(defaultServiceManager());
-        return sm->addService(String16(SERVICE::getServiceName()), new SERVICE());
+        return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated);
     }
 
-    static void publishAndJoinThreadPool() {
+    static void publishAndJoinThreadPool(bool allowIsolated = false) {
         sp<ProcessState> proc(ProcessState::self());
         sp<IServiceManager> sm(defaultServiceManager());
-        sm->addService(String16(SERVICE::getServiceName()), new SERVICE());
+        sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated);
         ProcessState::self()->startThreadPool();
         IPCThreadState::self()->joinThreadPool();
     }
diff --git a/include/binder/IServiceManager.h b/include/binder/IServiceManager.h
index 24e9e99..2c297d6 100644
--- a/include/binder/IServiceManager.h
+++ b/include/binder/IServiceManager.h
@@ -47,7 +47,8 @@
      * Register a service.
      */
     virtual status_t            addService( const String16& name,
-                                            const sp<IBinder>& service) = 0;
+                                            const sp<IBinder>& service,
+                                            bool allowIsolated = false) = 0;
 
     /**
      * Return list of all existing services.
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 33b305d..1750640 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -151,12 +151,14 @@
         return reply.readStrongBinder();
     }
 
-    virtual status_t addService(const String16& name, const sp<IBinder>& service)
+    virtual status_t addService(const String16& name, const sp<IBinder>& service,
+            bool allowIsolated)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
         data.writeString16(name);
         data.writeStrongBinder(service);
+        data.writeInt32(allowIsolated ? 1 : 0);
         status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
         return err == NO_ERROR ? reply.readExceptionCode() : err;
     }
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 10a0efe..a110dd6 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -2093,7 +2093,7 @@
         try {
             ActivityManagerService m = mSelf;
             
-            ServiceManager.addService("activity", m);
+            ServiceManager.addService("activity", m, true);
             ServiceManager.addService("meminfo", new MemBinder(m));
             ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
             ServiceManager.addService("dbinfo", new DbBinder(m));
@@ -2964,37 +2964,52 @@
         return mCompatModePackages.compatibilityInfoForPackageLocked(ai);
     }
 
+    void enforceNotIsolatedCaller(String caller) {
+        if (UserId.isIsolated(Binder.getCallingUid())) {
+            throw new SecurityException("Isolated process not allowed to call " + caller);
+        }
+    }
+
     public int getFrontActivityScreenCompatMode() {
+        enforceNotIsolatedCaller("getFrontActivityScreenCompatMode");
         synchronized (this) {
             return mCompatModePackages.getFrontActivityScreenCompatModeLocked();
         }
     }
 
     public void setFrontActivityScreenCompatMode(int mode) {
+        enforceCallingPermission(android.Manifest.permission.SET_SCREEN_COMPATIBILITY,
+                "setFrontActivityScreenCompatMode");
         synchronized (this) {
             mCompatModePackages.setFrontActivityScreenCompatModeLocked(mode);
         }
     }
 
     public int getPackageScreenCompatMode(String packageName) {
+        enforceNotIsolatedCaller("getPackageScreenCompatMode");
         synchronized (this) {
             return mCompatModePackages.getPackageScreenCompatModeLocked(packageName);
         }
     }
 
     public void setPackageScreenCompatMode(String packageName, int mode) {
+        enforceCallingPermission(android.Manifest.permission.SET_SCREEN_COMPATIBILITY,
+                "setPackageScreenCompatMode");
         synchronized (this) {
             mCompatModePackages.setPackageScreenCompatModeLocked(packageName, mode);
         }
     }
 
     public boolean getPackageAskScreenCompat(String packageName) {
+        enforceNotIsolatedCaller("getPackageAskScreenCompat");
         synchronized (this) {
             return mCompatModePackages.getPackageAskCompatModeLocked(packageName);
         }
     }
 
     public void setPackageAskScreenCompat(String packageName, boolean ask) {
+        enforceCallingPermission(android.Manifest.permission.SET_SCREEN_COMPATIBILITY,
+                "setPackageAskScreenCompat");
         synchronized (this) {
             mCompatModePackages.setPackageAskCompatModeLocked(packageName, ask);
         }
@@ -3069,6 +3084,7 @@
             int grantedMode, IBinder resultTo,
             String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
             String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
+        enforceNotIsolatedCaller("startActivity");
         int userId = 0;
         if (intent.getCategories() != null && intent.getCategories().contains(Intent.CATEGORY_HOME)) {
             // Requesting home, set the identity to the current user
@@ -3093,6 +3109,7 @@
             int grantedMode, IBinder resultTo,
             String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
             String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
+        enforceNotIsolatedCaller("startActivityAndWait");
         WaitResult res = new WaitResult();
         int userId = Binder.getOrigCallingUser();
         mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
@@ -3107,6 +3124,7 @@
             int grantedMode, IBinder resultTo,
             String resultWho, int requestCode, boolean onlyIfNeeded,
             boolean debug, Configuration config) {
+        enforceNotIsolatedCaller("startActivityWithConfig");
         int ret = mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
                 grantedUriPermissions, grantedMode, resultTo, resultWho,
                 requestCode, onlyIfNeeded,
@@ -3118,6 +3136,7 @@
             IntentSender intent, Intent fillInIntent, String resolvedType,
             IBinder resultTo, String resultWho, int requestCode,
             int flagsMask, int flagsValues) {
+        enforceNotIsolatedCaller("startActivityIntentSender");
         // Refuse possible leaked file descriptors
         if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
             throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -3259,6 +3278,7 @@
 
     public final int startActivities(IApplicationThread caller,
             Intent[] intents, String[] resolvedTypes, IBinder resultTo) {
+        enforceNotIsolatedCaller("startActivities");
         int ret = mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo,
                 Binder.getOrigCallingUser());
         return ret;
@@ -4020,6 +4040,7 @@
     
     public boolean clearApplicationUserData(final String packageName,
             final IPackageDataObserver observer, final int userId) {
+        enforceNotIsolatedCaller("clearApplicationUserData");
         int uid = Binder.getCallingUid();
         int pid = Binder.getCallingPid();
         long callingId = Binder.clearCallingIdentity();
@@ -4208,6 +4229,7 @@
     }
 
     public void closeSystemDialogs(String reason) {
+        enforceNotIsolatedCaller("closeSystemDialogs");
         Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
         if (reason != null) {
@@ -4248,6 +4270,7 @@
     
     public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
             throws RemoteException {
+        enforceNotIsolatedCaller("getProcessMemoryInfo");
         Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];
         for (int i=pids.length-1; i>=0; i--) {
             infos[i] = new Debug.MemoryInfo();
@@ -4257,6 +4280,7 @@
     }
 
     public long[] getProcessPss(int[] pids) throws RemoteException {
+        enforceNotIsolatedCaller("getProcessPss");
         long[] pss = new long[pids.length];
         for (int i=pids.length-1; i>=0; i--) {
             pss[i] = Debug.getPss(pids[i]);
@@ -4825,10 +4849,12 @@
     }
 
     public void showBootMessage(final CharSequence msg, final boolean always) {
+        enforceNotIsolatedCaller("showBootMessage");
         mWindowManager.showBootMessage(msg, always);
     }
 
     public void dismissKeyguardOnNextActivity() {
+        enforceNotIsolatedCaller("dismissKeyguardOnNextActivity");
         synchronized (this) {
             mMainStack.dismissKeyguardOnNextActivityLocked();
         }
@@ -4991,6 +5017,7 @@
     public IIntentSender getIntentSender(int type,
             String packageName, IBinder token, String resultWho,
             int requestCode, Intent[] intents, String[] resolvedTypes, int flags) {
+        enforceNotIsolatedCaller("getIntentSender");
         // Refuse possible leaked file descriptors
         if (intents != null) {
             if (intents.length < 1) {
@@ -5293,6 +5320,10 @@
         if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID) {
             return PackageManager.PERMISSION_GRANTED;
         }
+        // Isolated processes don't get any permissions.
+        if (UserId.isIsolated(uid)) {
+            return PackageManager.PERMISSION_DENIED;
+        }
         // If there is a uid that owns whatever is being accessed, it has
         // blanket access to it regardless of the permissions it requires.
         if (owningUid >= 0 && UserId.isSameApp(uid, owningUid)) {
@@ -5445,6 +5476,8 @@
     }
 
     public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
+        enforceNotIsolatedCaller("checkUriPermission");
+
         // Another redirected-binder-call permissions check as in
         // {@link checkComponentPermission}.
         Identity tlsIdentity = sCallerIdentity.get();
@@ -5595,6 +5628,7 @@
 
     public int checkGrantUriPermission(int callingUid, String targetPkg,
             Uri uri, int modeFlags) {
+        enforceNotIsolatedCaller("checkGrantUriPermission");
         synchronized(this) {
             return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags);
         }
@@ -5703,6 +5737,7 @@
 
     public void grantUriPermission(IApplicationThread caller, String targetPkg,
             Uri uri, int modeFlags) {
+        enforceNotIsolatedCaller("grantUriPermission");
         synchronized(this) {
             final ProcessRecord r = getRecordForAppLocked(caller);
             if (r == null) {
@@ -5826,6 +5861,7 @@
 
     public void revokeUriPermission(IApplicationThread caller, Uri uri,
             int modeFlags) {
+        enforceNotIsolatedCaller("revokeUriPermission");
         synchronized(this) {
             final ProcessRecord r = getRecordForAppLocked(caller);
             if (r == null) {
@@ -5870,6 +5906,7 @@
 
     @Override
     public IBinder newUriPermissionOwner(String name) {
+        enforceNotIsolatedCaller("newUriPermissionOwner");
         synchronized(this) {
             UriPermissionOwner owner = new UriPermissionOwner(this, name);
             return owner.getExternalTokenLocked();
@@ -6406,6 +6443,7 @@
      * @return Returns true if the move completed, false if not.
      */
     public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
+        enforceNotIsolatedCaller("moveActivityTaskToBack");
         synchronized(this) {
             final long origId = Binder.clearCallingIdentity();
             int taskId = getTaskForActivityLocked(token, !nonRoot);
@@ -6460,6 +6498,7 @@
     }
 
     public void finishOtherInstances(IBinder token, ComponentName className) {
+        enforceNotIsolatedCaller("finishOtherInstances");
         synchronized(this) {
             final long origId = Binder.clearCallingIdentity();
 
@@ -6938,6 +6977,7 @@
 
     public final ContentProviderHolder getContentProvider(
             IApplicationThread caller, String name) {
+        enforceNotIsolatedCaller("getContentProvider");
         if (caller == null) {
             String msg = "null IApplicationThread when getting content provider "
                     + name;
@@ -6958,6 +6998,7 @@
      * @param cpr
      */
     public void removeContentProvider(IApplicationThread caller, String name) {
+        enforceNotIsolatedCaller("removeContentProvider");
         synchronized (this) {
             int userId = UserId.getUserId(Binder.getCallingUid());
             ContentProviderRecord cpr = mProviderMap.getProviderByName(name, userId);
@@ -7020,6 +7061,7 @@
             return;
         }
 
+        enforceNotIsolatedCaller("publishContentProviders");
         synchronized(this) {
             final ProcessRecord r = getRecordForAppLocked(caller);
             if (DEBUG_MU)
@@ -7107,6 +7149,7 @@
      *     src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
      */
     public String getProviderMimeType(Uri uri) {
+        enforceNotIsolatedCaller("getProviderMimeType");
         final String name = uri.getAuthority();
         final long ident = Binder.clearCallingIdentity();
         ContentProviderHolder holder = null;
@@ -7224,6 +7267,7 @@
     }
 
     public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException {
+        enforceNotIsolatedCaller("openContentUri");
         String name = uri.getAuthority();
         ContentProviderHolder cph = getContentProviderExternal(name);
         ParcelFileDescriptor pfd = null;
@@ -7477,6 +7521,7 @@
     }
     
     public void registerActivityWatcher(IActivityWatcher watcher) {
+        enforceNotIsolatedCaller("registerActivityWatcher");
         synchronized (this) {
             mWatchers.register(watcher);
         }
@@ -7489,6 +7534,7 @@
     }
 
     public void registerProcessObserver(IProcessObserver observer) {
+        enforceNotIsolatedCaller("registerProcessObserver");
         mProcessObservers.register(observer);
     }
 
@@ -7517,6 +7563,7 @@
     }
 
     public boolean isTopActivityImmersive() {
+        enforceNotIsolatedCaller("startActivity");
         synchronized (this) {
             ActivityRecord r = mMainStack.topRunningActivityLocked(null);
             return (r != null) ? r.immersive : false;
@@ -8701,6 +8748,7 @@
     }
 
     public List<ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState() {
+        enforceNotIsolatedCaller("getProcessesInErrorState");
         // assume our apps are happy - lazy create the list
         List<ActivityManager.ProcessErrorStateInfo> errList = null;
 
@@ -8763,6 +8811,7 @@
     }
 
     public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
+        enforceNotIsolatedCaller("getRunningAppProcesses");
         // Lazy instantiation of list
         List<ActivityManager.RunningAppProcessInfo> runList = null;
         synchronized (this) {
@@ -8808,6 +8857,7 @@
     }
 
     public List<ApplicationInfo> getRunningExternalApplications() {
+        enforceNotIsolatedCaller("getRunningExternalApplications");
         List<ActivityManager.RunningAppProcessInfo> runningApps = getRunningAppProcesses();
         List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
         if (runningApps != null && runningApps.size() > 0) {
@@ -11323,6 +11373,7 @@
     
     public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
             int flags) {
+        enforceNotIsolatedCaller("getServices");
         synchronized (this) {
             ArrayList<ActivityManager.RunningServiceInfo> res
                     = new ArrayList<ActivityManager.RunningServiceInfo>();
@@ -11349,6 +11400,7 @@
     }
 
     public PendingIntent getRunningServiceControlPanel(ComponentName name) {
+        enforceNotIsolatedCaller("getRunningServiceControlPanel");
         synchronized (this) {
             int userId = UserId.getUserId(Binder.getCallingUid());
             ServiceRecord r = mServiceMap.getServiceByName(name, userId);
@@ -12076,6 +12128,7 @@
 
     public ComponentName startService(IApplicationThread caller, Intent service,
             String resolvedType) {
+        enforceNotIsolatedCaller("startService");
         // Refuse possible leaked file descriptors
         if (service != null && service.hasFileDescriptors() == true) {
             throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -12118,6 +12171,7 @@
 
     public int stopService(IApplicationThread caller, Intent service,
             String resolvedType) {
+        enforceNotIsolatedCaller("stopService");
         // Refuse possible leaked file descriptors
         if (service != null && service.hasFileDescriptors() == true) {
             throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -12155,6 +12209,7 @@
     }
 
     public IBinder peekService(Intent service, String resolvedType) {
+        enforceNotIsolatedCaller("peekService");
         // Refuse possible leaked file descriptors
         if (service != null && service.hasFileDescriptors() == true) {
             throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -12293,6 +12348,7 @@
     public int bindService(IApplicationThread caller, IBinder token,
             Intent service, String resolvedType,
             IServiceConnection connection, int flags) {
+        enforceNotIsolatedCaller("bindService");
         // Refuse possible leaked file descriptors
         if (service != null && service.hasFileDescriptors() == true) {
             throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -12949,6 +13005,7 @@
 
     public Intent registerReceiver(IApplicationThread caller, String callerPackage,
             IIntentReceiver receiver, IntentFilter filter, String permission) {
+        enforceNotIsolatedCaller("registerReceiver");
         synchronized(this) {
             ProcessRecord callerApp = null;
             if (caller != null) {
@@ -13458,6 +13515,7 @@
             Intent intent, String resolvedType, IIntentReceiver resultTo,
             int resultCode, String resultData, Bundle map,
             String requiredPermission, boolean serialized, boolean sticky, int userId) {
+        enforceNotIsolatedCaller("broadcastIntent");
         synchronized(this) {
             intent = verifyBroadcastLocked(intent);
             
@@ -13704,6 +13762,7 @@
     public boolean startInstrumentation(ComponentName className,
             String profileFile, int flags, Bundle arguments,
             IInstrumentationWatcher watcher) {
+        enforceNotIsolatedCaller("startInstrumentation");
         // Refuse possible leaked file descriptors
         if (arguments != null && arguments.hasFileDescriptors()) {
             throw new IllegalArgumentException("File descriptors passed in Bundle");
@@ -13901,7 +13960,7 @@
      * configuration.
      * @param persistent TODO
      */
-    public boolean updateConfigurationLocked(Configuration values,
+    boolean updateConfigurationLocked(Configuration values,
             ActivityRecord starting, boolean persistent, boolean initLocale) {
         int changes = 0;
         
@@ -15321,7 +15380,7 @@
         synchronized (this) { }
     }
 
-    public void onCoreSettingsChange(Bundle settings) {
+    void onCoreSettingsChange(Bundle settings) {
         for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
             ProcessRecord processRecord = mLruProcesses.get(i);
             try {
diff --git a/tests/BiDiTests/res/layout/grid_layout_code.xml b/tests/BiDiTests/res/layout/grid_layout_code.xml
new file mode 100644
index 0000000..87a0ec0
--- /dev/null
+++ b/tests/BiDiTests/res/layout/grid_layout_code.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/grid_layout_code"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent">
+
+</FrameLayout>
\ No newline at end of file
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
index 4d7ace1..c5a1235 100644
--- a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
@@ -111,6 +111,8 @@
         addItem(result, "Grid LTR", BiDiTestGridLayoutLtr.class, R.id.grid_layout_ltr);
         addItem(result, "Grid RTL", BiDiTestGridLayoutRtl.class, R.id.grid_layout_rtl);
         addItem(result, "Grid LOC", BiDiTestGridLayoutLocale.class, R.id.grid_layout_locale);
+        addItem(result, "Grid C-LTR", BiDiTestGridLayoutCodeLtr.class, R.id.grid_layout_code);
+        addItem(result, "Grid C-RTL", BiDiTestGridLayoutCodeRtl.class, R.id.grid_layout_code);
 
         addItem(result, "Frame LTR", BiDiTestFrameLayoutLtr.class, R.id.frame_layout_ltr);
         addItem(result, "Frame RTL", BiDiTestFrameLayoutRtl.class, R.id.frame_layout_rtl);
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestGridLayoutCodeLtr.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestGridLayoutCodeLtr.java
new file mode 100644
index 0000000..859b8fb
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestGridLayoutCodeLtr.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bidi;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.GridLayout;
+
+import android.widget.*;
+
+import static android.text.InputType.*;
+import static android.widget.GridLayout.*;
+
+public class BiDiTestGridLayoutCodeLtr extends Fragment {
+
+    private FrameLayout currentView;
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        currentView = (FrameLayout) inflater.inflate(R.layout.grid_layout_code, container, false);
+        return currentView;
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        currentView.addView(create(currentView.getContext()));
+    }
+
+    public static View create(Context context) {
+        GridLayout layout = new GridLayout(context);
+        layout.setUseDefaultMargins(true);
+        layout.setAlignmentMode(ALIGN_BOUNDS);
+        layout.setRowOrderPreserved(false);
+        layout.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
+
+        Spec row1 = spec(0);
+        Spec row2 = spec(1);
+        Spec row3 = spec(2, BASELINE);
+        Spec row4 = spec(3, BASELINE);
+        Spec row5 = spec(2, 3, FILL); // allow the last two rows to overlap the middle two
+        Spec row6 = spec(5);
+        Spec row7 = spec(6);
+
+        Spec col1a = spec(0, 4, CENTER);
+        Spec col1b = spec(0, 4, START);
+        Spec col1c = spec(0, END);
+        Spec col2 = spec(1, START);
+        Spec col3 = spec(2, FILL);
+        Spec col4a = spec(3);
+        Spec col4b = spec(3, FILL);
+
+        {
+            TextView c = new TextView(context);
+            c.setTextSize(32);
+            c.setText("Email setup");
+            layout.addView(c, new GridLayout.LayoutParams(row1, col1a));
+        }
+        {
+            TextView c = new TextView(context);
+            c.setTextSize(16);
+            c.setText("You can configure email in just a few steps:");
+            layout.addView(c, new GridLayout.LayoutParams(row2, col1b));
+        }
+        {
+            TextView c = new TextView(context);
+            c.setText("Email address:");
+            layout.addView(c, new GridLayout.LayoutParams(row3, col1c));
+        }
+        {
+            EditText c = new EditText(context);
+            c.setEms(10);
+            c.setInputType(TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
+            layout.addView(c, new GridLayout.LayoutParams(row3, col2));
+        }
+        {
+            TextView c = new TextView(context);
+            c.setText("Password:");
+            layout.addView(c, new GridLayout.LayoutParams(row4, col1c));
+        }
+        {
+            TextView c = new EditText(context);
+            c.setEms(8);
+            c.setInputType(TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_PASSWORD);
+            layout.addView(c, new GridLayout.LayoutParams(row4, col2));
+        }
+        {
+            Space c = new Space(context);
+            layout.addView(c, new GridLayout.LayoutParams(row5, col3));
+        }
+        {
+            Button c = new Button(context);
+            c.setText("Manual setup");
+            layout.addView(c, new GridLayout.LayoutParams(row6, col4a));
+        }
+        {
+            Button c = new Button(context);
+            c.setText("Next");
+            layout.addView(c, new GridLayout.LayoutParams(row7, col4b));
+        }
+
+        return layout;
+    }
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestGridLayoutCodeRtl.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestGridLayoutCodeRtl.java
new file mode 100644
index 0000000..fac8c95
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestGridLayoutCodeRtl.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bidi;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.*;
+
+import static android.text.InputType.*;
+import static android.widget.GridLayout.*;
+
+public class BiDiTestGridLayoutCodeRtl extends Fragment {
+
+    private FrameLayout currentView;
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        currentView = (FrameLayout) inflater.inflate(R.layout.grid_layout_code, container, false);
+        return currentView;
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        currentView.addView(create(currentView.getContext()));
+    }
+
+    public static View create(Context context) {
+        GridLayout layout = new GridLayout(context);
+        layout.setUseDefaultMargins(true);
+        layout.setAlignmentMode(ALIGN_BOUNDS);
+        layout.setRowOrderPreserved(false);
+        layout.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
+
+        Spec row1 = spec(0);
+        Spec row2 = spec(1);
+        Spec row3 = spec(2, BASELINE);
+        Spec row4 = spec(3, BASELINE);
+        Spec row5 = spec(2, 3, FILL); // allow the last two rows to overlap the middle two
+        Spec row6 = spec(5);
+        Spec row7 = spec(6);
+
+        Spec col1a = spec(0, 4, CENTER);
+        Spec col1b = spec(0, 4, START);
+        Spec col1c = spec(0, END);
+        Spec col2 = spec(1, START);
+        Spec col3 = spec(2, FILL);
+        Spec col4a = spec(3);
+        Spec col4b = spec(3, FILL);
+
+        {
+            TextView c = new TextView(context);
+            c.setTextSize(32);
+            c.setText("Email setup");
+            layout.addView(c, new GridLayout.LayoutParams(row1, col1a));
+        }
+        {
+            TextView c = new TextView(context);
+            c.setTextSize(16);
+            c.setText("You can configure email in just a few steps:");
+            layout.addView(c, new GridLayout.LayoutParams(row2, col1b));
+        }
+        {
+            TextView c = new TextView(context);
+            c.setText("Email address:");
+            layout.addView(c, new GridLayout.LayoutParams(row3, col1c));
+        }
+        {
+            EditText c = new EditText(context);
+            c.setEms(10);
+            c.setInputType(TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
+            layout.addView(c, new GridLayout.LayoutParams(row3, col2));
+        }
+        {
+            TextView c = new TextView(context);
+            c.setText("Password:");
+            layout.addView(c, new GridLayout.LayoutParams(row4, col1c));
+        }
+        {
+            TextView c = new EditText(context);
+            c.setEms(8);
+            c.setInputType(TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_PASSWORD);
+            layout.addView(c, new GridLayout.LayoutParams(row4, col2));
+        }
+        {
+            Space c = new Space(context);
+            layout.addView(c, new GridLayout.LayoutParams(row5, col3));
+        }
+        {
+            Button c = new Button(context);
+            c.setText("Manual setup");
+            layout.addView(c, new GridLayout.LayoutParams(row6, col4a));
+        }
+        {
+            Button c = new Button(context);
+            c.setText("Next");
+            layout.addView(c, new GridLayout.LayoutParams(row7, col4b));
+        }
+
+        return layout;
+    }
+}