Merge into jb-mr1-dev

Change-Id: Idf183be6a41ff37add5141a20e96d5190396d1a4
diff --git a/api/current.txt b/api/current.txt
index a3b2434..2cbf02d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -13948,6 +13948,14 @@
     method public byte[] transceive(byte[]) throws java.io.IOException;
   }
 
+  public final class NfcBarcode extends android.nfc.tech.BasicTagTechnology {
+    method public static android.nfc.tech.NfcBarcode get(android.nfc.Tag);
+    method public byte[] getBarcode();
+    method public int getType();
+    field public static final int TYPE_KOVIO = 1; // 0x1
+    field public static final int TYPE_UNKNOWN = -1; // 0xffffffff
+  }
+
   public final class NfcF extends android.nfc.tech.BasicTagTechnology {
     method public static android.nfc.tech.NfcF get(android.nfc.Tag);
     method public byte[] getManufacturer();
@@ -17297,6 +17305,7 @@
     field public static final java.lang.String SYNC_DATA8 = "sync_data8";
     field public static final java.lang.String SYNC_DATA9 = "sync_data9";
     field public static final java.lang.String TITLE = "title";
+    field public static final java.lang.String UID_2445 = "uid2445";
   }
 
   public static final class CalendarContract.EventsEntity implements android.provider.BaseColumns android.provider.CalendarContract.EventsColumns android.provider.CalendarContract.SyncColumns {
@@ -18789,7 +18798,7 @@
     method public static int getInt(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
     method public static long getLong(android.content.ContentResolver, java.lang.String, long);
     method public static long getLong(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
-    method public static synchronized java.lang.String getString(android.content.ContentResolver, java.lang.String);
+    method public static java.lang.String getString(android.content.ContentResolver, java.lang.String);
     method public static android.net.Uri getUriFor(java.lang.String);
     method public static boolean putFloat(android.content.ContentResolver, java.lang.String, float);
     method public static boolean putInt(android.content.ContentResolver, java.lang.String, int);
@@ -18845,7 +18854,7 @@
     method public static int getInt(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
     method public static long getLong(android.content.ContentResolver, java.lang.String, long);
     method public static long getLong(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
-    method public static synchronized java.lang.String getString(android.content.ContentResolver, java.lang.String);
+    method public static java.lang.String getString(android.content.ContentResolver, java.lang.String);
     method public static android.net.Uri getUriFor(java.lang.String);
     method public static final boolean isLocationProviderEnabled(android.content.ContentResolver, java.lang.String);
     method public static boolean putFloat(android.content.ContentResolver, java.lang.String, float);
@@ -18928,7 +18937,7 @@
     method public static long getLong(android.content.ContentResolver, java.lang.String, long);
     method public static long getLong(android.content.ContentResolver, java.lang.String) throws android.provider.Settings.SettingNotFoundException;
     method public static deprecated boolean getShowGTalkServiceStatus(android.content.ContentResolver);
-    method public static synchronized java.lang.String getString(android.content.ContentResolver, java.lang.String);
+    method public static java.lang.String getString(android.content.ContentResolver, java.lang.String);
     method public static android.net.Uri getUriFor(java.lang.String);
     method public static boolean putConfiguration(android.content.ContentResolver, android.content.res.Configuration);
     method public static boolean putFloat(android.content.ContentResolver, java.lang.String, float);
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index c3f57e8..9b08493 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1530,8 +1530,9 @@
             IBinder resultTo = data.readStrongBinder();
             Bundle options = data.readInt() != 0
                     ? Bundle.CREATOR.createFromParcel(data) : null;
+            int userId = data.readInt();
             int result = startActivities(app, intents, resolvedTypes, resultTo,
-                    options);
+                    options, userId);
             reply.writeNoException();
             reply.writeInt(result);
             return true;
@@ -3708,7 +3709,7 @@
     
     public int startActivities(IApplicationThread caller,
             Intent[] intents, String[] resolvedTypes, IBinder resultTo,
-            Bundle options) throws RemoteException {
+            Bundle options, int userId) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
@@ -3722,6 +3723,7 @@
         } else {
             data.writeInt(0);
         }
+        data.writeInt(userId);
         mRemote.transact(START_ACTIVITIES_TRANSACTION, data, reply, 0);
         reply.readException();
         int result = reply.readInt();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index aa8ef21..e613e04 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -65,6 +65,7 @@
 import android.os.ServiceManager;
 import android.os.StrictMode;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
 import android.util.AndroidRuntimeException;
@@ -2114,9 +2115,7 @@
                     + ", dir=" + r.packageInfo.getAppDir());
 
             if (activity != null) {
-                ContextImpl appContext = new ContextImpl();
-                appContext.init(r.packageInfo, r.token, this);
-                appContext.setOuterContext(activity);
+                Context appContext = createBaseContextForActivity(r, activity);
                 CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                 Configuration config = new Configuration(mCompatConfiguration);
                 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
@@ -2181,6 +2180,31 @@
         return activity;
     }
 
+    private Context createBaseContextForActivity(ActivityClientRecord r,
+            final Activity activity) {
+        ContextImpl appContext = new ContextImpl();
+        appContext.init(r.packageInfo, r.token, this);
+        appContext.setOuterContext(activity);
+
+        // For debugging purposes, if the activity's package name contains the value of
+        // the "debug.use-second-display" system property as a substring, then show
+        // its content on a secondary display if there is one.
+        Context baseContext = appContext;
+        String pkgName = SystemProperties.get("debug.second-display.pkg");
+        if (pkgName != null && !pkgName.isEmpty()
+                && r.packageInfo.mPackageName.contains(pkgName)) {
+            DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
+            for (int displayId : dm.getDisplayIds()) {
+                if (displayId != Display.DEFAULT_DISPLAY) {
+                    Display display = dm.getRealDisplay(displayId);
+                    baseContext = appContext.createDisplayContext(display);
+                    break;
+                }
+            }
+        }
+        return baseContext;
+    }
+
     private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
         // If we are getting ready to gc after going to the background, well
         // we are back active so skip it.
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index a6ec9b6..6df0c37 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -965,6 +965,20 @@
         startActivities(intents, null);
     }
 
+    /** @hide */
+    @Override
+    public void startActivitiesAsUser(Intent[] intents, Bundle options, UserHandle userHandle) {
+        if ((intents[0].getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
+            throw new AndroidRuntimeException(
+                    "Calling startActivities() from outside of an Activity "
+                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag on first Intent."
+                    + " Is this really what you want?");
+        }
+        mMainThread.getInstrumentation().execStartActivitiesAsUser(
+            getOuterContext(), mMainThread.getApplicationThread(), null,
+            (Activity)null, intents, options, userHandle.getIdentifier());
+    }
+
     @Override
     public void startActivities(Intent[] intents, Bundle options) {
         if ((intents[0].getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 2b2679e..9454636 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -311,7 +311,7 @@
 
     public int startActivities(IApplicationThread caller,
             Intent[] intents, String[] resolvedTypes, IBinder resultTo,
-            Bundle options) throws RemoteException;
+            Bundle options, int userId) throws RemoteException;
 
     public int getFrontActivityScreenCompatMode() throws RemoteException;
     public void setFrontActivityScreenCompatMode(int mode) throws RemoteException;
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index ee4e964..e0856ae 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1430,6 +1430,21 @@
      */
     public void execStartActivities(Context who, IBinder contextThread,
             IBinder token, Activity target, Intent[] intents, Bundle options) {
+        execStartActivitiesAsUser(who, contextThread, token, target, intents, options,
+                UserHandle.myUserId());
+    }
+
+    /**
+     * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int)},
+     * but accepts an array of activities to be started.  Note that active
+     * {@link ActivityMonitor} objects only match against the first activity in
+     * the array.
+     *
+     * {@hide}
+     */
+    public void execStartActivitiesAsUser(Context who, IBinder contextThread,
+            IBinder token, Activity target, Intent[] intents, Bundle options,
+            int userId) {
         IApplicationThread whoThread = (IApplicationThread) contextThread;
         if (mActivityMonitors != null) {
             synchronized (mSync) {
@@ -1453,7 +1468,8 @@
                 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver());
             }
             int result = ActivityManagerNative.getDefault()
-                .startActivities(whoThread, intents, resolvedTypes, token, options);
+                .startActivities(whoThread, intents, resolvedTypes, token, options,
+                        userId);
             checkStartActivityResult(result, intents[0]);
         } catch (RemoteException e) {
         }
diff --git a/core/java/android/app/TaskStackBuilder.java b/core/java/android/app/TaskStackBuilder.java
index cadf5e4..9d5bcc6 100644
--- a/core/java/android/app/TaskStackBuilder.java
+++ b/core/java/android/app/TaskStackBuilder.java
@@ -23,6 +23,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.Bundle;
+import android.os.UserHandle;
 import android.util.Log;
 
 import java.util.ArrayList;
@@ -128,7 +129,11 @@
         if (parent != null) {
             // We have the actual parent intent, build the rest from static metadata
             // then add the direct parent intent to the end.
-            addParentStack(parent.getComponent());
+            ComponentName target = parent.getComponent();
+            if (target == null) {
+                target = parent.resolveActivity(mSourceContext.getPackageManager());
+            }
+            addParentStack(target);
             addNextIntent(parent);
         }
         return this;
@@ -205,18 +210,26 @@
 
     /**
      * Start the task stack constructed by this builder.
+     * @hide
+     */
+    public void startActivities(Bundle options, UserHandle userHandle) {
+        if (mIntents.isEmpty()) {
+            throw new IllegalStateException(
+                    "No intents added to TaskStackBuilder; cannot startActivities");
+        }
+
+        mSourceContext.startActivitiesAsUser(getIntents(), options, userHandle);
+    }
+
+    /**
+     * Start the task stack constructed by this builder.
      *
      * @param options Additional options for how the Activity should be started.
      * See {@link android.content.Context#startActivity(Intent, Bundle)
      * Context.startActivity(Intent, Bundle)} for more details.
      */
     public void startActivities(Bundle options) {
-        if (mIntents.isEmpty()) {
-            throw new IllegalStateException(
-                    "No intents added to TaskStackBuilder; cannot startActivities");
-        }
-
-        mSourceContext.startActivities(getIntents(), options);
+        startActivities(options, new UserHandle(UserHandle.myUserId()));
     }
 
     /**
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 9162d29..ac36cf7 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -974,6 +974,36 @@
     public abstract void startActivities(Intent[] intents, Bundle options);
 
     /**
+     * @hide
+     * Launch multiple new activities.  This is generally the same as calling
+     * {@link #startActivity(Intent)} for the first Intent in the array,
+     * that activity during its creation calling {@link #startActivity(Intent)}
+     * for the second entry, etc.  Note that unlike that approach, generally
+     * none of the activities except the last in the array will be created
+     * at this point, but rather will be created when the user first visits
+     * them (due to pressing back from the activity on top).
+     *
+     * <p>This method throws {@link ActivityNotFoundException}
+     * if there was no Activity found for <em>any</em> given Intent.  In this
+     * case the state of the activity stack is undefined (some Intents in the
+     * list may be on it, some not), so you probably want to avoid such situations.
+     *
+     * @param intents An array of Intents to be started.
+     * @param options Additional options for how the Activity should be started.
+     * @param userHandle The user for whom to launch the activities
+     * See {@link android.content.Context#startActivity(Intent, Bundle)
+     * Context.startActivity(Intent, Bundle)} for more details.
+     *
+     * @throws ActivityNotFoundException
+     *
+     * @see {@link #startActivities(Intent[])}
+     * @see PackageManager#resolveActivity
+     */
+    public void startActivitiesAsUser(Intent[] intents, Bundle options, UserHandle userHandle) {
+        throw new RuntimeException("Not implemented. Must override in a subclass.");
+    }
+
+    /**
      * Same as {@link #startIntentSender(IntentSender, Intent, int, int, int, Bundle)}
      * with no options specified.
      *
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index d824f1e..84ad667 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -311,6 +311,12 @@
         mBase.startActivities(intents, options);
     }
 
+    /** @hide */
+    @Override
+    public void startActivitiesAsUser(Intent[] intents, Bundle options, UserHandle userHandle) {
+        mBase.startActivitiesAsUser(intents, options, userHandle);
+    }
+
     @Override
     public void startIntentSender(IntentSender intent,
             Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 375d788..1e8671b 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -1161,25 +1161,28 @@
     public native final void setDisplayOrientation(int degrees);
 
     /**
-     * Enable or disable the default shutter sound when taking a picture.
+     * <p>Enable or disable the default shutter sound when taking a picture.</p>
      *
-     * By default, the camera plays the system-defined camera shutter sound when
-     * {@link #takePicture} is called. Using this method, the shutter sound can
-     * be disabled. It is strongly recommended that an alternative shutter sound
-     * is played in the {@link ShutterCallback} when the system shutter sound is
-     * disabled.
+     * <p>By default, the camera plays the system-defined camera shutter sound
+     * when {@link #takePicture} is called. Using this method, the shutter sound
+     * can be disabled. It is strongly recommended that an alternative shutter
+     * sound is played in the {@link ShutterCallback} when the system shutter
+     * sound is disabled.</p>
      *
-     * Note that devices may not always allow control of the camera shutter
-     * sound. If the shutter sound cannot be controlled, this method will return
-     * false.
+     * <p>Note that devices may not always allow disabling the camera shutter
+     * sound. If the shutter sound state cannot be set to the desired value,
+     * this method will return false. {@link CameraInfo#canDisableShutterSound}
+     * can be used to determine whether the device will allow the shutter sound
+     * to be disabled.</p>
      *
      * @param enabled whether the camera should play the system shutter sound
      *                when {@link #takePicture takePicture} is called.
-     * @return true if the shutter sound state was successfully changed. False
-     *         if the shutter sound cannot be controlled; in this case, the
-     *         application should not play its own shutter sound since the
-     *         system shutter sound will play when a picture is taken.
+     * @return {@code true} if the shutter sound state was successfully
+     *         changed. {@code false} if the shutter sound state could not be
+     *         changed. {@code true} is also returned if shutter sound playback
+     *         is already set to the requested state.
      * @see #takePicture
+     * @see CameraInfo#canDisableShutterSound
      * @see ShutterCallback
      */
     public native final boolean enableShutterSound(boolean enabled);
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index f9b765cb..f2cd232 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -24,6 +24,7 @@
 import android.nfc.tech.NdefFormatable;
 import android.nfc.tech.NfcA;
 import android.nfc.tech.NfcB;
+import android.nfc.tech.NfcBarcode;
 import android.nfc.tech.NfcF;
 import android.nfc.tech.NfcV;
 import android.nfc.tech.TagTechnology;
@@ -184,6 +185,9 @@
                 case TagTechnology.NFC_V:
                     strings[i] = NfcV.class.getName();
                     break;
+                case TagTechnology.NFC_BARCODE:
+                    strings[i] = NfcBarcode.class.getName();
+                    break;
                 default:
                     throw new IllegalArgumentException("Unknown tech type " + techList[i]);
             }
diff --git a/core/java/android/nfc/tech/Ndef.java b/core/java/android/nfc/tech/Ndef.java
index a31cb9c..64aa2996 100644
--- a/core/java/android/nfc/tech/Ndef.java
+++ b/core/java/android/nfc/tech/Ndef.java
@@ -140,8 +140,8 @@
      *
      * <p>Does not cause any RF activity and does not block.
      *
-     * @param tag an MIFARE Classic compatible tag
-     * @return MIFARE Classic object
+     * @param tag an NDEF compatible tag
+     * @return Ndef object
      */
     public static Ndef get(Tag tag) {
         if (!tag.hasTech(TagTechnology.NDEF)) return null;
diff --git a/core/java/android/nfc/tech/NfcBarcode.java b/core/java/android/nfc/tech/NfcBarcode.java
new file mode 100644
index 0000000..3149857
--- /dev/null
+++ b/core/java/android/nfc/tech/NfcBarcode.java
@@ -0,0 +1,102 @@
+/*
+ * 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 android.nfc.tech;
+
+import android.nfc.Tag;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+/**
+ * Provides access to tags containing just a barcode.
+ *
+ * <p>Acquire an {@link NfcBarcode} object using {@link #get}.
+ *
+ */
+public final class NfcBarcode extends BasicTagTechnology {
+
+    /** Kovio Tags */
+    public static final int TYPE_KOVIO = 1;
+    public static final int TYPE_UNKNOWN = -1;
+
+    /** @hide */
+    public static final String EXTRA_BARCODE_TYPE = "barcodetype";
+
+    private int mType;
+
+    /**
+     * Get an instance of {@link NfcBarcode} for the given tag.
+     *
+     * <p>Returns null if {@link NfcBarcode} was not enumerated in {@link Tag#getTechList}.
+     *
+     * <p>Does not cause any RF activity and does not block.
+     *
+     * @param tag an NfcBarcode compatible tag
+     * @return NfcBarcode object
+     */
+    public static NfcBarcode get(Tag tag) {
+        if (!tag.hasTech(TagTechnology.NFC_BARCODE)) return null;
+        try {
+            return new NfcBarcode(tag);
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Internal constructor, to be used by NfcAdapter
+     * @hide
+     */
+    public NfcBarcode(Tag tag) throws RemoteException {
+        super(tag, TagTechnology.NFC_BARCODE);
+        Bundle extras = tag.getTechExtras(TagTechnology.NFC_BARCODE);
+        if (extras != null) {
+            mType = extras.getInt(EXTRA_BARCODE_TYPE);
+        } else {
+            throw new NullPointerException("NfcBarcode tech extras are null.");
+        }
+    }
+
+    /**
+     * Returns the NFC Barcode tag type.
+     *
+     * <p>Currently only one of {@link #TYPE_KOVIO} or {@link #TYPE_UNKNOWN}.
+     *
+     * <p>Does not cause any RF activity and does not block.
+     *
+     * @return the NFC Barcode tag type
+     */
+    public int getType() {
+        return mType;
+    }
+
+    /**
+     * Returns the barcode of an NfcBarcode tag.
+     *
+     * <p>Does not cause any RF activity and does not block.
+     *
+     * @return a byte array containing the barcode
+     */
+    public byte[] getBarcode() {
+        switch (mType) {
+            case TYPE_KOVIO:
+                // For Kovio tags the barcode matches the ID
+                return mTag.getId();
+            default:
+                return null;
+        }
+    }
+}
diff --git a/core/java/android/nfc/tech/TagTechnology.java b/core/java/android/nfc/tech/TagTechnology.java
index be5cbd2..3493ea7 100644
--- a/core/java/android/nfc/tech/TagTechnology.java
+++ b/core/java/android/nfc/tech/TagTechnology.java
@@ -148,6 +148,15 @@
     public static final int MIFARE_ULTRALIGHT = 9;
 
     /**
+     * This technology is an instance of {@link NfcBarcode}.
+     * <p>Support for this technology type is optional. If a stack doesn't support this technology
+     * type tags using it must still be discovered and present the lower level radio interface
+     * technologies in use.
+     * @hide
+     */
+    public static final int NFC_BARCODE = 10;
+
+    /**
      * Get the {@link Tag} object backing this {@link TagTechnology} object.
      * @return the {@link Tag} backing this {@link TagTechnology} object.
      */
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 364004b..5c4c036 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -109,8 +109,6 @@
 
                 // /storage/emulated/0
                 mExternalStorage = buildPath(emulatedBase, rawUserId);
-                // /storage/emulated/obb
-                mExternalStorageAndroidObb = buildPath(emulatedBase, "obb");
                 // /data/media/0
                 mMediaStorage = buildPath(mediaBase, rawUserId);
 
@@ -123,12 +121,11 @@
 
                 // /storage/sdcard0
                 mExternalStorage = new File(rawExternalStorage);
-                // /storage/sdcard0/Android/obb
-                mExternalStorageAndroidObb = buildPath(mExternalStorage, DIRECTORY_ANDROID, "obb");
                 // /data/media
                 mMediaStorage = new File(rawMediaStorage);
             }
 
+            mExternalStorageAndroidObb = buildPath(mExternalStorage, DIRECTORY_ANDROID, "obb");
             mExternalStorageAndroidData = buildPath(mExternalStorage, DIRECTORY_ANDROID, "data");
             mExternalStorageAndroidMedia = buildPath(mExternalStorage, DIRECTORY_ANDROID, "media");
         }
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index fd0324b..af6e88e9 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -1245,6 +1245,12 @@
          */
         public static final String CUSTOM_APP_URI = "customAppUri";
 
+        /**
+         * The UID for events added from the RFC 2445 iCalendar format.
+         * Column name.
+         * <P>Type: TEXT</P>
+         */
+        public static final String UID_2445 = "uid2445";
     }
 
     /**
@@ -1382,6 +1388,7 @@
                 DatabaseUtils.cursorIntToContentValuesIfPresent(cursor, cv, GUESTS_CAN_SEE_GUESTS);
                 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, CUSTOM_APP_PACKAGE);
                 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, CUSTOM_APP_URI);
+                DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, UID_2445);
                 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, ORGANIZER);
                 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, IS_ORGANIZER);
                 DatabaseUtils.cursorStringToContentValuesIfPresent(cursor, cv, _SYNC_ID);
@@ -1587,6 +1594,7 @@
      * <li>{@link #GUESTS_CAN_SEE_GUESTS}</li>
      * <li>{@link #CUSTOM_APP_PACKAGE}</li>
      * <li>{@link #CUSTOM_APP_URI}</li>
+     * <li>{@link #UID_2445}</li>
      * </ul>
      * The following Events columns are writable only by a sync adapter
      * <ul>
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f41e12c..9aae1ec 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -764,10 +764,6 @@
             return true;
         }
 
-        public boolean putString(ContentResolver cr, String name, String value) {
-            return putStringForUser(cr, name, value, UserHandle.myUserId());
-        }
-
         public String getStringForUser(ContentResolver cr, String name, final int userHandle) {
             final boolean isSelf = (userHandle == UserHandle.myUserId());
             if (isSelf) {
@@ -855,10 +851,6 @@
                 if (c != null) c.close();
             }
         }
-
-        public String getString(ContentResolver cr, String name) {
-            return getStringForUser(cr, name, UserHandle.myUserId());
-        }
     }
 
     /**
@@ -869,8 +861,17 @@
     public static final class System extends NameValueTable {
         public static final String SYS_PROP_SETTING_VERSION = "sys.settings_system_version";
 
-        // Populated lazily, guarded by class object:
-        private static NameValueCache sNameValueCache = null;
+        /**
+         * The content:// style URL for this table
+         */
+        public static final Uri CONTENT_URI =
+            Uri.parse("content://" + AUTHORITY + "/system");
+
+        private static final NameValueCache sNameValueCache = new NameValueCache(
+                SYS_PROP_SETTING_VERSION,
+                CONTENT_URI,
+                CALL_METHOD_GET_SYSTEM,
+                CALL_METHOD_PUT_SYSTEM);
 
         private static final HashSet<String> MOVED_TO_SECURE;
         static {
@@ -937,28 +938,18 @@
             MOVED_TO_GLOBAL.add(Settings.Global.MODE_RINGER);
         }
 
-        private static void lazyInitCache() {
-            if (sNameValueCache == null) {
-                sNameValueCache = new NameValueCache(
-                        SYS_PROP_SETTING_VERSION + '_' + UserHandle.myUserId(),
-                        CONTENT_URI,
-                        CALL_METHOD_GET_SYSTEM,
-                        CALL_METHOD_PUT_SYSTEM);
-            }
-        }
-
         /**
          * Look up a name in the database.
          * @param resolver to access the database with
          * @param name to look up in the table
          * @return the corresponding value, or null if not present
          */
-        public synchronized static String getString(ContentResolver resolver, String name) {
+        public static String getString(ContentResolver resolver, String name) {
             return getStringForUser(resolver, name, UserHandle.myUserId());
         }
 
         /** @hide */
-        public synchronized static String getStringForUser(ContentResolver resolver, String name,
+        public static String getStringForUser(ContentResolver resolver, String name,
                 int userHandle) {
             if (MOVED_TO_SECURE.contains(name)) {
                 Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
@@ -970,7 +961,6 @@
                         + " to android.provider.Settings.Global, returning read-only value.");
                 return Global.getStringForUser(resolver, name, userHandle);
             }
-            lazyInitCache();
             return sNameValueCache.getStringForUser(resolver, name, userHandle);
         }
 
@@ -998,7 +988,6 @@
                         + " to android.provider.Settings.Global, value is unchanged.");
                 return false;
             }
-            lazyInitCache();
             return sNameValueCache.putStringForUser(resolver, name, value, userHandle);
         }
 
@@ -1368,12 +1357,6 @@
         }
 
         /**
-         * The content:// style URL for this table
-         */
-        public static final Uri CONTENT_URI =
-            Uri.parse("content://" + AUTHORITY + "/system");
-
-        /**
          * @deprecated Use {@link android.provider.Settings.Global#STAY_ON_WHILE_PLUGGED_IN} instead
          */
         @Deprecated
@@ -2549,8 +2532,18 @@
     public static final class Secure extends NameValueTable {
         public static final String SYS_PROP_SETTING_VERSION = "sys.settings_secure_version";
 
+        /**
+         * The content:// style URL for this table
+         */
+        public static final Uri CONTENT_URI =
+            Uri.parse("content://" + AUTHORITY + "/secure");
+
         // Populated lazily, guarded by class object:
-        private static NameValueCache sNameValueCache = null;
+        private static final NameValueCache sNameValueCache = new NameValueCache(
+                SYS_PROP_SETTING_VERSION,
+                CONTENT_URI,
+                CALL_METHOD_GET_SECURE,
+                CALL_METHOD_PUT_SECURE);
 
         private static ILockSettings sLockSettings = null;
 
@@ -2654,28 +2647,18 @@
             MOVED_TO_GLOBAL.add(Settings.Global.WTF_IS_FATAL);
         }
 
-        private static void lazyInitCache() {
-            if (sNameValueCache == null) {
-                sNameValueCache = new NameValueCache(
-                        SYS_PROP_SETTING_VERSION + '_' + UserHandle.myUserId(),
-                        CONTENT_URI,
-                        CALL_METHOD_GET_SECURE,
-                        CALL_METHOD_PUT_SECURE);
-            }
-        }
-
         /**
          * Look up a name in the database.
          * @param resolver to access the database with
          * @param name to look up in the table
          * @return the corresponding value, or null if not present
          */
-        public synchronized static String getString(ContentResolver resolver, String name) {
+        public static String getString(ContentResolver resolver, String name) {
             return getStringForUser(resolver, name, UserHandle.myUserId());
         }
 
         /** @hide */
-        public synchronized static String getStringForUser(ContentResolver resolver, String name,
+        public static String getStringForUser(ContentResolver resolver, String name,
                 int userHandle) {
             if (MOVED_TO_GLOBAL.contains(name)) {
                 Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.Secure"
@@ -2683,21 +2666,23 @@
                 return Global.getStringForUser(resolver, name, userHandle);
             }
 
-            if (sLockSettings == null) {
-                sLockSettings = ILockSettings.Stub.asInterface(
-                        (IBinder) ServiceManager.getService("lock_settings"));
-                sIsSystemProcess = Process.myUid() == Process.SYSTEM_UID;
-            }
-            if (sLockSettings != null && !sIsSystemProcess
-                    && MOVED_TO_LOCK_SETTINGS.contains(name)) {
-                try {
-                    return sLockSettings.getString(name, "0", userHandle);
-                } catch (RemoteException re) {
-                    // Fall through
+            if (MOVED_TO_LOCK_SETTINGS.contains(name)) {
+                synchronized (Secure.class) {
+                    if (sLockSettings == null) {
+                        sLockSettings = ILockSettings.Stub.asInterface(
+                                (IBinder) ServiceManager.getService("lock_settings"));
+                        sIsSystemProcess = Process.myUid() == Process.SYSTEM_UID;
+                    }
+                }
+                if (sLockSettings != null && !sIsSystemProcess) {
+                    try {
+                        return sLockSettings.getString(name, "0", userHandle);
+                    } catch (RemoteException re) {
+                        // Fall through
+                    }
                 }
             }
 
-            lazyInitCache();
             return sNameValueCache.getStringForUser(resolver, name, userHandle);
         }
 
@@ -2720,7 +2705,6 @@
                         + " to android.provider.Settings.Global");
                 return Global.putStringForUser(resolver, name, value, userHandle);
             }
-            lazyInitCache();
             return sNameValueCache.putStringForUser(resolver, name, value, userHandle);
         }
 
@@ -3001,12 +2985,6 @@
         }
 
         /**
-         * The content:// style URL for this table
-         */
-        public static final Uri CONTENT_URI =
-            Uri.parse("content://" + AUTHORITY + "/secure");
-
-        /**
          * @deprecated Use {@link android.provider.Settings.Global#DEVELOPMENT_SETTINGS_ENABLED}
          * instead
          */
@@ -5765,17 +5743,11 @@
 
 
         // Populated lazily, guarded by class object:
-        private static NameValueCache sNameValueCache = null;
-
-        private static void lazyInitCache() {
-            if (sNameValueCache == null) {
-                sNameValueCache = new NameValueCache(
-                        SYS_PROP_SETTING_VERSION,
-                        CONTENT_URI,
-                        CALL_METHOD_GET_GLOBAL,
-                        CALL_METHOD_PUT_GLOBAL);
-            }
-        }
+        private static NameValueCache sNameValueCache = new NameValueCache(
+                    SYS_PROP_SETTING_VERSION,
+                    CONTENT_URI,
+                    CALL_METHOD_GET_GLOBAL,
+                    CALL_METHOD_PUT_GLOBAL);
 
         /**
          * Look up a name in the database.
@@ -5783,14 +5755,13 @@
          * @param name to look up in the table
          * @return the corresponding value, or null if not present
          */
-        public synchronized static String getString(ContentResolver resolver, String name) {
+        public static String getString(ContentResolver resolver, String name) {
             return getStringForUser(resolver, name, UserHandle.myUserId());
         }
 
         /** @hide */
-        public synchronized static String getStringForUser(ContentResolver resolver, String name,
+        public static String getStringForUser(ContentResolver resolver, String name,
                 int userHandle) {
-            lazyInitCache();
             return sNameValueCache.getStringForUser(resolver, name, userHandle);
         }
 
@@ -5809,7 +5780,6 @@
         /** @hide */
         public static boolean putStringForUser(ContentResolver resolver,
                 String name, String value, int userHandle) {
-            lazyInitCache();
             if (LOCAL_LOGV) {
                 Log.v(TAG, "Global.putString(name=" + name + ", value=" + value
                         + " for " + userHandle);
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index bafab21..49f9e9d 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -864,6 +864,12 @@
 
             if (mEglContext == null) {
                 mEglContext = createContext(sEgl, sEglDisplay, sEglConfig);
+                if (mEglContext == null) {
+                    //noinspection ConstantConditions
+                    throw new IllegalStateException("Could not create an EGL context. " +
+                            "eglCreateContext failed with error: " +
+                            GLUtils.getEGLErrorString(sEgl.eglGetError()));
+                }
                 sEglContextStorage.set(createManagedContext(mEglContext));
             }
         }
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 973c7f6..3be63d5 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -456,11 +456,12 @@
                 }
 
                 if (mWindow == null) {
+                    Display display = getDisplay();
                     mWindow = new MyWindow(this);
                     mLayout.type = mWindowType;
                     mLayout.gravity = Gravity.START|Gravity.TOP;
                     mSession.addToDisplayWithoutInputChannel(mWindow, mWindow.mSeq, mLayout,
-                            mVisible ? VISIBLE : GONE, Display.DEFAULT_DISPLAY, mContentInsets);
+                            mVisible ? VISIBLE : GONE, display.getDisplayId(), mContentInsets);
                 }
                 
                 boolean realSizeChanged;
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index b91eb28..a3834ac 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -116,7 +116,9 @@
 
 static OpenGLRenderer* android_view_GLES20Canvas_createRenderer(JNIEnv* env, jobject clazz) {
     RENDERER_LOGD("Create OpenGLRenderer");
-    return new OpenGLRenderer;
+    OpenGLRenderer* renderer = new OpenGLRenderer();
+    renderer->initProperties();
+    return renderer;
 }
 
 static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz,
@@ -734,7 +736,9 @@
 static OpenGLRenderer* android_view_GLES20Canvas_createLayerRenderer(JNIEnv* env,
         jobject clazz, Layer* layer) {
     if (layer) {
-        return new LayerRenderer(layer);
+        OpenGLRenderer* renderer = new LayerRenderer(layer);
+        renderer->initProperties();
+        return renderer;
     }
     return NULL;
 }
diff --git a/data/fonts/DroidSansFallback.ttf b/data/fonts/DroidSansFallback.ttf
index cfbc66a..2b75113 100644
--- a/data/fonts/DroidSansFallback.ttf
+++ b/data/fonts/DroidSansFallback.ttf
Binary files differ
diff --git a/data/fonts/DroidSansFallbackFull.ttf b/data/fonts/DroidSansFallbackFull.ttf
index 0cacabe..a9df005 100644
--- a/data/fonts/DroidSansFallbackFull.ttf
+++ b/data/fonts/DroidSansFallbackFull.ttf
Binary files differ
diff --git a/data/fonts/fallback_fonts.xml b/data/fonts/fallback_fonts.xml
index 2c9a0c8..50ff437 100644
--- a/data/fonts/fallback_fonts.xml
+++ b/data/fonts/fallback_fonts.xml
@@ -93,6 +93,11 @@
     </family>
     <family>
         <fileset>
+            <file>NanumGothic.ttf</file>
+        </fileset>
+    </family>
+    <family>
+        <fileset>
             <file>AndroidEmoji.ttf</file>
         </fileset>
     </family>
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index a4403c8..d0d1d93 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -34,6 +34,7 @@
 #include "OpenGLRenderer.h"
 #include "DisplayListRenderer.h"
 #include "PathRenderer.h"
+#include "Properties.h"
 #include "Vector.h"
 
 namespace android {
@@ -117,6 +118,8 @@
     memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices));
 
     mFirstSnapshot = new Snapshot;
+
+    mScissorOptimizationDisabled = false;
 }
 
 OpenGLRenderer::~OpenGLRenderer() {
@@ -124,16 +127,15 @@
     // GL APIs. All GL state should be kept in Caches.h
 }
 
