Merge "Fix for SettingsProvider to query for correct user."
diff --git a/api/current.txt b/api/current.txt
index d1363db..0569b9d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -26305,12 +26305,15 @@
     method public java.lang.CharSequence getPackageName();
     method public android.view.accessibility.AccessibilityNodeInfo getParent();
     method public java.lang.CharSequence getText();
+    method public int getTextSelectionEnd();
+    method public int getTextSelectionStart();
     method public java.lang.CharSequence getViewIdResourceName();
     method public int getWindowId();
     method public boolean isAccessibilityFocused();
     method public boolean isCheckable();
     method public boolean isChecked();
     method public boolean isClickable();
+    method public boolean isEditable();
     method public boolean isEnabled();
     method public boolean isFocusable();
     method public boolean isFocused();
@@ -26335,6 +26338,7 @@
     method public void setClassName(java.lang.CharSequence);
     method public void setClickable(boolean);
     method public void setContentDescription(java.lang.CharSequence);
+    method public void setEditable(boolean);
     method public void setEnabled(boolean);
     method public void setFocusable(boolean);
     method public void setFocused(boolean);
@@ -26353,6 +26357,7 @@
     method public void setSource(android.view.View);
     method public void setSource(android.view.View, int);
     method public void setText(java.lang.CharSequence);
+    method public void setTextSelection(int, int);
     method public void setViewIdResourceName(java.lang.CharSequence);
     method public void setVisibleToUser(boolean);
     method public void writeToParcel(android.os.Parcel, int);
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 2a59a1d..b92b9ce 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -61,8 +61,9 @@
     public static final int OP_SEND_SMS = 20;
     public static final int OP_READ_ICC_SMS = 21;
     public static final int OP_WRITE_ICC_SMS = 22;
+    public static final int OP_WRITE_SETTINGS = 23;
     /** @hide */