-///////////////////////////////////////////////////////////////////////////////
-// Debug
-///////////////////////////////////////////////////////////////////////////////
-
-void OpenGLRenderer::startMark(const char* name) const {
-    mCaches.startMark(0, name);
-}
-
-void OpenGLRenderer::endMark() const {
-    mCaches.endMark();
+void OpenGLRenderer::initProperties() {
+    char property[PROPERTY_VALUE_MAX];
+    if (property_get(PROPERTY_DISABLE_SCISSOR_OPTIMIZATION, property, "false")) {
+        mScissorOptimizationDisabled = !strcasecmp(property, "true");
+        INIT_LOGD("  Scissor optimization %s",
+                mScissorOptimizationDisabled ? "disabled" : "enabled");
+    } else {
+        INIT_LOGD("  Scissor optimization enabled");
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -268,40 +270,6 @@
     }
 }
 
-void OpenGLRenderer::debugOverdraw(bool enable, bool clear) {
-    if (mCaches.debugOverdraw && getTargetFbo() == 0) {
-        if (clear) {
-            mCaches.disableScissor();
-            mCaches.stencil.clear();
-        }
-        if (enable) {
-            mCaches.stencil.enableDebugWrite();
-        } else {
-            mCaches.stencil.disable();
-        }
-    }
-}
-
-void OpenGLRenderer::renderOverdraw() {
-    if (mCaches.debugOverdraw && getTargetFbo() == 0) {
-        const Rect* clip = mTilingSnapshot->clipRect;
-
-        mCaches.enableScissor();
-        mCaches.setScissor(clip->left, mTilingSnapshot->height - clip->bottom,
-                clip->right - clip->left, clip->bottom - clip->top);
-
-        mCaches.stencil.enableDebugTest(2);
-        drawColor(0x2f0000ff, SkXfermode::kSrcOver_Mode);
-        mCaches.stencil.enableDebugTest(3);
-        drawColor(0x2f00ff00, SkXfermode::kSrcOver_Mode);
-        mCaches.stencil.enableDebugTest(4);
-        drawColor(0x3fff0000, SkXfermode::kSrcOver_Mode);
-        mCaches.stencil.enableDebugTest(4, true);
-        drawColor(0x7fff0000, SkXfermode::kSrcOver_Mode);
-        mCaches.stencil.disable();
-    }
-}
-
 void OpenGLRenderer::interrupt() {
     if (mCaches.currentProgram) {
         if (mCaches.currentProgram->isInUse()) {
@@ -439,6 +407,52 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+// Debug
+///////////////////////////////////////////////////////////////////////////////
+
+void OpenGLRenderer::startMark(const char* name) const {
+    mCaches.startMark(0, name);
+}
+
+void OpenGLRenderer::endMark() const {
+    mCaches.endMark();
+}
+
+void OpenGLRenderer::debugOverdraw(bool enable, bool clear) {
+    if (mCaches.debugOverdraw && getTargetFbo() == 0) {
+        if (clear) {
+            mCaches.disableScissor();
+            mCaches.stencil.clear();
+        }
+        if (enable) {
+            mCaches.stencil.enableDebugWrite();
+        } else {
+            mCaches.stencil.disable();
+        }
+    }
+}
+
+void OpenGLRenderer::renderOverdraw() {
+    if (mCaches.debugOverdraw && getTargetFbo() == 0) {
+        const Rect* clip = mTilingSnapshot->clipRect;
+
+        mCaches.enableScissor();
+        mCaches.setScissor(clip->left, mTilingSnapshot->height - clip->bottom,
+                clip->right - clip->left, clip->bottom - clip->top);
+
+        mCaches.stencil.enableDebugTest(2);
+        drawColor(0x2f0000ff, SkXfermode::kSrcOver_Mode);
+        mCaches.stencil.enableDebugTest(3);
+        drawColor(0x2f00ff00, SkXfermode::kSrcOver_Mode);
+        mCaches.stencil.enableDebugTest(4);
+        drawColor(0x3fff0000, SkXfermode::kSrcOver_Mode);
+        mCaches.stencil.enableDebugTest(4, true);
+        drawColor(0x7fff0000, SkXfermode::kSrcOver_Mode);
+        mCaches.stencil.disable();
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // Layers
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -1248,7 +1262,7 @@
 
     bool rejected = !clipRect.intersects(r);
     if (!isDeferred() && !rejected) {
-        mCaches.setScissorEnabled(!clipRect.contains(r));
+        mCaches.setScissorEnabled(mScissorOptimizationDisabled || !clipRect.contains(r));
     }
 
     return rejected;
@@ -1384,8 +1398,8 @@
     // When the blending mode is kClear_Mode, we need to use a modulate color
     // argb=1,0,0,0
     accountForClear(mode);
-    chooseBlending(blend || (mColorSet && mColorA < 1.0f) || (mShader && mShader->blend()), mode,
-            mDescription, swapSrcDst);
+    chooseBlending(blend || (mColorSet && mColorA < 1.0f) || (mShader && mShader->blend()) ||
+            (mColorFilter && mColorFilter->blend()), mode, mDescription, swapSrcDst);
 }
 
 void OpenGLRenderer::setupDrawProgram() {
@@ -2711,7 +2725,7 @@
         debugLayerUpdate = mCaches.debugLayersUpdates;
     }
 
-    mCaches.setScissorEnabled(!clip.contains(transformed));
+    mCaches.setScissorEnabled(mScissorOptimizationDisabled || !clip.contains(transformed));
     mCaches.activeTexture(0);
 
     if (CC_LIKELY(!layer->region.isEmpty())) {
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 46e66cb..c29e3fb 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -64,6 +64,12 @@
     virtual ~OpenGLRenderer();
 
     /**
+     * Read externally defined properties to control the behavior
+     * of the renderer.
+     */
+    ANDROID_API void initProperties();
+
+    /**
      * Indicates whether this renderer executes drawing commands immediately.
      * If this method returns true, the drawing commands will be executed
      * later.
@@ -804,6 +810,10 @@
     // Indicate whether we are drawing an opaque frame
     bool mOpaqueFrame;
 
+    // See PROPERTY_DISABLE_SCISSOR_OPTIMIZATION in
+    // Properties.h
+    bool mScissorOptimizationDisabled;
+
     friend class DisplayListRenderer;
 
 }; // class OpenGLRenderer
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index c81319e..7bc2b37 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -347,7 +347,6 @@
         // None
         "",
         // Matrix
-        // TODO: Fix premultiplied alpha computations for color matrix
         "    fragColor *= colorMatrix;\n"
         "    fragColor += colorMatrixVector;\n"
         "    fragColor.rgb *= fragColor.a;\n",
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 31e60e44..1e8765b 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -67,6 +67,21 @@
  */
 #define PROPERTY_DEBUG_OVERDRAW "debug.hwui.show_overdraw"
 
+/**
+ * Used to enable/disable scissor optimization. The accepted values are
+ * "true" and "false". The default value is "false".
+ *
+ * When scissor optimization is enabled, OpenGLRenderer will attempt to
+ * minimize the use of scissor by selectively enabling and disabling the
+ * GL scissor test.
+ * When the optimization is disabled, OpenGLRenderer will keep the GL
+ * scissor test enabled and change the scissor rect as needed.
+ * Some GPUs (for instance the SGX 540) perform better when changing
+ * the scissor rect often than when enabling/disabling the scissor test
+ * often.
+ */
+#define PROPERTY_DISABLE_SCISSOR_OPTIMIZATION "ro.hwui.disable_scissor_opt"
+
 // These properties are defined in mega-bytes
 #define PROPERTY_TEXTURE_CACHE_SIZE "ro.hwui.texture_cache_size"
 #define PROPERTY_LAYER_CACHE_SIZE "ro.hwui.layer_cache_size"
diff --git a/libs/hwui/SkiaColorFilter.cpp b/libs/hwui/SkiaColorFilter.cpp
index b86bbc5..f754388 100644
--- a/libs/hwui/SkiaColorFilter.cpp
+++ b/libs/hwui/SkiaColorFilter.cpp
@@ -34,13 +34,10 @@
 // Color matrix filter
 ///////////////////////////////////////////////////////////////////////////////
 
-SkiaColorMatrixFilter::SkiaColorMatrixFilter(SkColorFilter *skFilter, float* matrix, float* vector):
+SkiaColorMatrixFilter::SkiaColorMatrixFilter(SkColorFilter* skFilter, float* matrix, float* vector):
         SkiaColorFilter(skFilter, kColorMatrix, true), mMatrix(matrix), mVector(vector) {
-    // Skia uses the range [0..255] for the addition vector, but we need
-    // the [0..1] range to apply the vector in GLSL
-    for (int i = 0; i < 4; i++) {
-        mVector[i] /= 255.0f;
-    }
+    // TODO: We should be smarter about this
+    mBlend = true;
 }
 
 SkiaColorMatrixFilter::~SkiaColorMatrixFilter() {
@@ -62,7 +59,7 @@
 // Lighting color filter
 ///////////////////////////////////////////////////////////////////////////////
 
-SkiaLightingFilter::SkiaLightingFilter(SkColorFilter *skFilter, int multiply, int add):
+SkiaLightingFilter::SkiaLightingFilter(SkColorFilter* skFilter, int multiply, int add):
         SkiaColorFilter(skFilter, kLighting, true) {
     mMulR = ((multiply >> 16) & 0xFF) / 255.0f;
     mMulG = ((multiply >>  8) & 0xFF) / 255.0f;
@@ -71,6 +68,9 @@
     mAddR = ((add >> 16) & 0xFF) / 255.0f;
     mAddG = ((add >>  8) & 0xFF) / 255.0f;
     mAddB = ((add      ) & 0xFF) / 255.0f;
+
+    // A lighting filter always ignores alpha
+    mBlend = false;
 }
 
 void SkiaLightingFilter::describe(ProgramDescription& description, const Extensions& extensions) {
@@ -86,13 +86,16 @@
 // Blend color filter
 ///////////////////////////////////////////////////////////////////////////////
 
-SkiaBlendFilter::SkiaBlendFilter(SkColorFilter *skFilter, int color, SkXfermode::Mode mode):
+SkiaBlendFilter::SkiaBlendFilter(SkColorFilter* skFilter, int color, SkXfermode::Mode mode):
         SkiaColorFilter(skFilter, kBlend, true), mMode(mode) {
     const int alpha = (color >> 24) & 0xFF;
     mA = alpha / 255.0f;
     mR = mA * ((color >> 16) & 0xFF) / 255.0f;
     mG = mA * ((color >>  8) & 0xFF) / 255.0f;
     mB = mA * ((color      ) & 0xFF) / 255.0f;
+
+    // TODO: We should do something smarter here
+    mBlend = true;
 }
 
 void SkiaBlendFilter::describe(ProgramDescription& description, const Extensions& extensions) {
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index cee8da8..c366a8d 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -154,6 +154,7 @@
     private static final int MSG_SET_RSX_CONNECTION_STATE = 23; // change remote submix connection
     private static final int MSG_SET_FORCE_RSX_USE = 24;        // force remote submix audio routing
     private static final int MSG_CHECK_MUSIC_ACTIVE = 25;
+    private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 26;
 
     // flags for MSG_PERSIST_VOLUME indicating if current and/or last audible volume should be
     // persisted
@@ -3252,6 +3253,10 @@
                 case MSG_CHECK_MUSIC_ACTIVE:
                     onCheckMusicActive();
                     break;
+
+                case MSG_BROADCAST_AUDIO_BECOMING_NOISY:
+                    onSendBecomingNoisyIntent();
+                    break;
             }
         }
     }
@@ -3308,7 +3313,7 @@
                 address);
     }
 
-    private void sendBecomingNoisyIntent() {
+    private void onSendBecomingNoisyIntent() {
         sendBroadcastToAll(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
     }
 
@@ -3443,8 +3448,14 @@
                 }
             }
             if (devices == device) {
+                sendMsg(mAudioHandler,
+                        MSG_BROADCAST_AUDIO_BECOMING_NOISY,
+                        SENDMSG_REPLACE,
+                        0,
+                        0,
+                        null,
+                        0);
                 delay = 1000;
-                sendBecomingNoisyIntent();
             }
         }
 
@@ -3710,6 +3721,15 @@
             } else if (action.equalsIgnoreCase(Intent.ACTION_CONFIGURATION_CHANGED)) {
                 handleConfigurationChanged(context);
             } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
+                // attempt to stop music playabck for background user
+                sendMsg(mAudioHandler,
+                        MSG_BROADCAST_AUDIO_BECOMING_NOISY,
+                        SENDMSG_REPLACE,
+                        0,
+                        0,
+                        null,
+                        0);
+                // load volume settings for new user
                 readAudioSettings(true /*userSwitch*/);
                 // preserve STREAM_MUSIC volume from one user to the next.
                 sendMsg(mAudioHandler,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index b04475a..6d8b08f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -316,10 +316,10 @@
         String property = null, table = uri.getPathSegments().get(0);
         final boolean isGlobal = table.equals(TABLE_GLOBAL);
         if (table.equals(TABLE_SYSTEM)) {
-            property = Settings.System.SYS_PROP_SETTING_VERSION + '_' + userHandle;
+            property = Settings.System.SYS_PROP_SETTING_VERSION;
             backedUpDataChanged = true;
         } else if (table.equals(TABLE_SECURE)) {
-            property = Settings.Secure.SYS_PROP_SETTING_VERSION + '_' + userHandle;
+            property = Settings.Secure.SYS_PROP_SETTING_VERSION;
             backedUpDataChanged = true;
         } else if (isGlobal) {
             property = Settings.Global.SYS_PROP_SETTING_VERSION;    // this one is global
@@ -448,11 +448,6 @@
             sSystemCaches.delete(userHandle);
             sSecureCaches.delete(userHandle);
             sKnownMutationsInFlight.delete(userHandle);
-
-            String property = Settings.System.SYS_PROP_SETTING_VERSION + '_' + userHandle;
-            SystemProperties.set(property, "");
-            property = Settings.Secure.SYS_PROP_SETTING_VERSION + '_' + userHandle;
-            SystemProperties.set(property, "");
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index dab6306..8cf4445 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -143,7 +143,7 @@
         return mBarService;
     }
 
-    protected boolean isDeviceProvisioned() {
+    public boolean isDeviceProvisioned() {
         return mDeviceProvisioned;
     }
 
@@ -342,7 +342,8 @@
         Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                 Uri.fromParts("package", packageName, null));
         intent.setComponent(intent.resolveActivity(mContext.getPackageManager()));
-        TaskStackBuilder.create(mContext).addNextIntentWithParentStack(intent).startActivities();
+        TaskStackBuilder.create(mContext).addNextIntentWithParentStack(intent).startActivities(
+                null, UserHandle.CURRENT);
     }
 
     protected View.OnLongClickListener getNotificationLongClicker() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index a4a3a6a..57528a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -381,15 +381,6 @@
         mBar = panelBar;
     }
 
-    public void setImeWindowStatus(boolean visible) {
-        // To be implemented by classes extending PanelView
-    }
-
-    public void setup(NetworkController network, BluetoothController bt, BatteryController batt,
-            LocationController location) {
-        // To be implemented by classes extending PanelView
-    }
-
     public void collapse() {
         // TODO: abort animation or ongoing touch
         if (!isFullyCollapsed()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index c55da5d..7e44b16 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -171,7 +171,7 @@
     TextView mNotificationPanelDebugText;
 
     // settings
-    PanelView mSettingsPanel;
+    SettingsPanelView mSettingsPanel;
     int mSettingsPanelGravity;
 
     // top bar
@@ -426,8 +426,9 @@
         }
 
         // Quick Settings (WIP)
-        mSettingsPanel = (PanelView) mStatusBarWindow.findViewById(R.id.settings_panel);
+        mSettingsPanel = (SettingsPanelView) mStatusBarWindow.findViewById(R.id.settings_panel);
         mSettingsPanel.setBar(mStatusBarView);
+        mSettingsPanel.setService(this);
         mSettingsPanel.setup(mNetworkController, mBluetoothController, mBatteryController,
                 mLocationController);
 
@@ -1854,7 +1855,7 @@
         }
 
         // Update the QuickSettings container
-        ((SettingsPanelView) mSettingsPanel).updateResources();
+        mSettingsPanel.updateResources();
 
         loadDimens();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index 37fa524..160cf8f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.phone;
 
+import android.app.ActivityManagerNative;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.PendingIntent;
@@ -36,6 +37,7 @@
 import android.hardware.display.WifiDisplayStatus;
 import android.net.Uri;
 import android.os.Handler;
+import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.provider.ContactsContract;
@@ -75,6 +77,7 @@
 
     private DisplayManager mDisplayManager;
     private WifiDisplayStatus mWifiDisplayStatus;
+    private PhoneStatusBar mStatusBarService;
 
     private BrightnessController mBrightnessController;
     private BluetoothController mBluetoothController;
@@ -129,6 +132,14 @@
         mBar = bar;
     }
 
+    public void setService(PhoneStatusBar phoneStatusBar) {
+        mStatusBarService = phoneStatusBar;
+    }
+
+    public PhoneStatusBar getService() {
+        return mStatusBarService;
+    }
+
     public void setImeWindowStatus(boolean visible) {
         mModel.onImeWindowStatusChanged(visible);
     }
@@ -203,10 +214,21 @@
         Intent intent = new Intent(action);
         startSettingsActivity(intent);
     }
+
     private void startSettingsActivity(Intent intent) {
+        startSettingsActivity(intent, true);
+    }
+
+    private void startSettingsActivity(Intent intent, boolean onlyProvisioned) {
+        if (onlyProvisioned && !getService().isDeviceProvisioned()) return;
+        try {
+            // Dismiss the lock screen when Settings starts.
+            ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
+        } catch (RemoteException e) {
+        }
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
-        mBar.collapseAllPanels(true);
-        mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+        mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+        getService().animateCollapse();
     }
 
     private void addUserTiles(ViewGroup parent, LayoutInflater inflater) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
index 4a7a424..2ed450dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
@@ -58,18 +58,14 @@
         }
     }
 
-    @Override
     public void setImeWindowStatus(boolean visible) {
         if (mQS != null) {
             mQS.setImeWindowStatus(visible);
         }
     }
 