-    public static final int _NUM_OP = 23;
+    public static final int _NUM_OP = 24;
 
     /**
      * This maps each operation to the operation that serves as the
@@ -96,6 +97,7 @@
             OP_WRITE_SMS,
             OP_READ_SMS,
             OP_WRITE_SMS,
+            OP_WRITE_SETTINGS,
     };
 
     /**
@@ -126,6 +128,7 @@
             "SEND_SMS",
             "READ_ICC_SMS",
             "WRITE_ICC_SMS",
+            "WRITE_SETTINGS",
     };
 
     /**
@@ -156,6 +159,7 @@
             android.Manifest.permission.SEND_SMS,
             android.Manifest.permission.READ_SMS,
             android.Manifest.permission.WRITE_SMS,
+            android.Manifest.permission.WRITE_SETTINGS,
     };
 
     public static int opToSwitch(int op) {
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index e66efd5..90ee0ac 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -174,8 +174,8 @@
      */
     class Transport extends ContentProviderNative {
         AppOpsManager mAppOpsManager = null;
-        int mReadOp = -1;
-        int mWriteOp = -1;
+        int mReadOp = AppOpsManager.OP_NONE;
+        int mWriteOp = AppOpsManager.OP_NONE;
 
         ContentProvider getContentProvider() {
             return ContentProvider.this;
@@ -274,7 +274,7 @@
 
         @Override
         public Bundle call(String callingPkg, String method, String arg, Bundle extras) {
-            return ContentProvider.this.call(method, arg, extras);
+            return ContentProvider.this.callFromPackage(callingPkg, method, arg, extras);
         }
 
         @Override
@@ -309,7 +309,7 @@
 
         private int enforceReadPermission(String callingPkg, Uri uri) throws SecurityException {
             enforceReadPermissionInner(uri);
-            if (mAppOpsManager != null) {
+            if (mReadOp != AppOpsManager.OP_NONE) {
                 return mAppOpsManager.noteOp(mReadOp, Binder.getCallingUid(), callingPkg);
             }
             return AppOpsManager.MODE_ALLOWED;
@@ -378,7 +378,7 @@
 
         private int enforceWritePermission(String callingPkg, Uri uri) throws SecurityException {
             enforceWritePermissionInner(uri);
-            if (mAppOpsManager != null) {
+            if (mWriteOp != AppOpsManager.OP_NONE) {
                 return mAppOpsManager.noteOp(mWriteOp, Binder.getCallingUid(), callingPkg);
             }
             return AppOpsManager.MODE_ALLOWED;
@@ -529,6 +529,11 @@
         mTransport.mWriteOp = writeOp;
     }
 
+    /** @hide */
+    public AppOpsManager getAppOpsManager() {
+        return mTransport.mAppOpsManager;
+    }
+
     /**
      * Implement this to initialize your content provider on startup.
      * This method is called for all registered content providers on the
@@ -1189,6 +1194,15 @@
     }
 
     /**
+     * @hide
+     * Front-end to {@link #call(String, String, android.os.Bundle)} that provides the name
+     * of the calling package.
+     */
+    public Bundle callFromPackage(String callingPackag, String method, String arg, Bundle extras) {
+        return call(method, arg, extras);
+    }
+
+    /**
      * Call a provider-defined method.  This can be used to implement
      * interfaces that are cheaper and/or unnatural for a table-like
      * model.
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index e0c9d2c..41384d2 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -194,7 +194,8 @@
         return mMinDelay;
     }
 
-    int getHandle() {
+    /** @hide */
+    public int getHandle() {
         return mHandle;
     }
 
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index b8ad818..c0d2fae 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -1314,56 +1314,4 @@
             return mLegacySensorManager;
         }
     }
-
-    /**
-     * Sensor event pool implementation.
-     * @hide
-     */
-    protected static final class SensorEventPool {
-        private final int mPoolSize;
-        private final SensorEvent mPool[];
-        private int mNumItemsInPool;
-
-        private SensorEvent createSensorEvent() {
-            // maximal size for all legacy events is 3
-            return new SensorEvent(3);
-        }
-
-        SensorEventPool(int poolSize) {
-            mPoolSize = poolSize;
-            mNumItemsInPool = poolSize;
-            mPool = new SensorEvent[poolSize];
-        }
-
-        SensorEvent getFromPool() {
-            SensorEvent t = null;
-            synchronized (this) {
-                if (mNumItemsInPool > 0) {
-                    // remove the "top" item from the pool
-                    final int index = mPoolSize - mNumItemsInPool;
-                    t = mPool[index];
-                    mPool[index] = null;
-                    mNumItemsInPool--;
-                }
-            }
-            if (t == null) {
-                // the pool was empty or this item was removed from the pool for
-                // the first time. In any case, we need to create a new item.
-                t = createSensorEvent();
-            }
-            return t;
-        }
-
-        void returnToPool(SensorEvent t) {
-            synchronized (this) {
-                // is there space left in the pool?
-                if (mNumItemsInPool < mPoolSize) {
-                    // if so, return the item to the pool
-                    mNumItemsInPool++;
-                    final int index = mPoolSize - mNumItemsInPool;
-                    mPool[index] = t;
-                }
-            }
-        }
-    }
 }
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 7375e7d..9591631 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -16,18 +16,19 @@
 
 package android.hardware;
 
-import android.os.Looper;
-import android.os.Process;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+
+import dalvik.system.CloseGuard;
+
 import android.os.Handler;
-import android.os.Message;
-import android.util.Log;
+import android.os.Looper;
+import android.os.MessageQueue;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 
-import java.util.ArrayList;
-import java.util.List;
-
 /**
  * Sensor manager implementation that communicates with the built-in
  * system sensors.
@@ -35,236 +36,43 @@
  * @hide
  */
 public class SystemSensorManager extends SensorManager {
-    private static final int SENSOR_DISABLE = -1;
-    private static boolean sSensorModuleInitialized = false;
-    private static ArrayList<Sensor> sFullSensorsList = new ArrayList<Sensor>();
-    /* The thread and the sensor list are global to the process
-     * but the actual thread is spawned on demand */
-    private static SensorThread sSensorThread;
-    private static int sQueue;
+    private static native void nativeClassInit();
+    private static native int nativeGetNextSensor(Sensor sensor, int next);
 
-    // Used within this module from outside SensorManager, don't make private
-    static SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>();
-    static final ArrayList<ListenerDelegate> sListeners =
-        new ArrayList<ListenerDelegate>();
+    private static boolean sSensorModuleInitialized = false;
+    private static final Object sSensorModuleLock = new Object();
+    private static final ArrayList<Sensor> sFullSensorsList = new ArrayList<Sensor>();
+    private static final SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>();
+
+    // Listener list
+    private final ArrayList<SensorEventListenerSensorPair> mListenerDelegates = new ArrayList<SensorEventListenerSensorPair>();
 
     // Common pool of sensor events.
-    static SensorEventPool sPool;
+    private static SensorEventPool sPool;
 
     // Looper associated with the context in which this instance was created.
-    final Looper mMainLooper;
+    private final Looper mMainLooper;
 
-    /*-----------------------------------------------------------------------*/
+    // maps a SensorEventListener to a SensorEventQueue
+    private final Hashtable<SensorEventListener, SensorEventQueue> mSensorEventQueueMap;
 
-    static private class SensorThread {
-
-        Thread mThread;
-        boolean mSensorsReady;
-
-        SensorThread() {
-        }
-
-        @Override
-        protected void finalize() {
-        }
-
-        // must be called with sListeners lock
-        boolean startLocked() {
-            try {
-                if (mThread == null) {
-                    mSensorsReady = false;
-                    SensorThreadRunnable runnable = new SensorThreadRunnable();
-                    Thread thread = new Thread(runnable, SensorThread.class.getName());
-                    thread.start();
-                    synchronized (runnable) {
-                        while (mSensorsReady == false) {
-                            runnable.wait();
-                        }
-                    }
-                    mThread = thread;
-                }
-            } catch (InterruptedException e) {
-            }
-            return mThread == null ? false : true;
-        }
-
-        private class SensorThreadRunnable implements Runnable {
-            SensorThreadRunnable() {
-            }
-
-            private boolean open() {
-                // NOTE: this cannot synchronize on sListeners, since
-                // it's held in the main thread at least until we
-                // return from here.
-                sQueue = sensors_create_queue();
-                return true;
-            }
-
-            public void run() {
-                //Log.d(TAG, "entering main sensor thread");
-                final float[] values = new float[3];
-                final int[] status = new int[1];
-                final long timestamp[] = new long[1];
-                Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
-
-                if (!open()) {
-                    return;
-                }
-
-                synchronized (this) {
-                    // we've open the driver, we're ready to open the sensors
-                    mSensorsReady = true;
-                    this.notify();
-                }
-
-                while (true) {
-                    // wait for an event
-                    final int sensor = sensors_data_poll(sQueue, values, status, timestamp);
-
-                    int accuracy = status[0];
-                    synchronized (sListeners) {
-                        if (sensor == -1 || sListeners.isEmpty()) {
-                            // we lost the connection to the event stream. this happens
-                            // when the last listener is removed or if there is an error
-                            if (sensor == -1 && !sListeners.isEmpty()) {
-                                // log a warning in case of abnormal termination
-                                Log.e(TAG, "_sensors_data_poll() failed, we bail out: sensors=" + sensor);
-                            }
-                            // we have no more listeners or polling failed, terminate the thread
-                            sensors_destroy_queue(sQueue);
-                            sQueue = 0;
-                            mThread = null;
-                            break;
-                        }
-                        final Sensor sensorObject = sHandleToSensor.get(sensor);
-                        if (sensorObject != null) {
-                            // report the sensor event to all listeners that
-                            // care about it.
-                            final int size = sListeners.size();
-                            for (int i=0 ; i<size ; i++) {
-                                ListenerDelegate listener = sListeners.get(i);
-                                if (listener.hasSensor(sensorObject)) {
-                                    // this is asynchronous (okay to call
-                                    // with sListeners lock held).
-                                    listener.onSensorChangedLocked(sensorObject,
-                                            values, timestamp, accuracy);
-                                }
-                            }
-                        }
-                    }
-                }
-                //Log.d(TAG, "exiting main sensor thread");
-            }
-        }
-    }
-
-    /*-----------------------------------------------------------------------*/
-
-    private class ListenerDelegate {
-        private final SensorEventListener mSensorEventListener;
-        private final ArrayList<Sensor> mSensorList = new ArrayList<Sensor>();
-        private final Handler mHandler;
-        public SparseBooleanArray mSensors = new SparseBooleanArray();
-        public SparseBooleanArray mFirstEvent = new SparseBooleanArray();
-        public SparseIntArray mSensorAccuracies = new SparseIntArray();
-
-        ListenerDelegate(SensorEventListener listener, Sensor sensor, Handler handler) {
-            mSensorEventListener = listener;
-            Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
-            // currently we create one Handler instance per listener, but we could
-            // have one per looper (we'd need to pass the ListenerDelegate
-            // instance to handleMessage and keep track of them separately).
-            mHandler = new Handler(looper) {
-                @Override
-                public void handleMessage(Message msg) {
-                    final SensorEvent t = (SensorEvent)msg.obj;
-                    final int handle = t.sensor.getHandle();
-
-                    switch (t.sensor.getType()) {
-                        // Only report accuracy for sensors that support it.
-                        case Sensor.TYPE_MAGNETIC_FIELD:
-                        case Sensor.TYPE_ORIENTATION:
-                            // call onAccuracyChanged() only if the value changes
-                            final int accuracy = mSensorAccuracies.get(handle);
-                            if ((t.accuracy >= 0) && (accuracy != t.accuracy)) {
-                                mSensorAccuracies.put(handle, t.accuracy);
-                                mSensorEventListener.onAccuracyChanged(t.sensor, t.accuracy);
-                            }
-                            break;
-                        default:
-                            // For other sensors, just report the accuracy once
-                            if (mFirstEvent.get(handle) == false) {
-                                mFirstEvent.put(handle, true);
-                                mSensorEventListener.onAccuracyChanged(
-                                        t.sensor, SENSOR_STATUS_ACCURACY_HIGH);
-                            }
-                            break;
-                    }
-
-                    mSensorEventListener.onSensorChanged(t);
-                    sPool.returnToPool(t);
-                }
-            };
-            addSensor(sensor);
-        }
-
-        Object getListener() {
-            return mSensorEventListener;
-        }
-
-        void addSensor(Sensor sensor) {
-            mSensors.put(sensor.getHandle(), true);
-            mSensorList.add(sensor);
-        }
-        int removeSensor(Sensor sensor) {
-            mSensors.delete(sensor.getHandle());
-            mSensorList.remove(sensor);
-            return mSensors.size();
-        }
-        boolean hasSensor(Sensor sensor) {
-            return mSensors.get(sensor.getHandle());
-        }
-        List<Sensor> getSensors() {
-            return mSensorList;
-        }
-
-        void onSensorChangedLocked(Sensor sensor, float[] values, long[] timestamp, int accuracy) {
-            SensorEvent t = sPool.getFromPool();
-            final float[] v = t.values;
-            v[0] = values[0];
-            v[1] = values[1];
-            v[2] = values[2];
-            t.timestamp = timestamp[0];
-            t.accuracy = accuracy;
-            t.sensor = sensor;
-            Message msg = Message.obtain();
-            msg.what = 0;
-            msg.obj = t;
-            msg.setAsynchronous(true);
-            mHandler.sendMessage(msg);
-        }
-    }
-
-    /**
-     * {@hide}
-     */
+    /** {@hide} */
     public SystemSensorManager(Looper mainLooper) {
         mMainLooper = mainLooper;
+        mSensorEventQueueMap = new Hashtable<SensorEventListener, SensorEventQueue>();
 
-        synchronized(sListeners) {
+        synchronized(sSensorModuleLock) {
             if (!sSensorModuleInitialized) {
                 sSensorModuleInitialized = true;
 
                 nativeClassInit();
 
                 // initialize the sensor list
-                sensors_module_init();
                 final ArrayList<Sensor> fullList = sFullSensorsList;
                 int i = 0;
                 do {
                     Sensor sensor = new Sensor();
-                    i = sensors_module_get_next_sensor(sensor, i);
-
+                    i = nativeGetNextSensor(sensor, i);
                     if (i>=0) {
                         //Log.d(TAG, "found sensor: " + sensor.getName() +
                         //        ", handle=" + sensor.getHandle());
@@ -274,126 +82,304 @@
                 } while (i>0);
 
                 sPool = new SensorEventPool( sFullSensorsList.size()*2 );
-                sSensorThread = new SensorThread();
             }
         }
     }
 
+
     /** @hide */
     @Override
     protected List<Sensor> getFullSensorList() {
         return sFullSensorsList;
     }
 
-    private boolean enableSensorLocked(Sensor sensor, int delay) {
-        boolean result = false;
-        for (ListenerDelegate i : sListeners) {
-            if (i.hasSensor(sensor)) {
-                String name = sensor.getName();
-                int handle = sensor.getHandle();
-                result = sensors_enable_sensor(sQueue, name, handle, delay);
-                break;
-            }
-        }
-        return result;
-    }
-
-    private boolean disableSensorLocked(Sensor sensor) {
-        for (ListenerDelegate i : sListeners) {
-            if (i.hasSensor(sensor)) {
-                // not an error, it's just that this sensor is still in use
-                return true;
-            }
-        }
-        String name = sensor.getName();
-        int handle = sensor.getHandle();
-        return sensors_enable_sensor(sQueue, name, handle, SENSOR_DISABLE);
-    }
 
     /** @hide */
     @Override
     protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
-            int delay, Handler handler) {
-        boolean result = true;
-        synchronized (sListeners) {
-            // look for this listener in our list
-            ListenerDelegate l = null;
-            for (ListenerDelegate i : sListeners) {
-                if (i.getListener() == listener) {
-                    l = i;
-                    break;
+            int delay, Handler handler)
+    {
+        // Invariants to preserve:
+        // - one Looper per SensorEventListener
+        // - one Looper per SensorEventQueue
+        // We map SensorEventListeners to a SensorEventQueue, which holds the looper
+
+        if (sensor == null) throw new NullPointerException("sensor cannot be null");
+
+        boolean result;
+        synchronized (mSensorEventQueueMap) {
+            // check if we already have this SensorEventListener, Sensor pair
+            // registered -- if so, we ignore the register. This is not ideal
+            // but this is what the implementation has always been doing.
+            for (SensorEventListenerSensorPair l : mListenerDelegates) {
+                if (l.isSameListenerSensorPair(listener, sensor)) {
+                    // already added, just return silently.
+                    return true;
                 }
             }
 
-            // if we don't find it, add it to the list
-            if (l == null) {
-                l = new ListenerDelegate(listener, sensor, handler);
-                sListeners.add(l);
-                // if the list is not empty, start our main thread
-                if (!sListeners.isEmpty()) {
-                    if (sSensorThread.startLocked()) {
-                        if (!enableSensorLocked(sensor, delay)) {
-                            // oops. there was an error
-                            sListeners.remove(l);
-                            result = false;
-                        }
-                    } else {
-                        // there was an error, remove the listener
-                        sListeners.remove(l);
-                        result = false;
-                    }
-                } else {
-                    // weird, we couldn't add the listener
-                    result = false;
+            // now find the SensorEventQueue associated to this listener
+            SensorEventQueue queue = mSensorEventQueueMap.get(listener);
+            if (queue != null) {
+                result = queue.addSensor(sensor, delay);
+                if (result) {
+                    // create a new ListenerDelegate for this pair
+                    mListenerDelegates.add(new SensorEventListenerSensorPair(listener, sensor));
                 }
-            } else if (!l.hasSensor(sensor)) {
-                l.addSensor(sensor);
-                if (!enableSensorLocked(sensor, delay)) {
-                    // oops. there was an error
-                    l.removeSensor(sensor);
-                    result = false;
+            } else {
+                Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
+                queue = new SensorEventQueue(listener, looper.getQueue());
+                result = queue.addSensor(sensor, delay);
+                if (result) {
+                    // create a new ListenerDelegate for this pair
+                    mListenerDelegates.add(new SensorEventListenerSensorPair(listener, sensor));
+                    mSensorEventQueueMap.put(listener, queue);
+                } else {
+                    queue.dispose();
                 }
             }
         }
-
         return result;
     }
 
     /** @hide */
     @Override
     protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) {
-        synchronized (sListeners) {
-            final int size = sListeners.size();
-            for (int i=0 ; i<size ; i++) {
-                ListenerDelegate l = sListeners.get(i);
-                if (l.getListener() == listener) {
-                    if (sensor == null) {
-                        sListeners.remove(i);
-                        // disable all sensors for this listener
-                        for (Sensor s : l.getSensors()) {
-                            disableSensorLocked(s);
-                        }
-                    // Check if the ListenerDelegate has the sensor it is trying to unregister.
-                    } else if (l.hasSensor(sensor) && l.removeSensor(sensor) == 0) {
-                        // if we have no more sensors enabled on this listener,
-                        // take it off the list.
-                        sListeners.remove(i);
-                        disableSensorLocked(sensor);
-                    }
-                    break;
+        synchronized (mSensorEventQueueMap) {
+
+            // remove this listener/sensor from our list
+            final ArrayList<SensorEventListenerSensorPair> copy =
+                    new ArrayList<SensorEventListenerSensorPair>(mListenerDelegates);
+            int lastIndex = copy.size()-1;
+            for (int i=lastIndex ; i>= 0 ; i--) {
+                if (copy.get(i).isSameListenerSensorPair(listener, sensor)) {
+                    mListenerDelegates.remove(i);
+                }
+            }
+
+            // find the SensorEventQueue associated to this SensorEventListener
+            SensorEventQueue queue = mSensorEventQueueMap.get(listener);
+            if (queue != null) {
+                if (sensor != null) {
+                    queue.removeSensor(sensor);
+                } else {
+                    queue.removeAllSensors();
+                }
+                if (!queue.hasSensors()) {
+                    mSensorEventQueueMap.remove(listener);
+                    queue.dispose();
                 }
             }
         }
     }
 
-    private static native void nativeClassInit();
 
-    private static native int sensors_module_init();
-    private static native int sensors_module_get_next_sensor(Sensor sensor, int next);
+    /*
+     * ListenerDelegate is essentially a SensorEventListener, Sensor pair
+     * and is associated with a single SensorEventQueue.
+     */
+    private static final class SensorEventListenerSensorPair {
+        private final SensorEventListener mSensorEventListener;
+        private final Sensor mSensor;
+        public SensorEventListenerSensorPair(SensorEventListener listener, Sensor sensor) {
+            mSensorEventListener = listener;
+            mSensor = sensor;
+        }
+        public boolean isSameListenerSensorPair(SensorEventListener listener, Sensor sensor) {
+            // if sensor is null, we match only on the listener
+            if (sensor != null) {
+                return (listener == mSensorEventListener) &&
+                        (sensor.getHandle() == mSensor.getHandle());
+            } else {
+                return (listener == mSensorEventListener);
+            }
+        }
+    }
 
-    // Used within this module from outside SensorManager, don't make private
-    static native int sensors_create_queue();
-    static native void sensors_destroy_queue(int queue);
-    static native boolean sensors_enable_sensor(int queue, String name, int sensor, int enable);
-    static native int sensors_data_poll(int queue, float[] values, int[] status, long[] timestamp);
+    /*
+     * SensorEventQueue is the communication channel with the sensor service,
+     * there is a one-to-one mapping between SensorEventQueue and
+     * SensorEventListener.
+     */
+    private static final class SensorEventQueue {
+        private static native int nativeInitSensorEventQueue(SensorEventQueue eventQ, MessageQueue msgQ, float[] scratch);
+        private static native int nativeEnableSensor(int eventQ, int handle, int us);
+        private static native int nativeDisableSensor(int eventQ, int handle);
+        private static native void nativeDestroySensorEventQueue(int eventQ);
+        private int nSensorEventQueue;
+        private final SensorEventListener mListener;
+        private final SparseBooleanArray mActiveSensors = new SparseBooleanArray();
+        private final SparseIntArray mSensorAccuracies = new SparseIntArray();
+        private final SparseBooleanArray mFirstEvent = new SparseBooleanArray();
+        private final CloseGuard mCloseGuard = CloseGuard.get();
+        private final float[] mScratch = new float[16];
+
+        public SensorEventQueue(SensorEventListener listener, MessageQueue msgQ) {
+            nSensorEventQueue = nativeInitSensorEventQueue(this, msgQ, mScratch);
+            mListener = listener;
+            mCloseGuard.open("dispose");
+        }
+        public void dispose() {
+            dispose(false);
+        }
+
+        public boolean addSensor(Sensor sensor, int delay) {
+            if (enableSensor(sensor, delay) == 0) {
+                mActiveSensors.put(sensor.getHandle(), true);
+                return true;
+            }
+            return false;
+        }
+
+        public void removeAllSensors() {
+            for (int i=0 ; i<mActiveSensors.size(); i++) {
+                if (mActiveSensors.valueAt(i) == true) {
+                    int handle = mActiveSensors.keyAt(i);
+                    Sensor sensor = sHandleToSensor.get(handle);
+                    if (sensor != null) {
+                        disableSensor(sensor);
+                        mActiveSensors.put(handle, false);
+                    } else {
+                        // it should never happen -- just ignore.
+                    }
+                }
+            }
+        }
+
+        public void removeSensor(Sensor sensor) {
+            final int handle = sensor.getHandle();
+            if (mActiveSensors.get(handle)) {
+                disableSensor(sensor);
+                mActiveSensors.put(sensor.getHandle(), false);
+            }
+        }
+
+        public boolean hasSensors() {
+            // no more sensors are set
+            return mActiveSensors.indexOfValue(true) >= 0;
+        }
+        
+        @Override
+        protected void finalize() throws Throwable {
+            try {
+                dispose(true);
+            } finally {
+                super.finalize();
+            }
+        }
+
+        private void dispose(boolean finalized) {
+            if (mCloseGuard != null) {
+                if (finalized) {
+                    mCloseGuard.warnIfOpen();
+                }
+                mCloseGuard.close();
+            }
+            if (nSensorEventQueue != 0) {
+                nativeDestroySensorEventQueue(nSensorEventQueue);
+                nSensorEventQueue = 0;
+            }
+        }
+
+        private int enableSensor(Sensor sensor, int us) {
+            if (nSensorEventQueue == 0) throw new NullPointerException();
+            if (sensor == null) throw new NullPointerException();
+            return nativeEnableSensor(nSensorEventQueue, sensor.getHandle(), us);
+        }
+        private int disableSensor(Sensor sensor) {
+            if (nSensorEventQueue == 0) throw new NullPointerException();
+            if (sensor == null) throw new NullPointerException();
+            return nativeDisableSensor(nSensorEventQueue, sensor.getHandle());
+        }
+
+        // Called from native code.
+        @SuppressWarnings("unused")
+        private void dispatchSensorEvent(int handle, float[] values, int inAccuracy, long timestamp) {
+            // this is always called on the same thread.
+            final SensorEvent t = sPool.getFromPool();
+            try {
+                final Sensor sensor = sHandleToSensor.get(handle);
+                final SensorEventListener listener = mListener;
+                // FIXME: handle more than 3 values
+                System.arraycopy(values, 0, t.values, 0, 3);
+                t.timestamp = timestamp;
+                t.accuracy = inAccuracy;
+                t.sensor = sensor;
+                switch (t.sensor.getType()) {
+                    // Only report accuracy for sensors that support it.
+                    case Sensor.TYPE_MAGNETIC_FIELD:
+                    case Sensor.TYPE_ORIENTATION:
+                        // call onAccuracyChanged() only if the value changes
+                        final int accuracy = mSensorAccuracies.get(handle);
+                        if ((t.accuracy >= 0) && (accuracy != t.accuracy)) {
+                            mSensorAccuracies.put(handle, t.accuracy);
+                            listener.onAccuracyChanged(t.sensor, t.accuracy);
+                        }
+                        break;
+                    default:
+                        // For other sensors, just report the accuracy once
+                        if (mFirstEvent.get(handle) == false) {
+                            mFirstEvent.put(handle, true);
+                            listener.onAccuracyChanged(
+                                    t.sensor, SENSOR_STATUS_ACCURACY_HIGH);
+                        }
+                        break;
+                }
+                listener.onSensorChanged(t);
+            } finally {
+                sPool.returnToPool(t);
+            }
+        }
+    }
+
+    /*
+     * A dumb pool of SensorEvent
+     */
+    private static final class SensorEventPool {
+        private final int mPoolSize;
+        private final SensorEvent mPool[];
+        private int mNumItemsInPool;
+
+        private SensorEvent createSensorEvent() {
+            // maximal size for all legacy events is 3
+            return new SensorEvent(3);
+        }
+
+        SensorEventPool(int poolSize) {
+            mPoolSize = poolSize;
+            mNumItemsInPool = poolSize;
+            mPool = new SensorEvent[poolSize];
+        }
+
+        SensorEvent getFromPool() {
+            SensorEvent t = null;
+            synchronized (this) {
+                if (mNumItemsInPool > 0) {
+                    // remove the "top" item from the pool
+                    final int index = mPoolSize - mNumItemsInPool;
+                    t = mPool[index];
+                    mPool[index] = null;
+                    mNumItemsInPool--;
+                }
+            }
+            if (t == null) {
+                // the pool was empty or this item was removed from the pool for
+                // the first time. In any case, we need to create a new item.
+                t = createSensorEvent();
+            }
+            return t;
+        }
+
+        void returnToPool(SensorEvent t) {
+            synchronized (this) {
+                // is there space left in the pool?
+                if (mNumItemsInPool < mPoolSize) {
+                    // if so, return the item to the pool
+                    mNumItemsInPool++;
+                    final int index = mPoolSize - mNumItemsInPool;
+                    mPool[index] = t;
+                }
+            }
+        }
+    }
 }
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index abbb6a1..499ec77 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -301,6 +301,11 @@
         public abstract int getUserActivityCount(int type, int which);
         
         public static abstract class Sensor {
+            /*
+             * FIXME: it's not correct to use this magic value because it
+             * could clash with a sensor handle (which are defined by
+             * the sensor HAL, and therefore out of our control
+             */
             // Magic sensor number for the GPS.
             public static final int GPS = -10000;
             
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 8051923..80c9324 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -515,22 +515,22 @@
 
     @Override
     public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) {
-        return nQuickReject(mRenderer, left, top, right, bottom, type.nativeInt);
+        return nQuickReject(mRenderer, left, top, right, bottom);
     }
     
     private static native boolean nQuickReject(int renderer, float left, float top,
-            float right, float bottom, int edge);
+            float right, float bottom);
 
     @Override
     public boolean quickReject(Path path, EdgeType type) {
         path.computeBounds(mPathBounds, true);
         return nQuickReject(mRenderer, mPathBounds.left, mPathBounds.top,
-                mPathBounds.right, mPathBounds.bottom, type.nativeInt);
+                mPathBounds.right, mPathBounds.bottom);
     }
 
     @Override
     public boolean quickReject(RectF rect, EdgeType type) {
-        return nQuickReject(mRenderer, rect.left, rect.top, rect.right, rect.bottom, type.nativeInt);
+        return nQuickReject(mRenderer, rect.left, rect.top, rect.right, rect.bottom);
     }
 
     ///////////////////////////////////////////////////////////////////////////
diff --git a/core/java/android/view/SimulatedDpad.java b/core/java/android/view/SimulatedDpad.java
index 1ee416c..883fd49 100644
--- a/core/java/android/view/SimulatedDpad.java
+++ b/core/java/android/view/SimulatedDpad.java
@@ -145,6 +145,10 @@
         if (!synthesizeNewKeys) {
             mHandler.removeMessages(MSG_FLICK);
         }
+        InputDevice device = event.getDevice();
+        if (device == null) {
+            return;
+        }
         // Store what time the touchpad event occurred
         final long time = SystemClock.uptimeMillis();
         switch (event.getAction()) {
@@ -157,7 +161,7 @@
                 mAccumulatedY = 0;
                 mLastMoveX = 0;
                 mLastMoveY = 0;
-                if (event.getDevice().getMotionRange(MotionEvent.AXIS_Y).getMax()
+                if (device.getMotionRange(MotionEvent.AXIS_Y).getMax()
                         * EDGE_SWIPE_THRESHOLD < event.getY()) {
                     // Did the swipe begin in a valid region
                     mEdgeSwipePossible = true;
@@ -176,7 +180,7 @@
                 }
                 // Checks if the swipe has crossed the midpoint
                 // and if our swipe gesture is complete
-                if (event.getY() < (event.getDevice().getMotionRange(MotionEvent.AXIS_Y).getMax()
+                if (event.getY() < (device.getMotionRange(MotionEvent.AXIS_Y).getMax()
                         * .5) && mEdgeSwipePossible) {
                     mEdgeSwipePossible = false;
 
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index a972b75..c10f287 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -215,7 +215,6 @@
     private int mNativeSurfaceControl; // SurfaceControl*
     private int mGenerationId; // incremented each time mNativeSurface changes
     private final Canvas mCanvas = new CompatibleCanvas();
-    private int mCanvasSaveCount; // Canvas save count at time of lockCanvas()
 
     // The Translator for density compatibility mode.  This is used for scaling
     // the canvas to perform the appropriate density transformation.
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index cbd0668..ee3ca8c 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4859,13 +4859,25 @@
         event.setEnabled(isEnabled());
         event.setContentDescription(mContentDescription);
 
-        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED && mAttachInfo != null) {
-            ArrayList<View> focusablesTempList = mAttachInfo.mTempArrayList;
-            getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD,
-                    FOCUSABLES_ALL);
-            event.setItemCount(focusablesTempList.size());
-            event.setCurrentItemIndex(focusablesTempList.indexOf(this));
-            focusablesTempList.clear();
+        switch (event.getEventType()) {
+            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
+                ArrayList<View> focusablesTempList = (mAttachInfo != null)
+                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
+                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
+                event.setItemCount(focusablesTempList.size());
+                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
+                if (mAttachInfo != null) {
+                    focusablesTempList.clear();
+                }
+            } break;
+            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
+                CharSequence text = getIterableTextForAccessibility();
+                if (text != null && text.length() > 0) {
+                    event.setFromIndex(getAccessibilitySelectionStart());
+                    event.setToIndex(getAccessibilitySelectionEnd());
+                    event.setItemCount(text.length());
+                }
+            } break;
         }
     }
 
@@ -5081,7 +5093,10 @@
             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
         }
 
-        if (mContentDescription != null && mContentDescription.length() > 0) {
+        CharSequence text = getIterableTextForAccessibility();
+        if (text != null && text.length() > 0) {
+            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
+
             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
@@ -7153,11 +7168,15 @@
      * @hide
      */
     public void setAccessibilitySelection(int start, int end) {
+        if (start ==  end && end == mAccessibilityCursorPosition) {
+            return;
+        }
         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
             mAccessibilityCursorPosition = start;
         } else {
             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
         }
+        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
     }
 
     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index f61c879..ad87fcb 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -372,29 +372,31 @@
 
     // Boolean attributes.
 
-    private static final int PROPERTY_CHECKABLE = 0x00000001;
+    private static final int BOOLEAN_PROPERTY_CHECKABLE = 0x00000001;
 
-    private static final int PROPERTY_CHECKED = 0x00000002;
+    private static final int BOOLEAN_PROPERTY_CHECKED = 0x00000002;
 
-    private static final int PROPERTY_FOCUSABLE = 0x00000004;
+    private static final int BOOLEAN_PROPERTY_FOCUSABLE = 0x00000004;
 
-    private static final int PROPERTY_FOCUSED = 0x00000008;
+    private static final int BOOLEAN_PROPERTY_FOCUSED = 0x00000008;
 
-    private static final int PROPERTY_SELECTED = 0x00000010;
+    private static final int BOOLEAN_PROPERTY_SELECTED = 0x00000010;
 
-    private static final int PROPERTY_CLICKABLE = 0x00000020;
+    private static final int BOOLEAN_PROPERTY_CLICKABLE = 0x00000020;
 
-    private static final int PROPERTY_LONG_CLICKABLE = 0x00000040;
+    private static final int BOOLEAN_PROPERTY_LONG_CLICKABLE = 0x00000040;
 
-    private static final int PROPERTY_ENABLED = 0x00000080;
+    private static final int BOOLEAN_PROPERTY_ENABLED = 0x00000080;
 
-    private static final int PROPERTY_PASSWORD = 0x00000100;
+    private static final int BOOLEAN_PROPERTY_PASSWORD = 0x00000100;
 
-    private static final int PROPERTY_SCROLLABLE = 0x00000200;
+    private static final int BOOLEAN_PROPERTY_SCROLLABLE = 0x00000200;
 
-    private static final int PROPERTY_ACCESSIBILITY_FOCUSED = 0x00000400;
+    private static final int BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED = 0x00000400;
 
-    private static final int PROPERTY_VISIBLE_TO_USER = 0x00000800;
+    private static final int BOOLEAN_PROPERTY_VISIBLE_TO_USER = 0x00000800;
+
+    private static final int BOOLEAN_PROPERTY_EDITABLE = 0x00001000;
 
     /**
      * Bits that provide the id of a virtual descendant of a view.
@@ -478,6 +480,9 @@
 
     private int mMovementGranularities;
 
+    private int mTextSelectionStart = UNDEFINED;
+    private int mTextSelectionEnd = UNDEFINED;
+
     private int mConnectionId = UNDEFINED;
 
     /**
@@ -987,7 +992,7 @@
      * @return True if the node is checkable.
      */
     public boolean isCheckable() {
-        return getBooleanProperty(PROPERTY_CHECKABLE);
+        return getBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE);
     }
 
     /**
@@ -1003,7 +1008,7 @@
      * @throws IllegalStateException If called from an AccessibilityService.
      */
     public void setCheckable(boolean checkable) {
-        setBooleanProperty(PROPERTY_CHECKABLE, checkable);
+        setBooleanProperty(BOOLEAN_PROPERTY_CHECKABLE, checkable);
     }
 
     /**
@@ -1012,7 +1017,7 @@
      * @return True if the node is checked.
      */
     public boolean isChecked() {
-        return getBooleanProperty(PROPERTY_CHECKED);
+        return getBooleanProperty(BOOLEAN_PROPERTY_CHECKED);
     }
 
     /**
@@ -1028,7 +1033,7 @@
      * @throws IllegalStateException If called from an AccessibilityService.
      */
     public void setChecked(boolean checked) {
-        setBooleanProperty(PROPERTY_CHECKED, checked);
+        setBooleanProperty(BOOLEAN_PROPERTY_CHECKED, checked);
     }
 
     /**
@@ -1037,7 +1042,7 @@
      * @return True if the node is focusable.
      */
     public boolean isFocusable() {
-        return getBooleanProperty(PROPERTY_FOCUSABLE);
+        return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE);
     }
 
     /**
@@ -1053,7 +1058,7 @@
      * @throws IllegalStateException If called from an AccessibilityService.
      */
     public void setFocusable(boolean focusable) {
-        setBooleanProperty(PROPERTY_FOCUSABLE, focusable);
+        setBooleanProperty(BOOLEAN_PROPERTY_FOCUSABLE, focusable);
     }
 
     /**
@@ -1062,7 +1067,7 @@
      * @return True if the node is focused.
      */
     public boolean isFocused() {
-        return getBooleanProperty(PROPERTY_FOCUSED);
+        return getBooleanProperty(BOOLEAN_PROPERTY_FOCUSED);
     }
 
     /**
@@ -1078,7 +1083,7 @@
      * @throws IllegalStateException If called from an AccessibilityService.
      */
     public void setFocused(boolean focused) {
-        setBooleanProperty(PROPERTY_FOCUSED, focused);
+        setBooleanProperty(BOOLEAN_PROPERTY_FOCUSED, focused);
     }
 
     /**
@@ -1087,7 +1092,7 @@
      * @return Whether the node is visible to the user.
      */
     public boolean isVisibleToUser() {
-        return getBooleanProperty(PROPERTY_VISIBLE_TO_USER);
+        return getBooleanProperty(BOOLEAN_PROPERTY_VISIBLE_TO_USER);
     }
 
     /**
@@ -1103,7 +1108,7 @@
      * @throws IllegalStateException If called from an AccessibilityService.
      */
     public void setVisibleToUser(boolean visibleToUser) {
-        setBooleanProperty(PROPERTY_VISIBLE_TO_USER, visibleToUser);
+        setBooleanProperty(BOOLEAN_PROPERTY_VISIBLE_TO_USER, visibleToUser);
     }
 
     /**
@@ -1112,7 +1117,7 @@
      * @return True if the node is accessibility focused.
      */
     public boolean isAccessibilityFocused() {
-        return getBooleanProperty(PROPERTY_ACCESSIBILITY_FOCUSED);
+        return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED);
     }
 
     /**
@@ -1128,7 +1133,7 @@
      * @throws IllegalStateException If called from an AccessibilityService.
      */
     public void setAccessibilityFocused(boolean focused) {
-        setBooleanProperty(PROPERTY_ACCESSIBILITY_FOCUSED, focused);
+        setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED, focused);
     }
 
     /**
@@ -1137,7 +1142,7 @@
      * @return True if the node is selected.
      */
     public boolean isSelected() {
-        return getBooleanProperty(PROPERTY_SELECTED);
+        return getBooleanProperty(BOOLEAN_PROPERTY_SELECTED);
     }
 
     /**
@@ -1153,7 +1158,7 @@
      * @throws IllegalStateException If called from an AccessibilityService.
      */
     public void setSelected(boolean selected) {
-        setBooleanProperty(PROPERTY_SELECTED, selected);
+        setBooleanProperty(BOOLEAN_PROPERTY_SELECTED, selected);
     }
 
     /**
@@ -1162,7 +1167,7 @@
      * @return True if the node is clickable.
      */
     public boolean isClickable() {
-        return getBooleanProperty(PROPERTY_CLICKABLE);
+        return getBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE);
     }
 
     /**
@@ -1178,7 +1183,7 @@
      * @throws IllegalStateException If called from an AccessibilityService.
      */
     public void setClickable(boolean clickable) {
-        setBooleanProperty(PROPERTY_CLICKABLE, clickable);
+        setBooleanProperty(BOOLEAN_PROPERTY_CLICKABLE, clickable);
     }
 
     /**
@@ -1187,7 +1192,7 @@
      * @return True if the node is long clickable.
      */
     public boolean isLongClickable() {
-        return getBooleanProperty(PROPERTY_LONG_CLICKABLE);
+        return getBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE);
     }
 
     /**
@@ -1203,7 +1208,7 @@
      * @throws IllegalStateException If called from an AccessibilityService.
      */
     public void setLongClickable(boolean longClickable) {
-        setBooleanProperty(PROPERTY_LONG_CLICKABLE, longClickable);
+        setBooleanProperty(BOOLEAN_PROPERTY_LONG_CLICKABLE, longClickable);
     }
 
     /**
@@ -1212,7 +1217,7 @@
      * @return True if the node is enabled.
      */
     public boolean isEnabled() {
-        return getBooleanProperty(PROPERTY_ENABLED);
+        return getBooleanProperty(BOOLEAN_PROPERTY_ENABLED);
     }
 
     /**
@@ -1228,7 +1233,7 @@
      * @throws IllegalStateException If called from an AccessibilityService.
      */
     public void setEnabled(boolean enabled) {
-        setBooleanProperty(PROPERTY_ENABLED, enabled);
+        setBooleanProperty(BOOLEAN_PROPERTY_ENABLED, enabled);
     }
 
     /**
@@ -1237,7 +1242,7 @@
      * @return True if the node is a password.
      */
     public boolean isPassword() {
-        return getBooleanProperty(PROPERTY_PASSWORD);
+        return getBooleanProperty(BOOLEAN_PROPERTY_PASSWORD);
     }
 
     /**
@@ -1253,7 +1258,7 @@
      * @throws IllegalStateException If called from an AccessibilityService.
      */
     public void setPassword(boolean password) {
-        setBooleanProperty(PROPERTY_PASSWORD, password);
+        setBooleanProperty(BOOLEAN_PROPERTY_PASSWORD, password);
     }
 
     /**
@@ -1262,7 +1267,7 @@
      * @return True if the node is scrollable, false otherwise.
      */
     public boolean isScrollable() {
-        return getBooleanProperty(PROPERTY_SCROLLABLE);
+        return getBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE);
     }
 
     /**
@@ -1279,7 +1284,32 @@
      */
     public void setScrollable(boolean scrollable) {
         enforceNotSealed();
-        setBooleanProperty(PROPERTY_SCROLLABLE, scrollable);
+        setBooleanProperty(BOOLEAN_PROPERTY_SCROLLABLE, scrollable);
+    }
+
+    /**
+     * Gets if the node is editable.
+     *
+     * @return True if the node is editable, false otherwise.
+     */
+    public boolean isEditable() {
+        return getBooleanProperty(BOOLEAN_PROPERTY_EDITABLE);
+    }
+
+    /**
+     * Sets whether this node is editable.
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param editable True if the node is editable.
+     *
+     * @throws IllegalStateException If called from an AccessibilityService.
+     */
+    public void setEditable(boolean editable) {
+        setBooleanProperty(BOOLEAN_PROPERTY_EDITABLE, editable);
     }
 
     /**
@@ -1533,6 +1563,43 @@
     }
 
     /**
+     * Gets the text selection start.
+     *
+     * @return The text selection start if there is selection or -1.
+     */
+    public int getTextSelectionStart() {
+        return mTextSelectionStart;
+    }
+
+    /**
+     * Gets the text selection end.
+     *
+     * @return The text selection end if there is selection or -1.
+     */
+    public int getTextSelectionEnd() {
+        return mTextSelectionEnd;
+    }
+
+    /**
+     * Sets the text selection start and end.
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param start The text selection start.
+     * @param end The text selection end.
+     *
+     * @throws IllegalStateException If called from an AccessibilityService.
+     */
+    public void setTextSelection(int start, int end) {
+        enforceNotSealed();
+        mTextSelectionStart = start;
+        mTextSelectionEnd = end;
+    }
+
+    /**
      * Gets the value of a boolean property.
      *
      * @param property The property.
@@ -1776,6 +1843,9 @@
         parcel.writeCharSequence(mContentDescription);
         parcel.writeCharSequence(mViewIdResourceName);
 
+        parcel.writeInt(mTextSelectionStart);
+        parcel.writeInt(mTextSelectionEnd);
+
         // Since instances of this class are fetched via synchronous i.e. blocking
         // calls in IPCs we always recycle as soon as the instance is marshaled.
         recycle();
@@ -1808,6 +1878,8 @@
         for (int i = 0; i < otherChildIdCount; i++) {
             mChildNodeIds.put(i, other.mChildNodeIds.valueAt(i));    
         }
+        mTextSelectionStart = other.mTextSelectionStart;
+        mTextSelectionEnd = other.mTextSelectionEnd;
     }
 
     /**
@@ -1852,6 +1924,9 @@
         mText = parcel.readCharSequence();
         mContentDescription = parcel.readCharSequence();
         mViewIdResourceName = parcel.readCharSequence();
+
+        mTextSelectionStart = parcel.readInt();
+        mTextSelectionEnd = parcel.readInt();
     }
 
     /**
@@ -1876,6 +1951,8 @@
         mContentDescription = null;
         mViewIdResourceName = null;
         mActions = 0;
+        mTextSelectionStart = UNDEFINED;
+        mTextSelectionEnd = UNDEFINED;
     }
 
     /**
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 74ded18..2ac5a12 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -1969,8 +1969,10 @@
                  * Ensure the user can't type in a value greater than the max
                  * allowed. We have to allow less than min as the user might
                  * want to delete some numbers and then type a new number.
+                 * And prevent multiple-"0" that exceeds the length of upper
+                 * bound number.
                  */
-                if (val > mMaxValue) {
+                if (val > mMaxValue || result.length() > String.valueOf(mMaxValue).length()) {
                     return "";
                 } else {
                     return filtered;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 1579e79..2145419 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -7165,6 +7165,7 @@
      */
     protected void onSelectionChanged(int selStart, int selEnd) {
         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
+        notifyAccessibilityStateChanged();
     }
 
     /**
@@ -7976,6 +7977,10 @@
             info.setText(getTextForAccessibility());
         }
 
+        if (mBufferType == BufferType.EDITABLE) {
+            info.setEditable(true);
+        }
+
         if (TextUtils.isEmpty(getContentDescription()) && !TextUtils.isEmpty(mText)) {
             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 12a7491..6bb7ac7 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -559,6 +559,21 @@
     }
 
     public void setHomeButtonEnabled(boolean enable) {
+        setHomeButtonEnabled(enable, true);
+    }
+
+    private void setHomeButtonEnabled(boolean enable, boolean recordState) {
+        if (recordState) {
+            mWasHomeEnabled = enable;
+        }
+
+        if (mExpandedActionView != null) {
+            // There's an action view currently showing and we want to keep the state
+            // configured for the action view at the moment. If we needed to record the
+            // new state for later we will have done so above.
+            return;
+        }
+
         mUpGoerFive.setEnabled(enable);
         mUpGoerFive.setFocusable(enable);
         // Make sure the home button has an accurate content description for accessibility.
@@ -1540,8 +1555,7 @@
             if (mTabScrollView != null) mTabScrollView.setVisibility(GONE);
             if (mSpinner != null) mSpinner.setVisibility(GONE);
             if (mCustomNavView != null) mCustomNavView.setVisibility(GONE);
-            mWasHomeEnabled = mUpGoerFive.isEnabled();
-            setHomeButtonEnabled(false);
+            setHomeButtonEnabled(false, false);
             requestLayout();
             item.setActionViewExpanded(true);
 
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index d705024..44e8757 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -160,7 +160,8 @@
 	external/skia/include/effects \
 	external/skia/include/images \
 	external/skia/include/ports \
-	external/skia/src/ports \
+	external/skia/src/core \
+	external/skia/src/images \
 	external/skia/include/utils \
 	external/sqlite/dist \
 	external/sqlite/android \
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index b7fdecf..daabce3 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -231,7 +231,7 @@
     }
 
     SkAutoTDelete<SkImageDecoder> add(decoder);
-    SkAutoTDelete<SkBitmap> adb(bitmap, !useExistingBitmap);
+    SkAutoTDelete<SkBitmap> adb(!useExistingBitmap ? bitmap : NULL);
 
     decoder->setPeeker(&peeker);
     if (!isPurgeable) {
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 5d6f738..7208c57 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -93,14 +93,6 @@
         return canvas->getDevice()->accessBitmap(false).height();
     }
 
-    static void setBitmap(JNIEnv* env, jobject, SkCanvas* canvas, SkBitmap* bitmap) {
-        if (bitmap) {
-            canvas->setBitmapDevice(*bitmap);
-        } else {
-            canvas->setDevice(NULL);
-        }
-    }
- 
     static int saveAll(JNIEnv* env, jobject jcanvas) {
         NPE_CHECK_RETURN_ZERO(env, jcanvas);
         return GraphicsJNI::getNativeCanvas(env, jcanvas)->save();
@@ -278,25 +270,25 @@
         canvas->setDrawFilter(filter);
     }
     
-    static jboolean quickReject__RectFI(JNIEnv* env, jobject, SkCanvas* canvas,
-                                        jobject rect, int edgetype) {
+    static jboolean quickReject__RectF(JNIEnv* env, jobject, SkCanvas* canvas,
+                                        jobject rect) {
         SkRect rect_;
         GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
-        return canvas->quickReject(rect_, (SkCanvas::EdgeType)edgetype);
+        return canvas->quickReject(rect_);
     }
- 
-    static jboolean quickReject__PathI(JNIEnv* env, jobject, SkCanvas* canvas,
-                                       SkPath* path, int edgetype) {
-        return canvas->quickReject(*path, (SkCanvas::EdgeType)edgetype);
+
+    static jboolean quickReject__Path(JNIEnv* env, jobject, SkCanvas* canvas,
+                                       SkPath* path) {
+        return canvas->quickReject(*path);
     }
- 
-    static jboolean quickReject__FFFFI(JNIEnv* env, jobject, SkCanvas* canvas,
+
+    static jboolean quickReject__FFFF(JNIEnv* env, jobject, SkCanvas* canvas,
                                        jfloat left, jfloat top, jfloat right,
-                                       jfloat bottom, int edgetype) {
+                                       jfloat bottom) {
         SkRect r;
         r.set(SkFloatToScalar(left), SkFloatToScalar(top),
               SkFloatToScalar(right), SkFloatToScalar(bottom));
-        return canvas->quickReject(r, (SkCanvas::EdgeType)edgetype);
+        return canvas->quickReject(r);
     }
  
     static void drawRGB(JNIEnv* env, jobject, SkCanvas* canvas,
@@ -938,12 +930,19 @@
                               jobject bounds) {
         SkRect   r;
         SkIRect ir;
-        bool     result = canvas->getClipBounds(&r, SkCanvas::kBW_EdgeType);
+        bool     result = canvas->getClipBounds(&r);
 
         if (!result) {
             r.setEmpty();
+        } else {
+            // ensure the clip is not larger than the canvas
+            SkRect canvasRect;
+            SkISize deviceSize = canvas->getDeviceSize();
+            canvasRect.iset(0, 0, deviceSize.fWidth, deviceSize.fHeight);
+            r.intersect(canvasRect);
         }
         r.round(&ir);
+
         (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
         return result;
     }
@@ -960,7 +959,6 @@
     {"isOpaque","()Z", (void*) SkCanvasGlue::isOpaque},
     {"getWidth","()I", (void*) SkCanvasGlue::getWidth},
     {"getHeight","()I", (void*) SkCanvasGlue::getHeight},
-    {"native_setBitmap","(II)V", (void*) SkCanvasGlue::setBitmap},
     {"save","()I", (void*) SkCanvasGlue::saveAll},
     {"save","(I)I", (void*) SkCanvasGlue::save},
     {"native_saveLayer","(ILandroid/graphics/RectF;II)I",
@@ -992,10 +990,10 @@
     {"native_getClipBounds","(ILandroid/graphics/Rect;)Z",
         (void*) SkCanvasGlue::getClipBounds},
     {"native_getCTM", "(II)V", (void*)SkCanvasGlue::getCTM},
-    {"native_quickReject","(ILandroid/graphics/RectF;I)Z",
-        (void*) SkCanvasGlue::quickReject__RectFI},
-    {"native_quickReject","(III)Z", (void*) SkCanvasGlue::quickReject__PathI},
-    {"native_quickReject","(IFFFFI)Z", (void*)SkCanvasGlue::quickReject__FFFFI},
+    {"native_quickReject","(ILandroid/graphics/RectF;)Z",
+        (void*) SkCanvasGlue::quickReject__RectF},
+    {"native_quickReject","(II)Z", (void*) SkCanvasGlue::quickReject__Path},
+    {"native_quickReject","(IFFFF)Z", (void*)SkCanvasGlue::quickReject__FFFF},
     {"native_drawRGB","(IIII)V", (void*) SkCanvasGlue::drawRGB},
     {"native_drawARGB","(IIIII)V", (void*) SkCanvasGlue::drawARGB},
     {"native_drawColor","(II)V", (void*) SkCanvasGlue::drawColor__I},
diff --git a/core/jni/android/graphics/NinePatchImpl.cpp b/core/jni/android/graphics/NinePatchImpl.cpp
index ff0eb45..01e7e3e 100644
--- a/core/jni/android/graphics/NinePatchImpl.cpp
+++ b/core/jni/android/graphics/NinePatchImpl.cpp
@@ -105,7 +105,7 @@
 void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds,
                        const SkBitmap& bitmap, const android::Res_png_9patch& chunk,
                        const SkPaint* paint, SkRegion** outRegion) {
-    if (canvas && canvas->quickReject(bounds, SkCanvas::kBW_EdgeType)) {
+    if (canvas && canvas->quickReject(bounds)) {
         return;
     }
 
diff --git a/core/jni/android/graphics/Region.cpp b/core/jni/android/graphics/Region.cpp
index ab7cf46..ded2186 100644
--- a/core/jni/android/graphics/Region.cpp
+++ b/core/jni/android/graphics/Region.cpp
@@ -177,7 +177,7 @@
 
     SkRegion* region = new SkRegion;
     size_t size = p->readInt32();
-    region->unflatten(p->readInplace(size));
+    region->readFromMemory(p->readInplace(size));
 
     return region;
 }
@@ -190,9 +190,9 @@
 
     android::Parcel* p = android::parcelForJavaObject(env, parcel);
 
-    size_t size = region->flatten(NULL);
+    size_t size = region->writeToMemory(NULL);
     p->writeInt32(size);
-    region->flatten(p->writeInplace(size));
+    region->writeToMemory(p->writeInplace(size));
 
     return true;
 }
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 6d3c878..7544645 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -345,7 +345,7 @@
 }
 
 void TextLayoutShaper::init() {
-    mDefaultTypeface = SkFontHost::CreateTypeface(NULL, NULL, NULL, 0, SkTypeface::kNormal);
+    mDefaultTypeface = SkFontHost::CreateTypeface(NULL, NULL, SkTypeface::kNormal);
 }
 
 void TextLayoutShaper::unrefTypefaces() {
diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp
index 7f4c37b..e056b61 100644
--- a/core/jni/android/graphics/Typeface.cpp
+++ b/core/jni/android/graphics/Typeface.cpp
@@ -147,25 +147,6 @@
     return SkTypeface::CreateFromFile(str.c_str());
 }
 
-#define MIN_GAMMA   (0.1f)
-#define MAX_GAMMA   (10.0f)
-static float pinGamma(float gamma) {
-    if (gamma < MIN_GAMMA) {
-        gamma = MIN_GAMMA;
-    } else if (gamma > MAX_GAMMA) {
-        gamma = MAX_GAMMA;
-    }
-    return gamma;
-}
-
-extern void skia_set_text_gamma(float, float);
-
-static void Typeface_setGammaForText(JNIEnv* env, jobject, jfloat blackGamma,
-                                     jfloat whiteGamma) {
-    // Comment this out for release builds. This is only used during development
-    skia_set_text_gamma(pinGamma(blackGamma), pinGamma(whiteGamma));
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 
 static JNINativeMethod gTypefaceMethods[] = {
@@ -177,7 +158,6 @@
                                            (void*)Typeface_createFromAsset },
     { "nativeCreateFromFile",     "(Ljava/lang/String;)I",
                                            (void*)Typeface_createFromFile },
-    { "setGammaForText", "(FF)V", (void*)Typeface_setGammaForText },
 };
 
 int register_android_graphics_Typeface(JNIEnv* env)
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 3c1b9c8..e8a6569 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -16,7 +16,8 @@
 
 #define LOG_TAG "SensorManager"
 
-#include "utils/Log.h"
+#include <utils/Log.h>
+#include <utils/Looper.h>
 
 #include <gui/Sensor.h>
 #include <gui/SensorManager.h>
@@ -24,7 +25,13 @@
 
 #include "jni.h"
 #include "JNIHelp.h"
+#include "android_os_MessageQueue.h"
+#include <android_runtime/AndroidRuntime.h>
 
+static struct {
+    jclass clazz;
+    jmethodID dispatchSensorEvent;
+} gSensorEventQueueClassInfo;
 
 namespace android {
 
@@ -41,20 +48,29 @@
     jfieldID    minDelay;
 } gSensorOffsets;
 
+
 /*
  * The method below are not thread-safe and not intended to be
  */
 
-
-static jint
-sensors_module_init(JNIEnv *env, jclass clazz)
+static void
+nativeClassInit (JNIEnv *_env, jclass _this)
 {
-    SensorManager::getInstance();
-    return 0;
+    jclass sensorClass = _env->FindClass("android/hardware/Sensor");
+    SensorOffsets& sensorOffsets = gSensorOffsets;
+    sensorOffsets.name        = _env->GetFieldID(sensorClass, "mName",      "Ljava/lang/String;");
+    sensorOffsets.vendor      = _env->GetFieldID(sensorClass, "mVendor",    "Ljava/lang/String;");
+    sensorOffsets.version     = _env->GetFieldID(sensorClass, "mVersion",   "I");
+    sensorOffsets.handle      = _env->GetFieldID(sensorClass, "mHandle",    "I");
+    sensorOffsets.type        = _env->GetFieldID(sensorClass, "mType",      "I");
+    sensorOffsets.range       = _env->GetFieldID(sensorClass, "mMaxRange",  "F");
+    sensorOffsets.resolution  = _env->GetFieldID(sensorClass, "mResolution","F");
+    sensorOffsets.power       = _env->GetFieldID(sensorClass, "mPower",     "F");
+    sensorOffsets.minDelay    = _env->GetFieldID(sensorClass, "mMinDelay",  "I");
 }
 
 static jint
-sensors_module_get_next_sensor(JNIEnv *env, jobject clazz, jobject sensor, jint next)
+nativeGetNextSensor(JNIEnv *env, jclass clazz, jobject sensor, jint next)
 {
     SensorManager& mgr(SensorManager::getInstance());
 
@@ -82,106 +98,161 @@
 }
 
 //----------------------------------------------------------------------------
-static jint
-sensors_create_queue(JNIEnv *env, jclass clazz)
-{
+
+class Receiver : public LooperCallback {
+    sp<SensorEventQueue> mSensorQueue;
+    sp<MessageQueue> mMessageQueue;
+    jobject mReceiverObject;
+    jfloatArray mScratch;
+public:
+    Receiver(const sp<SensorEventQueue>& sensorQueue,
+            const sp<MessageQueue>& messageQueue,
+            jobject receiverObject, jfloatArray scratch) {
+        JNIEnv* env = AndroidRuntime::getJNIEnv();
+        mSensorQueue = sensorQueue;
+        mMessageQueue = messageQueue;
+        mReceiverObject = env->NewGlobalRef(receiverObject);
+        mScratch = (jfloatArray)env->NewGlobalRef(scratch);
+    }
+    ~Receiver() {
+        JNIEnv* env = AndroidRuntime::getJNIEnv();
+        env->DeleteGlobalRef(mReceiverObject);
+        env->DeleteGlobalRef(mScratch);
+    }
+    sp<SensorEventQueue> getSensorEventQueue() const {
+        return mSensorQueue;
+    }
+
+    void destroy() {
+        mMessageQueue->getLooper()->removeFd( mSensorQueue->getFd() );
+    }
+
+private:
+    virtual void onFirstRef() {
+        LooperCallback::onFirstRef();
+        mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0,
+                ALOOPER_EVENT_INPUT, this, mSensorQueue.get());
+    }
+
+    virtual int handleEvent(int fd, int events, void* data) {
+        JNIEnv* env = AndroidRuntime::getJNIEnv();
+        sp<SensorEventQueue> q = reinterpret_cast<SensorEventQueue *>(data);
+        ssize_t n;
+        ASensorEvent buffer[16];
+        while ((n = q->read(buffer, 16)) > 0) {
+            for (int i=0 ; i<n ; i++) {
+
+                env->SetFloatArrayRegion(mScratch, 0, 16, buffer[i].data);
+
+                env->CallVoidMethod(mReceiverObject,
+                        gSensorEventQueueClassInfo.dispatchSensorEvent,
+                        buffer[i].sensor,
+                        mScratch,
+                        buffer[i].vector.status,
+                        buffer[i].timestamp);
+
+                if (env->ExceptionCheck()) {
+                    ALOGE("Exception dispatching input event.");
+                    return 1;
+                }
+            }
+        }
+        if (n<0 && n != -EAGAIN) {
+            // FIXME: error receiving events, what to do in this case?
+        }
+
+        return 1;
+    }
+};
+
+static jint nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jobject eventQ, jobject msgQ, jfloatArray scratch) {
     SensorManager& mgr(SensorManager::getInstance());
     sp<SensorEventQueue> queue(mgr.createEventQueue());
-    queue->incStrong(clazz);
-    return reinterpret_cast<int>(queue.get());
-}
 
-static void
-sensors_destroy_queue(JNIEnv *env, jclass clazz, jint nativeQueue)
-{
-    sp<SensorEventQueue> queue(reinterpret_cast<SensorEventQueue *>(nativeQueue));
-    if (queue != 0) {
-        queue->decStrong(clazz);
-    }
-}
-
-static jboolean
-sensors_enable_sensor(JNIEnv *env, jclass clazz,
-        jint nativeQueue, jstring name, jint sensor, jint delay)
-{
-    sp<SensorEventQueue> queue(reinterpret_cast<SensorEventQueue *>(nativeQueue));
-    if (queue == 0) return JNI_FALSE;
-    status_t res;
-    if (delay >= 0) {
-        res = queue->enableSensor(sensor, delay);
-    } else {
-        res = queue->disableSensor(sensor);
-    }
-    return res == NO_ERROR ? true : false;
-}
-
-static jint
-sensors_data_poll(JNIEnv *env, jclass clazz, jint nativeQueue,
-        jfloatArray values, jintArray status, jlongArray timestamp)
-{
-    sp<SensorEventQueue> queue(reinterpret_cast<SensorEventQueue *>(nativeQueue));
-    if (queue == 0) return -1;
-
-    status_t res;
-    ASensorEvent event;
-
-    res = queue->read(&event, 1);
-    if (res == 0) {
-        res = queue->waitForEvent();
-        if (res != NO_ERROR)
-            return -1;
-        // here we're guaranteed to have an event
-        res = queue->read(&event, 1);
-        ALOGE_IF(res==0, "sensors_data_poll: nothing to read after waitForEvent()");
-    }
-    if (res <= 0) {
-        return -1;
+    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);
+    if (messageQueue == NULL) {
+        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
+        return 0;
     }
 
-    jint accuracy = event.vector.status;
-    env->SetFloatArrayRegion(values, 0, 3, event.vector.v);
-    env->SetIntArrayRegion(status, 0, 1, &accuracy);
-    env->SetLongArrayRegion(timestamp, 0, 1, &event.timestamp);
-
-    return event.sensor;
+    sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQ, scratch);
+    receiver->incStrong(clazz);
+    return jint(receiver.get());
 }
 
-static void
-nativeClassInit (JNIEnv *_env, jclass _this)
-{
-    jclass sensorClass = _env->FindClass("android/hardware/Sensor");
-    SensorOffsets& sensorOffsets = gSensorOffsets;
-    sensorOffsets.name        = _env->GetFieldID(sensorClass, "mName",      "Ljava/lang/String;");
-    sensorOffsets.vendor      = _env->GetFieldID(sensorClass, "mVendor",    "Ljava/lang/String;");
-    sensorOffsets.version     = _env->GetFieldID(sensorClass, "mVersion",   "I");
-    sensorOffsets.handle      = _env->GetFieldID(sensorClass, "mHandle",    "I");
-    sensorOffsets.type        = _env->GetFieldID(sensorClass, "mType",      "I");
-    sensorOffsets.range       = _env->GetFieldID(sensorClass, "mMaxRange",  "F");
-    sensorOffsets.resolution  = _env->GetFieldID(sensorClass, "mResolution","F");
-    sensorOffsets.power       = _env->GetFieldID(sensorClass, "mPower",     "F");
-    sensorOffsets.minDelay    = _env->GetFieldID(sensorClass, "mMinDelay",  "I");
+static jint nativeEnableSensor(JNIEnv *env, jclass clazz, jint eventQ, jint handle, jint us) {
+    sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
+    return receiver->getSensorEventQueue()->enableSensor(handle, us);
 }
 
-static JNINativeMethod gMethods[] = {
-    {"nativeClassInit", "()V",              (void*)nativeClassInit },
-    {"sensors_module_init","()I",           (void*)sensors_module_init },
-    {"sensors_module_get_next_sensor","(Landroid/hardware/Sensor;I)I",
-                                            (void*)sensors_module_get_next_sensor },
+static jint nativeDisableSensor(JNIEnv *env, jclass clazz, jint eventQ, jint handle) {
+    sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
+    return receiver->getSensorEventQueue()->disableSensor(handle);
+}
 
-    {"sensors_create_queue",  "()I",        (void*)sensors_create_queue },
-    {"sensors_destroy_queue", "(I)V",       (void*)sensors_destroy_queue },
-    {"sensors_enable_sensor", "(ILjava/lang/String;II)Z",
-                                            (void*)sensors_enable_sensor },
+static void nativeDestroySensorEventQueue(JNIEnv *env, jclass clazz, jint eventQ, jint handle) {
+    sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
+    receiver->destroy();
+    receiver->decStrong(clazz);
+}
 
-    {"sensors_data_poll",  "(I[F[I[J)I",     (void*)sensors_data_poll },
+
+//----------------------------------------------------------------------------
+
+static JNINativeMethod gSystemSensorManagerMethods[] = {
+    {"nativeClassInit",
+            "()V",
+            (void*)nativeClassInit },
+
+    {"nativeGetNextSensor",
+            "(Landroid/hardware/Sensor;I)I",
+            (void*)nativeGetNextSensor },
+};
+
+static JNINativeMethod gSensorEventQueueMethods[] = {
+    {"nativeInitSensorEventQueue",
+            "(Landroid/hardware/SystemSensorManager$SensorEventQueue;Landroid/os/MessageQueue;[F)I",
+            (void*)nativeInitSensorEventQueue },
+
+    {"nativeEnableSensor",
+            "(III)I",
+            (void*)nativeEnableSensor },
+
+    {"nativeDisableSensor",
+            "(II)I",
+            (void*)nativeDisableSensor },
+
+    {"nativeDestroySensorEventQueue",
+            "(I)V",
+            (void*)nativeDestroySensorEventQueue },
 };
 
 }; // namespace android
 
 using namespace android;
 
+#define FIND_CLASS(var, className) \
+        var = env->FindClass(className); \
+        LOG_FATAL_IF(! var, "Unable to find class " className); \
+        var = jclass(env->NewGlobalRef(var));
+
+#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
+        var = env->GetMethodID(clazz, methodName, methodDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find method " methodName);
+
 int register_android_hardware_SensorManager(JNIEnv *env)
 {
-    return jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager",
-            gMethods, NELEM(gMethods));
+    jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager",
+            gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods));
+
+    jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager$SensorEventQueue",
+            gSensorEventQueueMethods, NELEM(gSensorEventQueueMethods));
+
+    FIND_CLASS(gSensorEventQueueClassInfo.clazz, "android/hardware/SystemSensorManager$SensorEventQueue");
+
+    GET_METHOD_ID(gSensorEventQueueClassInfo.dispatchSensorEvent,
+            gSensorEventQueueClassInfo.clazz,
+            "dispatchSensorEvent", "(I[FIJ)V");
+
+    return 0;
 }
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 33ed0b9..895a0dc 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -269,8 +269,7 @@
 // ----------------------------------------------------------------------------
 
 static bool android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject clazz,
-        OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
-        SkCanvas::EdgeType edge) {
+        OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom) {
     return renderer->quickReject(left, top, right, bottom);
 }
 