-    @Override
     public void setup(NetworkController networkController, BluetoothController bluetoothController,
             BatteryController batteryController, LocationController locationController) {
-        super.setup(networkController, bluetoothController, batteryController, locationController);
-
         if (mQS != null) {
             mQS.setup(networkController, bluetoothController, batteryController,
                     locationController);
@@ -93,4 +89,10 @@
             "settings,v=" + vel);
         super.fling(vel, always);
     }
+
+    public void setService(PhoneStatusBar phoneStatusBar) {
+        if (mQS != null) {
+            mQS.setService(phoneStatusBar);
+        }
+    }
 }
diff --git a/preloaded-classes b/preloaded-classes
index b505dbd..10c5c9e 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -568,7 +568,6 @@
 android.media.MediaScanner
 android.media.RemoteDisplay
 android.media.ToneGenerator
-android.media.videoeditor.MediaArtistNativeHelper
 android.net.ConnectivityManager
 android.net.Credentials
 android.net.DhcpInfoInternal
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 20c89ad..0e101e1 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -79,7 +79,6 @@
 
 import com.android.internal.R;
 import com.android.internal.content.PackageMonitor;
-import com.android.internal.os.SomeArgs;
 import com.android.internal.statusbar.IStatusBarService;
 
 import org.xmlpull.v1.XmlPullParserException;