@@ -981,7 +980,7 @@
     { "nSaveLayerAlpha",    "(IFFFFII)I",      (void*) android_view_GLES20Canvas_saveLayerAlpha },
     { "nSaveLayerAlpha",    "(III)I",          (void*) android_view_GLES20Canvas_saveLayerAlphaClip },
 
-    { "nQuickReject",       "(IFFFFI)Z",       (void*) android_view_GLES20Canvas_quickReject },
+    { "nQuickReject",       "(IFFFF)Z",        (void*) android_view_GLES20Canvas_quickReject },
     { "nClipRect",          "(IFFFFI)Z",       (void*) android_view_GLES20Canvas_clipRectF },
     { "nClipRect",          "(IIIIII)Z",       (void*) android_view_GLES20Canvas_clipRect },
     { "nClipPath",          "(III)Z",          (void*) android_view_GLES20Canvas_clipPath },
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 1f15370..ed92e43 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -66,7 +66,6 @@
     jfieldID mNativeSurfaceControl;
     jfieldID mGenerationId;
     jfieldID mCanvas;
-    jfieldID mCanvasSaveCount;
     jmethodID ctor;
 } gSurfaceClassInfo;
 
@@ -78,11 +77,16 @@
 } gRectClassInfo;
 
 static struct {
+    jfieldID mFinalizer;
     jfieldID mNativeCanvas;
     jfieldID mSurfaceFormat;
 } gCanvasClassInfo;
 
 static struct {
+    jfieldID mNativeCanvas;
+} gCanvasFinalizerClassInfo;
+
+static struct {
     jfieldID width;
     jfieldID height;
     jfieldID refreshRate;
@@ -135,6 +139,7 @@
         return mScreenshot.getFormat();
     }
 