@@ -472,13 +471,18 @@
             // If necessary enable accessibility and announce that.
             if (!userState.mIsAccessibilityEnabled) {
                 userState.mIsAccessibilityEnabled = true;
-                scheduleSendStateToClientsLocked(userState);
             }
+            // No touch exploration.
+            userState.mIsTouchExplorationEnabled = false;
+
+            // Hook the automation service up.
+            mUiAutomationService = new Service(mCurrentUserId, componentName,
+                    accessibilityServiceInfo, true);
+            mUiAutomationService.onServiceConnected(componentName, serviceClient.asBinder());
+
+            updateInputFilterLocked(userState);
+            scheduleSendStateToClientsLocked(userState);
         }
-        // Hook the automation service up.
-        mUiAutomationService = new Service(mCurrentUserId, componentName,
-                accessibilityServiceInfo, true);
-        mUiAutomationService.onServiceConnected(componentName, serviceClient.asBinder());
     }
 
     public void unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient) {
@@ -591,16 +595,6 @@
             // Recreate the internal state for the new user.
             mMainHandler.obtainMessage(MainHandler.MSG_SEND_RECREATE_INTERNAL_STATE,
                     mCurrentUserId, 0).sendToTarget();
-
-            // Re-register the test automation service after the new state is recreated.
-            if (mUiAutomationService != null) {
-                unregisterUiTestAutomationService(mUiAutomationService.mServiceInterface);
-                SomeArgs args = SomeArgs.obtain();
-                args.arg1 = mUiAutomationService.mServiceInterface;
-                args.arg2 = mUiAutomationService.mAccessibilityServiceInfo;
-                mMainHandler.obtainMessage(MainHandler.MSG_REGISTER_UI_TEST_AUTOMATION_SERVICE,
-                        args).sendToTarget();
-            }
         }
     }
 