+    SK_DECLARE_UNFLATTENABLE_OBJECT()
 protected:
     // overrides from SkPixelRef
     virtual void* onLockPixels(SkColorTable** ct) {
@@ -373,6 +378,15 @@
     }
 }
 
+static inline void swapCanvasPtr(JNIEnv* env, jobject canvasObj, SkCanvas* newCanvas) {
+  jobject canvasFinalizerObj = env->GetObjectField(canvasObj, gCanvasClassInfo.mFinalizer);
+  SkCanvas* previousCanvas = reinterpret_cast<SkCanvas*>(
+          env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas));
+  env->SetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas, (int)newCanvas);
+  env->SetIntField(canvasFinalizerObj, gCanvasFinalizerClassInfo.mNativeCanvas, (int)newCanvas);
+  SkSafeUnref(previousCanvas);
+}
+
 static jobject nativeLockCanvas(JNIEnv* env, jobject surfaceObj, jobject dirtyRectObj) {
     sp<Surface> surface(getSurface(env, surfaceObj));
     if (!Surface::isValid(surface)) {
@@ -409,8 +423,6 @@
     jobject canvasObj = env->GetObjectField(surfaceObj, gSurfaceClassInfo.mCanvas);
     env->SetIntField(canvasObj, gCanvasClassInfo.mSurfaceFormat, info.format);
 
-    SkCanvas* nativeCanvas = reinterpret_cast<SkCanvas*>(
-            env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas));
     SkBitmap bitmap;
     ssize_t bpr = info.s * bytesPerPixel(info.format);
     bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr);
@@ -423,7 +435,9 @@
         // be safe with an empty bitmap.
         bitmap.setPixels(NULL);
     }
-    nativeCanvas->setBitmapDevice(bitmap);
+
+    SkCanvas* nativeCanvas = SkNEW_ARGS(SkCanvas, (bitmap));
+    swapCanvasPtr(env, canvasObj, nativeCanvas);
 
     SkRegion clipReg;
     if (dirtyRegion.isRect()) { // very common case
@@ -440,9 +454,6 @@
 
     nativeCanvas->clipRegion(clipReg);
 
-    int saveCount = nativeCanvas->save();
-    env->SetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount, saveCount);
-
     if (dirtyRectObj) {
         const Rect& bounds(dirtyRegion.getBounds());
         env->SetIntField(dirtyRectObj, gRectClassInfo.left, bounds.left);
@@ -467,12 +478,8 @@
     }
 
     // detach the canvas from the surface
-    SkCanvas* nativeCanvas = reinterpret_cast<SkCanvas*>(
-            env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas));
-    int saveCount = env->GetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount);
-    nativeCanvas->restoreToCount(saveCount);
-    nativeCanvas->setBitmapDevice(SkBitmap());
-    env->SetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount, 0);
+    SkCanvas* nativeCanvas = SkNEW(SkCanvas);
+    swapCanvasPtr(env, canvasObj, nativeCanvas);
 
     // unlock surface
     status_t err = surface->unlockAndPost();