@@ -1166,7 +1160,6 @@
         public static final int MSG_SEND_STATE_TO_CLIENTS = 2;
         public static final int MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER = 3;
         public static final int MSG_SEND_RECREATE_INTERNAL_STATE = 4;
-        public static final int MSG_REGISTER_UI_TEST_AUTOMATION_SERVICE = 5;
 
         public MainHandler(Looper looper) {
             super(looper);
@@ -1202,17 +1195,6 @@
                         recreateInternalStateLocked(userState);
                     }
                 } break;
-                case MSG_REGISTER_UI_TEST_AUTOMATION_SERVICE: {
-                    SomeArgs args = (SomeArgs) msg.obj;
-                    try {
-                        IAccessibilityServiceClient client =
-                                (IAccessibilityServiceClient) args.arg1;
-                        AccessibilityServiceInfo info = (AccessibilityServiceInfo) args.arg2;
-                        registerUiTestAutomationService(client, info);
-                    } finally {
-                        args.recycle();
-                    }
-                } break;
             }
         }
 
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index aefc264..0c0f00c 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -706,7 +706,7 @@
         if (DEBUG_SERVICE) Slog.v(TAG, "retrieveServiceLocked: " + service
                 + " type=" + resolvedType + " callingUid=" + callingUid);
 
-        userId = mAm.handleIncomingUserLocked(callingPid, callingUid, userId,
+        userId = mAm.handleIncomingUser(callingPid, callingUid, userId,
                 false, true, "service", null);
 
         if (service.getComponent() != null) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index a21f6d5..3427699 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -2448,7 +2448,7 @@
             String resultWho, int requestCode, int startFlags,
             String profileFile, ParcelFileDescriptor profileFd, Bundle options, int userId) {
         enforceNotIsolatedCaller("startActivity");
-        userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                 false, true, "startActivity", null);
         return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
                 resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
@@ -2460,7 +2460,7 @@
             String resultWho, int requestCode, int startFlags, String profileFile,
             ParcelFileDescriptor profileFd, Bundle options, int userId) {
         enforceNotIsolatedCaller("startActivityAndWait");
-        userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                 false, true, "startActivityAndWait", null);
         WaitResult res = new WaitResult();
         mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
@@ -2474,7 +2474,7 @@
             String resultWho, int requestCode, int startFlags, Configuration config,
             Bundle options, int userId) {
         enforceNotIsolatedCaller("startActivityWithConfig");
-        userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                 false, true, "startActivityWithConfig", null);
         int ret = mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
                 resultTo, resultWho, requestCode, startFlags,
@@ -2613,7 +2613,7 @@
             Intent intent, String resolvedType, IBinder resultTo,
             String resultWho, int requestCode, int startFlags, Bundle options, int userId) {
 
-        userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                 false, true, "startActivityInPackage", null);
 
         int ret = mMainStack.startActivityMayWait(null, uid, intent, resolvedType,
@@ -2623,10 +2623,13 @@
     }
 
     public final int startActivities(IApplicationThread caller,
-            Intent[] intents, String[] resolvedTypes, IBinder resultTo, Bundle options) {
+            Intent[] intents, String[] resolvedTypes, IBinder resultTo, Bundle options,
+            int userId) {
         enforceNotIsolatedCaller("startActivities");
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+                false, true, "startActivity", null);
         int ret = mMainStack.startActivities(caller, -1, intents, resolvedTypes, resultTo,
-                options, UserHandle.getCallingUserId());
+                options, userId);
         return ret;
     }
 
@@ -2634,7 +2637,7 @@
             Intent[] intents, String[] resolvedTypes, IBinder resultTo,
             Bundle options, int userId) {
 
-        userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                 false, true, "startActivityInPackage", null);
         int ret = mMainStack.startActivities(null, uid, intents, resolvedTypes, resultTo,
                 options, userId);
@@ -3460,7 +3463,7 @@
         enforceNotIsolatedCaller("clearApplicationUserData");
         int uid = Binder.getCallingUid();
         int pid = Binder.getCallingPid();
-        userId = handleIncomingUserLocked(pid, uid,
+        userId = handleIncomingUser(pid, uid,
                 userId, false, true, "clearApplicationUserData", null);
         long callingId = Binder.clearCallingIdentity();
         try {
@@ -3516,7 +3519,7 @@
             throw new SecurityException(msg);
         }
 
-        userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(),
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                 userId, true, true, "killBackgroundProcesses", null);
         long callingId = Binder.clearCallingIdentity();
         try {
@@ -3591,7 +3594,7 @@
             Slog.w(TAG, msg);
             throw new SecurityException(msg);
         }
-        userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(),
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                 userId, true, true, "forceStopPackage", null);
         long callingId = Binder.clearCallingIdentity();
         try {
@@ -4596,7 +4599,7 @@
         synchronized(this) {
             int callingUid = Binder.getCallingUid();
             int origUserId = userId;
-            userId = handleIncomingUserLocked(Binder.getCallingPid(), callingUid, userId,
+            userId = handleIncomingUser(Binder.getCallingPid(), callingUid, userId,
                     type == ActivityManager.INTENT_SENDER_BROADCAST, true,
                     "getIntentSender", null);
             if (origUserId == UserHandle.USER_CURRENT) {
@@ -5756,26 +5759,8 @@
 
     public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
             int flags, int userId) {
-        final int callingUid = Binder.getCallingUid();
-        if (userId != UserHandle.getCallingUserId()) {
-            // Check if the caller is holding permissions for cross-user requests.
-            if (checkComponentPermission(
-                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
-                    Binder.getCallingPid(), callingUid, -1, true)
-                    != PackageManager.PERMISSION_GRANTED) {
-                String msg = "Permission Denial: "
-                        + "Request to get recent tasks for user " + userId
-                        + " but is calling from user " + UserHandle.getUserId(callingUid)
-                        + "; this requires "
-                        + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
-                Slog.w(TAG, msg);
-                throw new SecurityException(msg);
-            } else {
-                if (userId == UserHandle.USER_CURRENT) {
-                    userId = mCurrentUserId;
-                }
-            }
-        }
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+                false, true, "getRecentTasks", null);
 
         synchronized (this) {
             enforceCallingPermission(android.Manifest.permission.GET_TASKS,
@@ -6679,7 +6664,7 @@
             throw new SecurityException(msg);
         }
 
-        userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                 false, true, "getContentProvider", null);
         return getContentProviderImpl(caller, name, null, stable, userId);
     }
@@ -6688,7 +6673,7 @@
             String name, int userId, IBinder token) {
         enforceCallingPermission(android.Manifest.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY,
             "Do not have permission in call getContentProviderExternal()");
-        userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                 false, true, "getContentProvider", null);
         return getContentProviderExternalUnchecked(name, token, userId);
     }