@@ -888,14 +895,16 @@
             env->GetFieldID(gSurfaceClassInfo.clazz, "mGenerationId", "I");
     gSurfaceClassInfo.mCanvas =
             env->GetFieldID(gSurfaceClassInfo.clazz, "mCanvas", "Landroid/graphics/Canvas;");
-    gSurfaceClassInfo.mCanvasSaveCount =
-            env->GetFieldID(gSurfaceClassInfo.clazz, "mCanvasSaveCount", "I");
     gSurfaceClassInfo.ctor = env->GetMethodID(gSurfaceClassInfo.clazz, "<init>", "()V");
 
     clazz = env->FindClass("android/graphics/Canvas");
+    gCanvasClassInfo.mFinalizer = env->GetFieldID(clazz, "mFinalizer", "Landroid/graphics/Canvas$CanvasFinalizer;");
     gCanvasClassInfo.mNativeCanvas = env->GetFieldID(clazz, "mNativeCanvas", "I");
     gCanvasClassInfo.mSurfaceFormat = env->GetFieldID(clazz, "mSurfaceFormat", "I");
 
+    clazz = env->FindClass("android/graphics/Canvas$CanvasFinalizer");
+    gCanvasFinalizerClassInfo.mNativeCanvas = env->GetFieldID(clazz, "mNativeCanvas", "I");
+
     clazz = env->FindClass("android/graphics/Rect");
     gRectClassInfo.left = env->GetFieldID(clazz, "left", "I");
     gRectClassInfo.top = env->GetFieldID(clazz, "top", "I");
diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp
index 87b312f..64cbda3 100644
--- a/core/jni/android_view_TextureView.cpp
+++ b/core/jni/android_view_TextureView.cpp
@@ -43,11 +43,16 @@
 } gRectClassInfo;
 
 static struct {
-    jfieldID nativeCanvas;
-    jfieldID surfaceFormat;
+    jfieldID mFinalizer;
+    jfieldID mNativeCanvas;
+    jfieldID mSurfaceFormat;
 } gCanvasClassInfo;
 
 static struct {
+    jfieldID mNativeCanvas;
+} gCanvasFinalizerClassInfo;
+
+static struct {
     jfieldID nativeWindow;
 } gTextureViewClassInfo;
 
@@ -120,6 +125,15 @@
     }
 }
 
+static inline void swapCanvasPtr(JNIEnv* env, jobject canvasObj, SkCanvas* newCanvas) {
+  jobject canvasFinalizerObj = env->GetObjectField(canvasObj, gCanvasClassInfo.mFinalizer);
+  SkCanvas* previousCanvas = reinterpret_cast<SkCanvas*>(
+          env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas));
+  env->SetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas, (int)newCanvas);
+  env->SetIntField(canvasFinalizerObj, gCanvasFinalizerClassInfo.mNativeCanvas, (int)newCanvas);
+  SkSafeUnref(previousCanvas);
+}
+
 static void android_view_TextureView_lockCanvas(JNIEnv* env, jobject,
         jint nativeWindow, jobject canvas, jobject dirtyRect) {
 
@@ -157,9 +171,10 @@
         bitmap.setPixels(NULL);
     }
 
-    SET_INT(canvas, gCanvasClassInfo.surfaceFormat, buffer.format);
-    SkCanvas* nativeCanvas = (SkCanvas*) GET_INT(canvas, gCanvasClassInfo.nativeCanvas);
-    nativeCanvas->setBitmapDevice(bitmap);
+    SET_INT(canvas, gCanvasClassInfo.mSurfaceFormat, buffer.format);
+
+    SkCanvas* nativeCanvas = SkNEW_ARGS(SkCanvas, (bitmap));
+    swapCanvasPtr(env, canvas, nativeCanvas);
 
     SkRect clipRect;
     clipRect.set(rect.left, rect.top, rect.right, rect.bottom);