@@ -6953,7 +6938,7 @@
      */
     public String getProviderMimeType(Uri uri, int userId) {
         enforceNotIsolatedCaller("getProviderMimeType");
-        userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(),
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                 userId, false, true, "getProviderMimeType", null);
         final String name = uri.getAuthority();
         final long ident = Binder.clearCallingIdentity();
@@ -10926,14 +10911,6 @@
 
     public int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
             boolean requireFull, String name, String callerPackage) {
-        synchronized(this) {
-            return handleIncomingUserLocked(callingPid, callingUid, userId, allowAll,
-                    requireFull, name, callerPackage);
-        }        
-    }
-
-    int handleIncomingUserLocked(int callingPid, int callingUid, int userId, boolean allowAll,
-            boolean requireFull, String name, String callerPackage) {
         final int callingUserId = UserHandle.getUserId(callingUid);
         if (callingUserId != userId) {
             if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
@@ -10974,6 +10951,10 @@
             }
             if (userId == UserHandle.USER_CURRENT
                     || userId == UserHandle.USER_CURRENT_OR_SELF) {
+                // Note that we may be accessing this outside of a lock...
+                // shouldn't be a big deal, if this is being called outside
+                // of a locked context there is intrinsically a race with
+                // the value the caller will receive and someone else changing it.
                 userId = mCurrentUserId;
             }
             if (!allowAll && userId < 0) {
@@ -11280,7 +11261,7 @@
                 callingPid = Binder.getCallingPid();
             }
 
-            userId = this.handleIncomingUserLocked(callingPid, callingUid, userId,
+            userId = this.handleIncomingUser(callingPid, callingUid, userId,
                     true, true, "registerReceiver", callerPackage);
 
             List allSticky = null;
@@ -11515,7 +11496,7 @@
             Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
         }
 
-        userId = handleIncomingUserLocked(callingPid, callingUid, userId,
+        userId = handleIncomingUser(callingPid, callingUid, userId,
                 true, false, "broadcast", callerPackage);
 
         // Make sure that the user who is receiving this broadcast is started.
@@ -11928,7 +11909,7 @@
             throw new IllegalArgumentException("File descriptors passed in Intent");
         }
 
-        userId = handleIncomingUserLocked(Binder.getCallingPid(),
+        userId = handleIncomingUser(Binder.getCallingPid(),
                 Binder.getCallingUid(), userId, true, false, "removeStickyBroadcast", null);
 
         synchronized(this) {
@@ -12016,7 +11997,7 @@
             String profileFile, int flags, Bundle arguments,
             IInstrumentationWatcher watcher, int userId) {
         enforceNotIsolatedCaller("startInstrumentation");
-        userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(),
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                 userId, false, true, "startInstrumentation", null);
         // Refuse possible leaked file descriptors
         if (arguments != null && arguments.hasFileDescriptors()) {
@@ -12434,7 +12415,7 @@
                 } else {
                     try {
                         ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
-                                destIntent.getComponent(), 0, UserHandle.getCallingUserId());
+                                destIntent.getComponent(), 0, srec.userId);
                         int res = mMainStack.startActivityLocked(srec.app.thread, destIntent,
                                 null, aInfo, parent.appToken, null,
                                 0, -1, parent.launchedFromUid, 0, null, true, null);
@@ -13862,7 +13843,7 @@
     }
 
     private ProcessRecord findProcessLocked(String process, int userId, String callName) {
-        userId = handleIncomingUserLocked(Binder.getCallingPid(), Binder.getCallingUid(),
+        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                 userId, true, true, callName, null);
         ProcessRecord proc = null;
         try {
diff --git a/services/java/com/android/server/wm/Session.java b/services/java/com/android/server/wm/Session.java
index 16beeab..d84a52b 100644
--- a/services/java/com/android/server/wm/Session.java
+++ b/services/java/com/android/server/wm/Session.java
@@ -280,7 +280,8 @@
             // !!! FIXME: put all this heavy stuff onto the mH looper, as well as
             // the actual drag event dispatch stuff in the dragstate
 
-            mService.mDragState.register(callingWin.mDisplayContent.getDisplay());
+            Display display = callingWin.mDisplayContent.getDisplay();
+            mService.mDragState.register(display);
             mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
             if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel,
                     mService.mDragState.mServerChannel)) {
@@ -310,6 +311,7 @@
                         touchY - thumbCenterY);
                 surface.setAlpha(.7071f);
                 surface.setLayer(mService.mDragState.getDragLayerLw());
+                surface.setLayerStack(display.getLayerStack());
                 surface.show();
             } finally {
                 Surface.closeTransaction();
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 5a6e010..c09c261 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -9777,7 +9777,7 @@
                 if (moveInputMethodWindowsIfNeededLocked(
                         mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS &&
                         mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
-                    getDefaultDisplayContentLocked().layoutNeeded = true;
+                    displayContent.layoutNeeded = true;
                 }
                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
                     performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
@@ -9791,7 +9791,7 @@
 
             if ((focusChanged & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
                 // The change in focus caused us to need to do a layout.  Okay.
-                getDefaultDisplayContentLocked().layoutNeeded = true;
+                displayContent.layoutNeeded = true;
                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
                     performLayoutLockedInner(displayContent, true /*initial*/, updateInputWindows);
                 }
@@ -9814,22 +9814,29 @@
     }
 
     private WindowState computeFocusedWindowLocked() {
-        WindowState result = null;
-        WindowState win;
-
         if (mAnimator.mUniverseBackground != null
                 && mAnimator.mUniverseBackground.mWin.canReceiveKeys()) {
             return mAnimator.mUniverseBackground.mWin;
         }
 
-        int nextAppIndex = mAppTokens.size()-1;
-        WindowToken nextApp = nextAppIndex >= 0
-            ? mAppTokens.get(nextAppIndex) : null;
+        final int displayCount = mDisplayContents.size();
+        for (int i = 0; i < displayCount; i++) {
+            final DisplayContent displayContent = mDisplayContents.valueAt(i);
+            WindowState win = findFocusedWindowLocked(displayContent);
+            if (win != null) {
+                return win;
+            }
+        }
+        return null;
+    }
 
-        // TODO(multidisplay): IMEs are only supported on the default display.
-        WindowList windows = getDefaultWindowListLocked();
+    private WindowState findFocusedWindowLocked(DisplayContent displayContent) {
+        int nextAppIndex = mAppTokens.size()-1;
+        WindowToken nextApp = nextAppIndex >= 0 ? mAppTokens.get(nextAppIndex) : null;
+
+        final WindowList windows = displayContent.getWindowList();
         for (int i = windows.size() - 1; i >= 0; i--) {
-            win = windows.get(i);
+            final WindowState win = windows.get(i);
 
             if (localLOGV || DEBUG_FOCUS) Slog.v(
                 TAG, "Looking for focus: " + i
@@ -9879,12 +9886,10 @@
             if (win.canReceiveKeys()) {
                 if (DEBUG_FOCUS) Slog.v(
                         TAG, "Found focus @ " + i + " = " + win);
-                result = win;
-                break;
+                return win;
             }
         }
-
-        return result;
+        return null;
     }
 
     private void startFreezingDisplayLocked(boolean inTransaction,
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index 5f40709..b71e38e 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -1056,7 +1056,10 @@
             w.mSystemDecorRect.set(0, 0, w.mRequestedWidth, w.mRequestedHeight);
         } else if (!w.isDefaultDisplay()) {
             // On a different display is easy, just use the entire display.
-            w.mSystemDecorRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
+            w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
+            w.mSystemDecorRect.intersect(-w.mFrame.left, -w.mFrame.top,
+                    displayInfo.logicalWidth - w.mFrame.left,
+                    displayInfo.logicalHeight - w.mFrame.top);
         } else if (w.mLayer >= mService.mSystemDecorLayer) {
             // Above the decor layer is easy, just use the entire window.
             // Unless we have a universe background...  in which case all the
diff --git a/tests/RenderScriptTests/ImageProcessing/res/drawable-nodpi/img1600x1067b.jpg b/tests/RenderScriptTests/ImageProcessing/res/drawable-nodpi/img1600x1067b.jpg
new file mode 100644
index 0000000..aed0781
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/res/drawable-nodpi/img1600x1067b.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/ImageProcessing/res/drawable-nodpi/img640x427.jpg b/tests/RenderScriptTests/ImageProcessing/res/drawable-nodpi/img640x427.jpg
deleted file mode 100644
index 5bce392..0000000
--- a/tests/RenderScriptTests/ImageProcessing/res/drawable-nodpi/img640x427.jpg
+++ /dev/null
Binary files differ
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve3x3.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve3x3.rs
index 455fcc2..98128279 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve3x3.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve3x3.rs
@@ -30,15 +30,15 @@
     uint32_t y1 = min((int32_t)y+1, gHeight-1);
     uint32_t y2 = max((int32_t)y-1, 0);
 
-    float4 p00 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x1, y1))[0]);
-    float4 p01 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x, y1))[0]);
-    float4 p02 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x2, y1))[0]);
-    float4 p10 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x1, y))[0]);
-    float4 p11 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x, y))[0]);
-    float4 p12 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x2, y))[0]);
-    float4 p20 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x1, y2))[0]);
-    float4 p21 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x, y2))[0]);
-    float4 p22 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x2, y2))[0]);
+    float4 p00 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y1));
+    float4 p01 = convert_float4(rsGetElementAt_uchar4(gIn, x, y1));
+    float4 p02 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y1));
+    float4 p10 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y));
+    float4 p11 = convert_float4(rsGetElementAt_uchar4(gIn, x, y));
+    float4 p12 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y));
+    float4 p20 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y2));
+    float4 p21 = convert_float4(rsGetElementAt_uchar4(gIn, x, y2));
+    float4 p22 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y2));
     p00 *= gCoeffs[0];
     p01 *= gCoeffs[1];
     p02 *= gCoeffs[2];
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve5x5.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve5x5.rs
index fe6cf31..e6d03c9 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve5x5.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve5x5.rs
@@ -37,35 +37,35 @@
     uint32_t y3 = min((int32_t)y+1, gHeight-1);
     uint32_t y4 = min((int32_t)y+2, gHeight-1);
 
-    float4 p0 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x0, y0))[0]) * gCoeffs[0]
-              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x1, y0))[0]) * gCoeffs[1]
-              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x2, y0))[0]) * gCoeffs[2]
-              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x3, y0))[0]) * gCoeffs[3]
-              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x4, y0))[0]) * gCoeffs[4];
+    float4 p0 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y0)) * gCoeffs[0]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y0)) * gCoeffs[1]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y0)) * gCoeffs[2]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y0)) * gCoeffs[3]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y0)) * gCoeffs[4];
 