@@ -174,8 +189,8 @@
 static void android_view_TextureView_unlockCanvasAndPost(JNIEnv* env, jobject,
         jint nativeWindow, jobject canvas) {
 
-    SkCanvas* nativeCanvas = (SkCanvas*) GET_INT(canvas, gCanvasClassInfo.nativeCanvas);
-    nativeCanvas->setBitmapDevice(SkBitmap());
+    SkCanvas* nativeCanvas = SkNEW(SkCanvas);
+    swapCanvasPtr(env, canvas, nativeCanvas);
 
     if (nativeWindow) {
         sp<ANativeWindow> window((ANativeWindow*) nativeWindow);
@@ -226,8 +241,12 @@
     GET_FIELD_ID(gRectClassInfo.bottom, clazz, "bottom", "I");
 
     FIND_CLASS(clazz, "android/graphics/Canvas");
-    GET_FIELD_ID(gCanvasClassInfo.nativeCanvas, clazz, "mNativeCanvas", "I");
-    GET_FIELD_ID(gCanvasClassInfo.surfaceFormat, clazz, "mSurfaceFormat", "I");
+    GET_FIELD_ID(gCanvasClassInfo.mFinalizer, clazz, "mFinalizer", "Landroid/graphics/Canvas$CanvasFinalizer;");
+    GET_FIELD_ID(gCanvasClassInfo.mNativeCanvas, clazz, "mNativeCanvas", "I");
+    GET_FIELD_ID(gCanvasClassInfo.mSurfaceFormat, clazz, "mSurfaceFormat", "I");
+
+    FIND_CLASS(clazz, "android/graphics/Canvas$CanvasFinalizer");
+    GET_FIELD_ID(gCanvasFinalizerClassInfo.mNativeCanvas, clazz, "mNativeCanvas", "I");
 
     FIND_CLASS(clazz, "android/view/TextureView");
     GET_FIELD_ID(gTextureViewClassInfo.nativeWindow, clazz, "mNativeWindow", "I");
diff --git a/docs/html/about/versions/android-3.0.jd b/docs/html/about/versions/android-3.0.jd
index 68ac03a..d0b41d3 100644
--- a/docs/html/about/versions/android-3.0.jd
+++ b/docs/html/about/versions/android-3.0.jd
@@ -571,7 +571,7 @@
 can accelerate graphics operations and data processing. Renderscript is an ideal way to create
 high-performance 3D effects for applications, wallpapers, carousels, and more.</p>
 <p>For more information, see the <a
-href="{@docRoot}guide/topics/graphics/renderscript.html">3D Rendering and Computation with
+href="{@docRoot}guide/topics/renderscript/index.html">3D Rendering and Computation with
 Renderscript</a> documentation.</p></li>
 </ul>
 
diff --git a/docs/html/google/play-services/auth.jd b/docs/html/google/play-services/auth.jd
index 3f46c3f..8e11131 100644
--- a/docs/html/google/play-services/auth.jd
+++ b/docs/html/google/play-services/auth.jd
@@ -57,7 +57,12 @@
 </pre>
 <h2 id="obtain">Obtaining an Access Token</h2>
 <p>
-  With an email address, you can now obtain an access token. There are two general
+  With an email address and the service scope you can now obtain an access token.
+</p>
+<p class="note"><strong>Note:</strong> Specify <code>"oauth2:<em>scope</em>"</code> for a single scope or
+  <code>"oauth2:<em>scope1</em> <em>scope2</em> <em>scope3</em>"</code> for multiple scopes.</p>
+
+There are two general
   ways to get a token:</p>
 
     <ul>
@@ -73,6 +78,7 @@
 
     <h3>Using getToken()</h3>
     The following code snippet obtains an access token with an email address, the scope that you want to use for the service, and a {@link android.content.Context}:
+
 <pre>
 HelloActivity mActivity;
 String mEmail;
diff --git a/docs/html/sitemap.txt b/docs/html/sitemap.txt
index 3248b7d..105f60d 100644
--- a/docs/html/sitemap.txt
+++ b/docs/html/sitemap.txt
@@ -2611,7 +2611,7 @@
 http://developer.android.com/reference/android/support/v4/view/PagerTabStrip.html
 http://developer.android.com/reference/android/support/v4/view/PagerTitleStrip.html
 http://developer.android.com/reference/android/renderscript/RSSurfaceView.html
-http://developer.android.com/guide/topics/graphics/renderscript.html
+http://developer.android.com/guide/topics/renderscript/index.html
 http://developer.android.com/reference/android/renderscript/RSTextureView.html
 http://developer.android.com/reference/android/appwidget/AppWidgetHost.html
 http://developer.android.com/reference/javax/xml/XMLConstants.html
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 3949afd..483d11a 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -37,8 +37,8 @@
  * Canvas and Drawables</a> developer guide.</p></div>
  */
 public class Canvas {
-    // assigned in constructors, freed in finalizer
-    final int mNativeCanvas;
+    // assigned in constructors or setBitmap, freed in finalizer
+    int mNativeCanvas;
     
     // may be null
     private Bitmap mBitmap;
@@ -83,7 +83,7 @@
     private final CanvasFinalizer mFinalizer;
 
     private static class CanvasFinalizer {
-        private final int mNativeCanvas;
+        private int mNativeCanvas;
 
         public CanvasFinalizer(int nativeCanvas) {
             mNativeCanvas = nativeCanvas;
@@ -143,6 +143,17 @@
     }
 
     /**
+     * Replace existing canvas while ensuring that the swap has occurred before
+     * the previous native canvas is unreferenced.
+     */
+    private void safeCanvasSwap(int nativeCanvas) {
+        final int oldCanvas = mNativeCanvas;
+        mNativeCanvas = nativeCanvas;
+        mFinalizer.mNativeCanvas = nativeCanvas;
+        finalizer(oldCanvas);
+    }
+    
+    /**
      * Returns null.
      * 
      * @deprecated This method is not supported and should not be invoked.
@@ -168,11 +179,11 @@
     }
 
     /**
-     * Specify a bitmap for the canvas to draw into.  As a side-effect, also
-     * updates the canvas's target density to match that of the bitmap.
+     * Specify a bitmap for the canvas to draw into. As a side-effect, the
+     * canvas' target density is updated to match that of the bitmap while all
+     * other state such as the layers, filters, matrix, and clip are reset.
      *
      * @param bitmap Specifies a mutable bitmap for the canvas to draw into.
-     * 
      * @see #setDensity(int)
      * @see #getDensity()
      */
@@ -181,17 +192,19 @@
             throw new RuntimeException("Can't set a bitmap device on a GL canvas");
         }
 
-        int pointer = 0;
-        if (bitmap != null) {
+        if (bitmap == null) {
+            safeCanvasSwap(initRaster(0));
+            mDensity = Bitmap.DENSITY_NONE;
+        } else {
             if (!bitmap.isMutable()) {
                 throw new IllegalStateException();
             }
             throwIfRecycled(bitmap);
+
+            safeCanvasSwap(initRaster(bitmap.ni()));
             mDensity = bitmap.mDensity;
-            pointer = bitmap.ni();
         }
 
-        native_setBitmap(mNativeCanvas, pointer);
         mBitmap = bitmap;
     }
     
@@ -706,7 +719,7 @@
      *              does not intersect with the canvas' clip
      */
     public boolean quickReject(RectF rect, EdgeType type) {
-        return native_quickReject(mNativeCanvas, rect, type.nativeInt);
+        return native_quickReject(mNativeCanvas, rect);
     }
 
     /**
@@ -726,7 +739,7 @@
      *                    does not intersect with the canvas' clip
      */
     public boolean quickReject(Path path, EdgeType type) {
-        return native_quickReject(mNativeCanvas, path.ni(), type.nativeInt);
+        return native_quickReject(mNativeCanvas, path.ni());
     }
 
     /**
@@ -749,9 +762,9 @@
      * @return            true if the rect (transformed by the canvas' matrix)
      *                    does not intersect with the canvas' clip
      */
-    public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) {
-        return native_quickReject(mNativeCanvas, left, top, right, bottom,
-                                  type.nativeInt);
+    public boolean quickReject(float left, float top, float right, float bottom,
+                               EdgeType type) {
+        return native_quickReject(mNativeCanvas, left, top, right, bottom);
     }
 
     /**
@@ -1625,7 +1638,6 @@
     public static native void freeTextLayoutCaches();
 
     private static native int initRaster(int nativeBitmapOrZero);
-    private static native void native_setBitmap(int nativeCanvas, int bitmap);
     private static native int native_saveLayer(int nativeCanvas, RectF bounds,
                                                int paint, int layerFlags);
     private static native int native_saveLayer(int nativeCanvas, float l,
@@ -1656,15 +1668,12 @@
                                                        Rect bounds);
     private static native void native_getCTM(int canvas, int matrix);
     private static native boolean native_quickReject(int nativeCanvas,
-                                                     RectF rect,
-                                                     int native_edgeType);
+                                                     RectF rect);
     private static native boolean native_quickReject(int nativeCanvas,
-                                                     int path,
-                                                     int native_edgeType);
+                                                     int path);
     private static native boolean native_quickReject(int nativeCanvas,
                                                      float left, float top,
-                                                     float right, float bottom,
-                                                     int native_edgeType);
+                                                     float right, float bottom);
     private static native void native_drawRGB(int nativeCanvas, int r, int g,
                                               int b);
     private static native void native_drawARGB(int nativeCanvas, int a, int r,
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index f6b5ffc..157c7d1 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -375,9 +375,9 @@
      */
     public enum Direction {
         /** clockwise */
-        CW  (0),    // must match enum in SkPath.h
+        CW  (1),    // must match enum in SkPath.h
         /** counter-clockwise */
-        CCW (1);    // must match enum in SkPath.h
+        CCW (2);    // must match enum in SkPath.h
         
         Direction(int ni) {
             nativeInt = ni;
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 4487a3c..c68c9f7 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -225,16 +225,4 @@
     private static native int  nativeGetStyle(int native_instance);
     private static native int  nativeCreateFromAsset(AssetManager mgr, String path);
     private static native int nativeCreateFromFile(String path);
-
-    /**
-     * Set the global gamma coefficients for black and white text. This call is
-     * usually a no-op in shipping products, and only exists for testing during
-     * development.
-     *
-     * @param blackGamma gamma coefficient for black text
-     * @param whiteGamma gamma coefficient for white text
-     *
-     * @hide - this is just for calibrating devices, not for normal apps
-     */
-    public static native void setGammaForText(float blackGamma, float whiteGamma);
 }
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 5e9872f..ea02a17 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -67,7 +67,7 @@
  * <div class="special reference">
  * <h3>Developer Guides</h3>
  * <p>For more information about creating an application that uses Renderscript, read the
- * <a href="{@docRoot}guide/topics/graphics/renderscript.html">Renderscript</a> developer guide.</p>
+ * <a href="{@docRoot}guide/topics/renderscript/index.html">Renderscript</a> developer guide.</p>
  * </div>
  **/
 public class Allocation extends BaseObj {
diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java
index 20e716c..a79ce17 100644
--- a/graphics/java/android/renderscript/Element.java
+++ b/graphics/java/android/renderscript/Element.java
@@ -44,7 +44,7 @@
  * <div class="special reference">
  * <h3>Developer Guides</h3>
  * <p>For more information about creating an application that uses Renderscript, read the
- * <a href="{@docRoot}guide/topics/graphics/renderscript.html">Renderscript</a> developer guide.</p>
+ * <a href="{@docRoot}guide/topics/renderscript/index.html">Renderscript</a> developer guide.</p>
  * </div>
  **/
 public class Element extends BaseObj {
diff --git a/graphics/java/android/renderscript/RSSurfaceView.java b/graphics/java/android/renderscript/RSSurfaceView.java
index 506f1af..82ed95c 100644
--- a/graphics/java/android/renderscript/RSSurfaceView.java
+++ b/graphics/java/android/renderscript/RSSurfaceView.java
@@ -36,7 +36,7 @@
  * <div class="special reference">
  * <h3>Developer Guides</h3>
  * <p>For more information about creating an application that uses Renderscript, read the
- * <a href="{@docRoot}guide/topics/graphics/renderscript.html">Renderscript</a> developer guide.</p>
+ * <a href="{@docRoot}guide/topics/renderscript/index.html">Renderscript</a> developer guide.</p>
  * </div>
  */
 public class RSSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index fa115ff..7518ea8 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -41,7 +41,7 @@
  * <div class="special reference">
  * <h3>Developer Guides</h3>
  * <p>For more information about creating an application that uses Renderscript, read the
- * <a href="{@docRoot}guide/topics/graphics/renderscript.html">Renderscript</a> developer guide.</p>
+ * <a href="{@docRoot}guide/topics/renderscript/index.html">Renderscript</a> developer guide.</p>
  * </div>
  **/
 public class RenderScript {
@@ -947,6 +947,7 @@
                         mRS.mErrorCallback.mErrorNum = subID;
                         mRS.mErrorCallback.run();
                     } else {
+                        android.util.Log.e(LOG_TAG, "non fatal RS error, " + e);
                         // Do not throw here. In these cases, we do not have
                         // a fatal error.
                     }
diff --git a/graphics/java/android/renderscript/RenderScriptGL.java b/graphics/java/android/renderscript/RenderScriptGL.java
index 12c8102..5269405 100644
--- a/graphics/java/android/renderscript/RenderScriptGL.java
+++ b/graphics/java/android/renderscript/RenderScriptGL.java
@@ -39,7 +39,7 @@
  * <div class="special reference">
  * <h3>Developer Guides</h3>
  * <p>For more information about creating an application that uses Renderscript, read the
- * <a href="{@docRoot}guide/topics/graphics/renderscript.html">Renderscript</a> developer guide.</p>
+ * <a href="{@docRoot}guide/topics/renderscript/index.html">Renderscript</a> developer guide.</p>
  * </div>
  **/
 public class RenderScriptGL extends RenderScript {
diff --git a/graphics/java/android/renderscript/Type.java b/graphics/java/android/renderscript/Type.java
index cb12594..d1446f6 100644
--- a/graphics/java/android/renderscript/Type.java
+++ b/graphics/java/android/renderscript/Type.java
@@ -40,7 +40,7 @@
  * <div class="special reference">
  * <h3>Developer Guides</h3>
  * <p>For more information about creating an application that uses Renderscript, read the
- * <a href="{@docRoot}guide/topics/graphics/renderscript.html">Renderscript</a> developer guide.</p>
+ * <a href="{@docRoot}guide/topics/renderscript/index.html">Renderscript</a> developer guide.</p>
  * </div>
  **/
 public class Type extends BaseObj {
diff --git a/graphics/java/android/renderscript/package.html b/graphics/java/android/renderscript/package.html
index 775645f..5eab23c 100644
--- a/graphics/java/android/renderscript/package.html
+++ b/graphics/java/android/renderscript/package.html
@@ -4,7 +4,7 @@
 carrying out mathematical calculations and 3D graphics rendering.</p>
 
 <p>For more information, see the
-<a href="{@docRoot}guide/topics/graphics/renderscript.html">Renderscript</a> developer guide.</p>
+<a href="{@docRoot}guide/topics/renderscript/index.html">Renderscript</a> developer guide.</p>
 {@more}
 
 <p>An example of Renderscript in applications include the 3D carousel view that is present in
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 549edd2..67359ad 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -42,6 +42,7 @@
 		external/skia/include/core \
 		external/skia/include/effects \
 		external/skia/include/images \
+		external/skia/src/core \
 		external/skia/src/ports \
 		external/skia/include/utils
 
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 7e645d2..1a86b3a 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -89,6 +89,9 @@
 
     mFunctorsCount = 0;
 
+    debugLayersUpdates = false;
+    debugOverdraw = false;
+
     mInitialized = true;
 }
 
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index b25288b..f3bd188 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -18,7 +18,8 @@
 #define ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
 
 #include <SkChunkAlloc.h>
-#include <SkFlattenable.h>
+#include <SkReader32.h>
+#include <SkWriter32.h>
 #include <SkMatrix.h>
 #include <SkCamera.h>
 #include <SkPaint.h>
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 97988f7..d8297da 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "OpenGLRenderer"
 
+#include <SkGlyph.h>
 #include <SkUtils.h>
 
 #include <cutils/properties.h>
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index e8a85fd..a580d89 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -23,6 +23,7 @@
 
 #include <ui/Region.h>
 
+#include <SkPaint.h>
 #include <SkXfermode.h>
 
 #include "Rect.h"
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 45569ac..1fdd97d 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -80,7 +80,7 @@
     { SkXfermode::kDstATop_Mode,  GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA },
     { SkXfermode::kXor_Mode,      GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
     { SkXfermode::kPlus_Mode,     GL_ONE,                 GL_ONE },
-    { SkXfermode::kMultiply_Mode, GL_ZERO,                GL_SRC_COLOR },
+    { SkXfermode::kModulate_Mode, GL_ZERO,                GL_SRC_COLOR },
     { SkXfermode::kScreen_Mode,   GL_ONE,                 GL_ONE_MINUS_SRC_COLOR }
 };
 
@@ -101,7 +101,7 @@
     { SkXfermode::kDstATop_Mode,  GL_DST_ALPHA,           GL_ONE_MINUS_SRC_ALPHA },
     { SkXfermode::kXor_Mode,      GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA },
     { SkXfermode::kPlus_Mode,     GL_ONE,                 GL_ONE },
-    { SkXfermode::kMultiply_Mode, GL_DST_COLOR,           GL_ZERO },
+    { SkXfermode::kModulate_Mode, GL_DST_COLOR,           GL_ZERO },
     { SkXfermode::kScreen_Mode,   GL_ONE_MINUS_DST_COLOR, GL_ONE }
 };
 
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index 22c7dde..87ed825 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -184,6 +184,7 @@
 
 void Snapshot::resetClip(float left, float top, float right, float bottom) {
     clipRect = &mClipRectRoot;
+    clipRegion = &mClipRegionRoot;
     setClip(left, top, right, bottom);
 }
 
diff --git a/libs/hwui/font/CacheTexture.cpp b/libs/hwui/font/CacheTexture.cpp
index f653592..24b0523 100644
--- a/libs/hwui/font/CacheTexture.cpp
+++ b/libs/hwui/font/CacheTexture.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <SkGlyph.h>
 #include <utils/Log.h>
 
 #include "Debug.h"
diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp
index 128e8b8..1afcb46 100644
--- a/libs/hwui/font/Font.cpp
+++ b/libs/hwui/font/Font.cpp
@@ -20,6 +20,7 @@
 
 #include <utils/JenkinsHash.h>
 
+#include <SkGlyph.h>
 #include <SkUtils.h>
 
 #include "Debug.h"
diff --git a/media/tests/omxjpegdecoder/SkOmxPixelRef.h b/media/tests/omxjpegdecoder/SkOmxPixelRef.h
index afedcbd..374604c 100644
--- a/media/tests/omxjpegdecoder/SkOmxPixelRef.h
+++ b/media/tests/omxjpegdecoder/SkOmxPixelRef.h
@@ -33,6 +33,7 @@
      //! Return the allocation size for the pixels
     size_t getSize() const { return mSize; }
 
+    SK_DECLARE_UNFLATTENABLE_OBJECT()
 protected:
     // overrides from SkPixelRef
     virtual void* onLockPixels(SkColorTable**);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 36ef6e8..45319a8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -23,6 +23,7 @@
 import java.util.concurrent.atomic.AtomicInteger;
 
 import android.app.ActivityManager;
+import android.app.AppOpsManager;
 import android.app.backup.BackupManager;
 import android.content.BroadcastReceiver;
 import android.content.ContentProvider;
@@ -323,6 +324,7 @@
         mBackupManager = new BackupManager(getContext());
         mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
 
+        setAppOps(AppOpsManager.OP_NONE, AppOpsManager.OP_WRITE_SETTINGS);
         establishDbTracking(UserHandle.USER_OWNER);
 
         IntentFilter userFilter = new IntentFilter();
@@ -544,7 +546,8 @@
      * Fast path that avoids the use of chatty remoted Cursors.
      */
     @Override
-    public Bundle call(String method, String request, Bundle args) {
+    public Bundle callFromPackage(String callingPackage, String method, String request,
+            Bundle args) {
         int callingUser = UserHandle.getCallingUserId();
         if (args != null) {
             int reqUser = args.getInt(Settings.CALL_METHOD_USER_KEY, callingUser);
@@ -586,7 +589,22 @@
         // Put methods - new value is in the args bundle under the key named by
         // the Settings.NameValueTable.VALUE static.
         final String newValue = (args == null)
-        ? null : args.getString(Settings.NameValueTable.VALUE);
+                ? null : args.getString(Settings.NameValueTable.VALUE);
+
+        // Framework can't do automatic permission checking for calls, so we need
+        // to do it here.
+        if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException(
+                    String.format("Permission denial: writing to settings requires %1$s",
+                                  android.Manifest.permission.WRITE_SETTINGS));
+        }
+
+        // Also need to take care of app op.
+        if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SETTINGS, Binder.getCallingUid(),
+                callingPackage) != AppOpsManager.MODE_ALLOWED) {
+            return null;
+        }
 
         final ContentValues values = new ContentValues();
         values.put(Settings.NameValueTable.NAME, request);
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 48edc73..c40e26d 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -189,7 +189,7 @@
     <string name="quick_settings_location_label" msgid="3292451598267467545">"الموقع المستخدم"</string>
     <string name="quick_settings_media_device_label" msgid="1302906836372603762">"جهاز الوسائط"</string>
     <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
-    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"مكالمات طوارئ فقط"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"مكالمات الطوارئ فقط"</string>
     <string name="quick_settings_settings_label" msgid="5326556592578065401">"الإعدادات"</string>
     <string name="quick_settings_time_label" msgid="4635969182239736408">"الوقت"</string>
     <string name="quick_settings_user_label" msgid="5238995632130897840">"أنا"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 580bfe7..8c2dd8e 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -147,7 +147,7 @@
     <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Mode silenci."</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"S\'ha omès <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notificació omesa."</string>
-    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Àrea de notificacions"</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Capa de notificació."</string>
     <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Configuració ràpida."</string>
     <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Aplicacions recents."</string>
     <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Usuari <xliff:g id="USER">%s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 0789b29..d619de1 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -133,7 +133,7 @@
     <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"No hay tarjeta SIM."</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Conexión mediante Bluetooth"</string>
-    <string name="accessibility_airplane_mode" msgid="834748999790763092">"Modo avión"</string>
+    <string name="accessibility_airplane_mode" msgid="834748999790763092">"Modo de avión"</string>
     <!-- String.format failed for translation -->
     <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
     <skip />
@@ -154,7 +154,7 @@
     <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
     <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Móvil <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Batería <xliff:g id="STATE">%s</xliff:g>"</string>
-    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Modo avión <xliff:g id="STATE">%s</xliff:g>"</string>
+    <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Modo de avión <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>"</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarma: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Datos de 2G-3G inhabilitados"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index fff1aa0..c454bb1 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -157,14 +157,14 @@
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm ustawiony na <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Wyłączono transmisję danych 2G/3G"</string>
     <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Wyłączono transmisję danych 4G"</string>
-    <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Transmisja danych została wyłączona"</string>
+    <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Wyłączono komórkową transmisję danych"</string>
     <string name="data_usage_disabled_dialog_title" msgid="2086815304858964954">"Wyłączono transmisję danych"</string>
-    <string name="data_usage_disabled_dialog" msgid="3853117269051806280">"Ustawiony limit transmisji danych został osiągnięty."\n\n"Jeśli ponownie włączysz przesyłanie danych, operator może naliczyć dodatkowe opłaty."</string>
+    <string name="data_usage_disabled_dialog" msgid="3853117269051806280">"Osiągnięto określony limit wykorzystania transmisji danych."\n\n"Jeśli ponownie włączysz przesyłanie danych, operator może naliczyć opłaty."</string>
     <string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"Włącz transmisję danych"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Brak internetu"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: połączono"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Wyszukiwanie sygnału GPS"</string>
-    <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokalizacja z GPSa"</string>
+    <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokalizacja ustawiona według GPS"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Usuń wszystkie powiadomienia."</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"O aplikacji"</string>
     <string name="close_universe" msgid="3736513750241754348">"Zamknij"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 3d0ddd4..ccf4fd48 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -77,7 +77,7 @@
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Установить как камеру (PTP)"</string>
     <string name="installer_cd_button_title" msgid="2312667578562201583">"Установить приложение"</string>
     <string name="accessibility_back" msgid="567011538994429120">"Назад"</string>
-    <string name="accessibility_home" msgid="8217216074895377641">"Домой"</string>
+    <string name="accessibility_home" msgid="8217216074895377641">"Главная страница"</string>
     <string name="accessibility_menu" msgid="316839303324695949">"Меню"</string>
     <string name="accessibility_recent" msgid="8571350598987952883">"Недавние приложения"</string>
     <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Кнопка переключения способа ввода."</string>
@@ -118,8 +118,8 @@
     <string name="accessibility_two_bars" msgid="6437363648385206679">"два деления"</string>
     <string name="accessibility_three_bars" msgid="2648241415119396648">"три деления"</string>
     <string name="accessibility_signal_full" msgid="9122922886519676839">"надежный сигнал"</string>
-    <string name="accessibility_desc_on" msgid="2385254693624345265">"Вкл."</string>
-    <string name="accessibility_desc_off" msgid="6475508157786853157">"Выкл."</string>
+    <string name="accessibility_desc_on" msgid="2385254693624345265">"ВКЛ"</string>
+    <string name="accessibility_desc_off" msgid="6475508157786853157">"ВЫКЛ"</string>
     <string name="accessibility_desc_connected" msgid="8366256693719499665">"Подключено"</string>
     <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
     <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 7666f7d..91214d1 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -197,8 +197,8 @@
     <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Ej ansluten"</string>
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Inget nätverk"</string>
     <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi är inaktiverat"</string>
-    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Trådlös skärm"</string>
-    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Trådlös skärm"</string>
+    <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi visas"</string>
+    <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Trådlös visning"</string>
     <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Ljusstyrka"</string>
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Meddelanden visas här"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index f43eabe..7750e77 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -35,10 +35,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Поточні"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Сповіщення"</string>
     <string name="battery_low_title" msgid="2783104807551211639">"Підключіть зарядний пристрій"</string>
-    <string name="battery_low_subtitle" msgid="1752040062087829196">"Акумулятор розряджається."</string>
+    <string name="battery_low_subtitle" msgid="1752040062087829196">"Батарея виснажується."</string>
     <string name="battery_low_percent_format" msgid="1077244949318261761">"Залишилося <xliff:g id="NUMBER">%d%%</xliff:g>"</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Заряджання USB не підтримується."\n"Використовуйте лише наданий у комплекті зарядний пристрій."</string>
-    <string name="battery_low_why" msgid="7279169609518386372">"Використання акумулятора"</string>
+    <string name="battery_low_why" msgid="7279169609518386372">"Викор. батареї"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Налаштування"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Режим польоту"</string>
@@ -85,11 +85,11 @@
     <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Збільшення екрана."</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth під’єднано."</string>
     <string name="accessibility_bluetooth_disconnected" msgid="7416648669976870175">"Bluetooth від’єднано."</string>
-    <string name="accessibility_no_battery" msgid="358343022352820946">"Акумулятор розряджений."</string>
-    <string name="accessibility_battery_one_bar" msgid="7774887721891057523">"Заряд акумулятора: одна смужка."</string>
-    <string name="accessibility_battery_two_bars" msgid="8500650438735009973">"Заряд акумулятора: дві смужки."</string>
-    <string name="accessibility_battery_three_bars" msgid="2302983330865040446">"Заряд акумулятора: три смужки."</string>
-    <string name="accessibility_battery_full" msgid="8909122401720158582">"Акумулятор заряджений."</string>
+    <string name="accessibility_no_battery" msgid="358343022352820946">"Немає заряду батареї."</string>
+    <string name="accessibility_battery_one_bar" msgid="7774887721891057523">"Одна смужка заряду батареї."</string>
+    <string name="accessibility_battery_two_bars" msgid="8500650438735009973">"Дві смужки заряду батареї."</string>
+    <string name="accessibility_battery_three_bars" msgid="2302983330865040446">"Три смужки заряду батареї."</string>
+    <string name="accessibility_battery_full" msgid="8909122401720158582">"Повний заряд батареї"</string>
     <string name="accessibility_no_phone" msgid="4894708937052611281">"Немає сигналу телефону."</string>
     <string name="accessibility_phone_one_bar" msgid="687699278132664115">"Одна смужка сигналу телефону."</string>
     <string name="accessibility_phone_two_bars" msgid="8384905382804815201">"Дві смужки сигналу телефону."</string>
@@ -134,7 +134,7 @@
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Немає SIM-карти."</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Прив’язка Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Режим польоту."</string>
-    <string name="accessibility_battery_level" msgid="7451474187113371965">"Заряд акумулятора: <xliff:g id="NUMBER">%d</xliff:g>."</string>
+    <string name="accessibility_battery_level" msgid="7451474187113371965">"Відсотків батареї: <xliff:g id="NUMBER">%d</xliff:g>."</string>
     <string name="accessibility_settings_button" msgid="799583911231893380">"Налаштування системи."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Сповіщення."</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Очистити сповіщення."</string>
diff --git a/services/input/SpriteController.cpp b/services/input/SpriteController.cpp
index 1f3d2cf..8163ea0 100644
--- a/services/input/SpriteController.cpp
+++ b/services/input/SpriteController.cpp
@@ -208,8 +208,7 @@
                         surfaceInfo.w, surfaceInfo.h, bpr);
                 surfaceBitmap.setPixels(surfaceInfo.bits);
 
-                SkCanvas surfaceCanvas;
-                surfaceCanvas.setBitmapDevice(surfaceBitmap);
+                SkCanvas surfaceCanvas(surfaceBitmap);
 
                 SkPaint paint;
                 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
diff --git a/services/java/com/android/server/AppOpsService.java b/services/java/com/android/server/AppOpsService.java
index 335917e..748b3cb 100644
--- a/services/java/com/android/server/AppOpsService.java
+++ b/services/java/com/android/server/AppOpsService.java
@@ -204,6 +204,7 @@
     @Override
     public void setMode(int code, int uid, String packageName, int mode) {
         verifyIncomingUid(uid);
+        verifyIncomingOp(code);
         synchronized (this) {
             Op op = getOpLocked(AppOpsManager.opToSwitch(code), uid, packageName, true);
             if (op != null) {
@@ -218,6 +219,7 @@
     @Override
     public int checkOperation(int code, int uid, String packageName) {
         verifyIncomingUid(uid);
+        verifyIncomingOp(code);
         synchronized (this) {
             Op op = getOpLocked(AppOpsManager.opToSwitch(code), uid, packageName, false);
             if (op == null) {
@@ -230,6 +232,7 @@
     @Override
     public int noteOperation(int code, int uid, String packageName) {
         verifyIncomingUid(uid);
+        verifyIncomingOp(code);
         synchronized (this) {
             Ops ops = getOpsLocked(uid, packageName, true);
             if (ops == null) {
@@ -261,6 +264,7 @@
     @Override
     public int startOperation(int code, int uid, String packageName) {
         verifyIncomingUid(uid);
+        verifyIncomingOp(code);
         synchronized (this) {
             Ops ops = getOpsLocked(uid, packageName, true);
             if (ops == null) {
@@ -291,6 +295,7 @@
     @Override
     public void finishOperation(int code, int uid, String packageName) {
         verifyIncomingUid(uid);
+        verifyIncomingOp(code);
         synchronized (this) {
             Op op = getOpLocked(code, uid, packageName, true);
             if (op == null) {
@@ -322,6 +327,13 @@
                 Binder.getCallingPid(), Binder.getCallingUid(), null);
     }
 
+    private void verifyIncomingOp(int op) {
+        if (op >= 0 && op < AppOpsManager._NUM_OP) {
+            return;
+        }
+        throw new IllegalArgumentException("Bad operation #" + op);
+    }
+
     private Ops getOpsLocked(int uid, String packageName, boolean edit) {
         HashMap<String, Ops> pkgOps = mUidOps.get(uid);
         if (pkgOps == null) {
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 62f9965..6bed964 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -667,20 +667,15 @@
         mProvidersByName.remove(provider.getName());
     }
 
-
     /**
-     * Returns "true" if access to the specified location provider is allowed by the current user's
-     * settings. Access to all location providers is forbidden to non-location-provider processes
-     * belonging to background users.
+     * Returns "true" if access to the specified location provider is allowed by the current
+     * user's settings. Access to all location providers is forbidden to non-location-provider
+     * processes belonging to background users.
      *
      * @param provider the name of the location provider
-     * @param uid the requestor's UID
      * @return
      */
-    private boolean isAllowedBySettingsLocked(String provider, int uid) {
-        if (UserHandle.getUserId(uid) != mCurrentUserId && !isUidALocationProvider(uid)) {
-            return false;
-        }
+    private boolean isAllowedByCurrentUserSettingsLocked(String provider) {
         if (mEnabledProviders.contains(provider)) {
             return true;
         }
@@ -694,6 +689,22 @@
     }
 
     /**
+     * Returns "true" if access to the specified location provider is allowed by the specified
+     * user's settings. Access to all location providers is forbidden to non-location-provider
+     * processes belonging to background users.
+     *
+     * @param provider the name of the location provider
+     * @param uid the requestor's UID
+     * @return
+     */
+    private boolean isAllowedByUserSettingsLocked(String provider, int uid) {
+        if (UserHandle.getUserId(uid) != mCurrentUserId && !isUidALocationProvider(uid)) {
+            return false;
+        }
+        return isAllowedByCurrentUserSettingsLocked(provider);
+    }
+
+    /**
      * Returns the permission string associated with the specified resolution level.
      *
      * @param resolutionLevel the resolution level
@@ -882,7 +893,7 @@
                         continue;
                     }
                     if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
-                        if (enabledOnly && !isAllowedBySettingsLocked(name, uid)) {
+                        if (enabledOnly && !isAllowedByUserSettingsLocked(name, uid)) {
                             continue;
                         }
                         if (criteria != null && !LocationProvider.propertiesMeetCriteria(
@@ -958,8 +969,7 @@
             LocationProviderInterface p = mProviders.get(i);
             boolean isEnabled = p.isEnabled();
             String name = p.getName();
-            boolean shouldBeEnabled = isAllowedBySettingsLocked(name,
-                    UserHandle.getUid(mCurrentUserId, 0));
+            boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
             if (isEnabled && !shouldBeEnabled) {
                 updateProviderListenersLocked(name, false, mCurrentUserId);
                 changesMade = true;
@@ -1270,7 +1280,7 @@
             oldRecord.disposeLocked(false);
         }
 
-        boolean isProviderEnabled = isAllowedBySettingsLocked(name, uid);
+        boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid);
         if (isProviderEnabled) {
             applyRequirementsLocked(name);
         } else {
@@ -1327,7 +1337,7 @@
         // update provider
         for (String provider : providers) {
             // If provider is already disabled, don't need to do anything
-            if (!isAllowedBySettingsLocked(provider, UserHandle.getUid(mCurrentUserId, 0))) {
+            if (!isAllowedByCurrentUserSettingsLocked(provider)) {
                 continue;
             }
 
@@ -1368,7 +1378,7 @@
                 LocationProviderInterface provider = mProvidersByName.get(name);
                 if (provider == null) return null;
 
-                if (!isAllowedBySettingsLocked(name, uid)) return null;
+                if (!isAllowedByUserSettingsLocked(name, uid)) return null;
 
                 Location location = mLastLocation.get(name);
                 if (location == null) {
@@ -1449,7 +1459,7 @@
         final int uid = Binder.getCallingUid();
         final long ident = Binder.clearCallingIdentity();
         try {
-            if (checkLocationAccess(uid, packageName, allowedResolutionLevel)) {
+            if (!checkLocationAccess(uid, packageName, allowedResolutionLevel)) {
                 return false;
             }
         } finally {
@@ -1542,13 +1552,14 @@
                 provider);
         if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
 
+        int uid = Binder.getCallingUid();
         long identity = Binder.clearCallingIdentity();
         try {
             synchronized (mLock) {
                 LocationProviderInterface p = mProvidersByName.get(provider);
                 if (p == null) return false;
 
-                return isAllowedBySettingsLocked(provider, UserHandle.getUid(mCurrentUserId, 0));
+                return isAllowedByUserSettingsLocked(provider, uid);
             }
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -1836,13 +1847,12 @@
             myLocation.setIsFromMockProvider(true);
         }
 
-        if (!passive) {
-            // notify passive provider of the new location
-            mPassiveProvider.updateLocation(myLocation);
-        }
-
         synchronized (mLock) {
-            if (isAllowedBySettingsLocked(provider, UserHandle.getUid(mCurrentUserId, 0))) {
+            if (isAllowedByCurrentUserSettingsLocked(provider)) {
+                if (!passive) {
+                    // notify passive provider of the new location
+                    mPassiveProvider.updateLocation(myLocation);
+                }
                 handleLocationChangedLocked(myLocation, passive);
             }
         }
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 44f2d12..1ede6e9 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -7415,9 +7415,7 @@
     }
 
     public void requestBugReport() {
-        // No permission check because this can't do anything harmful --
-        // it will just eventually cause the user to be presented with
-        // a UI to select where the bug report goes.
+        enforceCallingPermission(android.Manifest.permission.DUMP, "requestBugReport");
         SystemProperties.set("ctl.start", "bugreport");
     }
 
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 14d1058..2a9016b 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -168,6 +168,15 @@
         </activity>
 
         <activity
+                android:name="ClipRegion3Activity"
+                android:label="_ClipRegion3">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity
                 android:name="DisplayListLayersActivity"
                 android:label="__DisplayListLayers">
             <intent-filter>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ClipRegion3Activity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ClipRegion3Activity.java
new file mode 100644
index 0000000..6fd03fb
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ClipRegion3Activity.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2010 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.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Path;
+import android.os.Bundle;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class ClipRegion3Activity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        final RegionView group = new RegionView(this);
+
+        final TextView text = new TextView(this);
+        text.setText(buildText());
+        group.addView(text);
+
+        setContentView(group);
+    }
+
+    private static CharSequence buildText() {
+        StringBuffer buffer = new StringBuffer();
+        for (int i = 0; i < 10; i++) {
+            buffer.append(LOREM_IPSUM);
+        }
+        return buffer;
+    }
+
+    public static class RegionView extends FrameLayout {
+        private final Path mClipPath = new Path();
+        private float mClipPosition = 0.5f;
+
+        public RegionView(Context c) {
+            super(c);
+            setAlpha(0.5f);
+        }
+
+        @Override
+        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+            super.onSizeChanged(w, h, oldw, oldh);
+            mClipPath.reset();
+            mClipPath.addCircle(0.0f, 0.0f, getWidth() / 4.0f, Path.Direction.CW);
+        }
+
+        @Override
+        protected void dispatchDraw(Canvas canvas) {
+            canvas.drawARGB(255, 255, 255, 255);
+
+            canvas.save(Canvas.MATRIX_SAVE_FLAG);
+            canvas.translate(mClipPosition * getWidth(), getHeight() / 2.0f);
+            canvas.clipPath(mClipPath);
+            canvas.restore();
+
+            super.dispatchDraw(canvas);
+
+            invalidate();
+        }
+    }
+
+    private static final String LOREM_IPSUM = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sagittis molestie aliquam. Donec metus metus, laoreet nec sagittis vitae, ultricies sit amet eros. Suspendisse sed massa sit amet felis consectetur gravida. In vitae erat mi, in egestas nisl. Phasellus quis ipsum massa, at scelerisque arcu. Nam lectus est, pellentesque eget lacinia non, congue vitae augue. Aliquam erat volutpat. Pellentesque bibendum tincidunt viverra. Aliquam erat volutpat. Maecenas pretium vulputate placerat. Nulla varius elementum rutrum. Aenean mollis blandit imperdiet. Pellentesque interdum fringilla ligula.";
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
index 2414d70..8701cc8 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
@@ -188,11 +188,6 @@
         return delegate.mStyle;
     }
 
-    @LayoutlibDelegate
-    /*package*/ static void setGammaForText(float blackGamma, float whiteGamma) {
-        // This is for device testing only: pass
-    }
-
     // ---- Private delegate/helper methods ----
 
     private Typeface_Delegate(String family, int style) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index e682da7..8b643c0 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -1206,6 +1206,11 @@
     }
 
     @Override
+    public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
+        // pass
+    }
+
+    @Override
     public void sendOrderedBroadcast(Intent arg0, String arg1) {
         // pass
 
@@ -1220,6 +1225,13 @@
     }
 
     @Override
+    public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp,
+            BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
+            String initialData, Bundle initialExtras) {
+        // pass
+    }
+
+    @Override
     public void sendBroadcastAsUser(Intent intent, UserHandle user) {
         // pass
     }
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 9c59f63..ed8b99b 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -1767,9 +1767,6 @@
     private void handleSuccessfulIpConfiguration(DhcpResults dhcpResults) {
         mLastSignalLevel = -1; // force update of signal strength
         mReconnectCount = 0; //Reset IP failure tracking
-        if (dhcpResults.serverAddress == null) {
-            dhcpResults = null;
-        }
         synchronized (mDhcpResultsLock) {
             mDhcpResults = dhcpResults;
         }