-    float4 p1 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x0, y1))[0]) * gCoeffs[5]
-              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x1, y1))[0]) * gCoeffs[6]
-              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x2, y1))[0]) * gCoeffs[7]
-              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x3, y1))[0]) * gCoeffs[8]
-              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x4, y1))[0]) * gCoeffs[9];
+    float4 p1 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y1)) * gCoeffs[5]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y1)) * gCoeffs[6]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y1)) * gCoeffs[7]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y1)) * gCoeffs[8]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y1)) * gCoeffs[9];
 
-    float4 p2 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x0, y2))[0]) * gCoeffs[10]
-              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x1, y2))[0]) * gCoeffs[11]
-              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x2, y2))[0]) * gCoeffs[12]
-              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x3, y2))[0]) * gCoeffs[13]
-              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x4, y2))[0]) * gCoeffs[14];
+    float4 p2 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y2)) * gCoeffs[10]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y2)) * gCoeffs[11]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y2)) * gCoeffs[12]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y2)) * gCoeffs[13]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y2)) * gCoeffs[14];
 
-    float4 p3 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x0, y3))[0]) * gCoeffs[15]
-              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x1, y3))[0]) * gCoeffs[16]
-              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x2, y3))[0]) * gCoeffs[17]
-              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x3, y3))[0]) * gCoeffs[18]
-              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x4, y3))[0]) * gCoeffs[19];
+    float4 p3 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y3)) * gCoeffs[15]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y3)) * gCoeffs[16]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y3)) * gCoeffs[17]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y3)) * gCoeffs[18]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y3)) * gCoeffs[19];
 
-    float4 p4 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x0, y4))[0]) * gCoeffs[20]
-              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x1, y4))[0]) * gCoeffs[21]
-              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x2, y4))[0]) * gCoeffs[22]
-              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x3, y4))[0]) * gCoeffs[23]
-              + convert_float4(((uchar4 *)rsGetElementAt(gIn, x4, y4))[0]) * gCoeffs[24];
+    float4 p4 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y4)) * gCoeffs[20]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x1, y4)) * gCoeffs[21]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x2, y4)) * gCoeffs[22]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x3, y4)) * gCoeffs[23]
+              + convert_float4(rsGetElementAt_uchar4(gIn, x4, y4)) * gCoeffs[24];
 
     p0 = clamp(p0 + p1 + p2 + p3 + p4, 0.f, 255.f);
     *out = convert_uchar4(p0);
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.rs
index 783bc4a..ea42524 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.rs
@@ -48,15 +48,15 @@
     uint32_t y1 = min((int32_t)y+1, (int32_t)(gHeight -1));
     uint32_t y2 = max((int32_t)y-1, (int32_t)0);
 
-    uint p00 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x1, y1))[0];
-    uint p01 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x, y1))[0];
-    uint p02 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x2, y1))[0];
-    uint p10 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x1, y))[0];
-    uint p11 = 230 * ((uchar *)rsGetElementAt(gBlendSource, x, y))[0];
-    uint p12 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x2, y))[0];
-    uint p20 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x1, y2))[0];
-    uint p21 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x, y2))[0];
-    uint p22 = 56 *  ((uchar *)rsGetElementAt(gBlendSource, x2, y2))[0];
+    uint p00 = 56 *  rsGetElementAt_uchar(gBlendSource, x1, y1);
+    uint p01 = 114 * rsGetElementAt_uchar(gBlendSource, x, y1);
+    uint p02 = 56 *  rsGetElementAt_uchar(gBlendSource, x2, y1);
+    uint p10 = 114 * rsGetElementAt_uchar(gBlendSource, x1, y);
+    uint p11 = 230 * rsGetElementAt_uchar(gBlendSource, x, y);
+    uint p12 = 114 * rsGetElementAt_uchar(gBlendSource, x2, y);
+    uint p20 = 56 *  rsGetElementAt_uchar(gBlendSource, x1, y2);
+    uint p21 = 114 * rsGetElementAt_uchar(gBlendSource, x, y2);
+    uint p22 = 56 *  rsGetElementAt_uchar(gBlendSource, x2, y2);
 
     p00 += p01;
     p02 += p10;
@@ -78,7 +78,7 @@
 rs_allocation gNoise;
 void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
     float4 ip = convert_float4(*in);
-    float pnoise = (float) ((uchar *)rsGetElementAt(gNoise, x, y))[0];
+    float pnoise = (float) rsGetElementAt_uchar(gNoise, x, y);
 
     float energy_level = ip.r + ip.g + ip.b;
     float energy_mask = (28.f - sqrt(energy_level)) * 0.03571f;
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
index 2a06491..83fadcb 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
@@ -76,6 +76,7 @@
         unitTests.add(new UT_clamp_relaxed(this, mRes, mCtx));
         unitTests.add(new UT_convert(this, mRes, mCtx));
         unitTests.add(new UT_convert_relaxed(this, mRes, mCtx));
+        unitTests.add(new UT_copy_test(this, mRes, mCtx));
         unitTests.add(new UT_rsdebug(this, mRes, mCtx));
         unitTests.add(new UT_rstime(this, mRes, mCtx));
         unitTests.add(new UT_rstypes(this, mRes, mCtx));
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_copy_test.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_copy_test.java
new file mode 100644
index 0000000..380f6ec
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_copy_test.java
@@ -0,0 +1,120 @@
+/*
+ * 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.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+
+public class UT_copy_test extends UnitTest {
+    private Resources mRes;
+    boolean pass = true;
+
+    protected UT_copy_test(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Copy", ctx);
+        mRes = res;
+    }
+
+    void testFloat2(RenderScript rs, ScriptC_copy_test s) {
+        Allocation a1 = Allocation.createSized(rs, Element.F32_2(rs), 1024);
+        Allocation a2 = Allocation.createSized(rs, Element.F32_2(rs), 1024);
+
+        float[] f1 = new float[1024 * 2];
+        float[] f2 = new float[1024 * 2];
+        for (int ct=0; ct < f1.length; ct++) {
+            f1[ct] = (float)ct;
+        }
+        a1.copyFrom(f1);
+
+        s.forEach_copyFloat2(a1, a2);
+
+        a2.copyTo(f2);
+        for (int ct=0; ct < f1.length; ct++) {
+            if (f1[ct] != f2[ct]) {
+                failTest();
+                Log.v("RS Test", "Compare failed at " + ct + ", " + f1[ct] + ", " + f2[ct]);
+            }
+        }
+        a1.destroy();
+        a2.destroy();
+    }
+
+    void testFloat3(RenderScript rs, ScriptC_copy_test s) {
+        Allocation a1 = Allocation.createSized(rs, Element.F32_3(rs), 1024);
+        Allocation a2 = Allocation.createSized(rs, Element.F32_3(rs), 1024);
+
+        float[] f1 = new float[1024 * 4];
+        float[] f2 = new float[1024 * 4];
+        for (int ct=0; ct < f1.length; ct++) {
+            f1[ct] = (float)ct;
+        }
+        a1.copyFrom(f1);
+
+        s.forEach_copyFloat3(a1, a2);
+
+        a2.copyTo(f2);
+        for (int ct=0; ct < f1.length; ct++) {
+            if ((f1[ct] != f2[ct]) && ((ct&3) != 3)) {
+                failTest();
+                Log.v("RS Test", "Compare failed at " + ct + ", " + f1[ct] + ", " + f2[ct]);
+            }
+        }
+        a1.destroy();
+        a2.destroy();
+    }
+
+    void testFloat4(RenderScript rs, ScriptC_copy_test s) {
+        Allocation a1 = Allocation.createSized(rs, Element.F32_4(rs), 1024);
+        Allocation a2 = Allocation.createSized(rs, Element.F32_4(rs), 1024);
+
+        float[] f1 = new float[1024 * 4];
+        float[] f2 = new float[1024 * 4];
+        for (int ct=0; ct < f1.length; ct++) {
+            f1[ct] = (float)ct;
+        }
+        a1.copyFrom(f1);
+
+        s.forEach_copyFloat4(a1, a2);
+
+        a2.copyTo(f2);
+        for (int ct=0; ct < f1.length; ct++) {
+            if (f1[ct] != f2[ct]) {
+                failTest();
+                Log.v("RS Test", "Compare failed at " + ct + ", " + f1[ct] + ", " + f2[ct]);
+            }
+        }
+        a1.destroy();
+        a2.destroy();
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_copy_test s = new ScriptC_copy_test(pRS);
+        pRS.setMessageHandler(mRsMessage);
+
+        testFloat2(pRS, s);
+        testFloat3(pRS, s);
+        testFloat4(pRS, s);
+        s.invoke_sendResult(true);
+
+        pRS.finish();
+        waitForMessage();
+        pRS.destroy();
+    }
+}
+
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/copy_test.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/copy_test.rs
new file mode 100644
index 0000000..f4243eb
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/copy_test.rs
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#include "shared.rsh"
+
+void sendResult(bool pass) {
+    if (pass) {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+}
+
+
+float2 __attribute((kernel)) copyFloat2(float2 i) {
+    return i;
+}
+
+float3 __attribute((kernel)) copyFloat3(float3 i) {
+    return i;
+}
+
+float4 __attribute((kernel)) copyFloat4(float4 i) {
+    return i;
+}
+
+
diff --git a/tools/aidl/aidl.cpp b/tools/aidl/aidl.cpp
index 8dbbf50..0728246 100644
--- a/tools/aidl/aidl.cpp
+++ b/tools/aidl/aidl.cpp
@@ -590,7 +590,8 @@
     }
 
     const document_item_type* next = items->next;
-    if (items->next != NULL) {
+    // Allow parcelables to skip the "one-only" rule.
+    if (items->next != NULL && next->item_type != USER_DATA_TYPE) {
         int lineno = -1;
         if (next->item_type == INTERFACE_TYPE_BINDER) {
             lineno = ((interface_type*)next)->interface_token.lineno;
@@ -598,9 +599,6 @@
         else if (next->item_type == INTERFACE_TYPE_RPC) {
             lineno = ((interface_type*)next)->interface_token.lineno;
         }
-        else if (next->item_type == USER_DATA_TYPE) {
-            lineno = ((user_data_type*)next)->keyword_token.lineno;
-        }
         fprintf(stderr, "%s:%d aidl can only handle one interface per file\n",
                             filename, lineno);
         return 1;