Merge "may fix build on some version of gcc"
diff --git a/api/current.txt b/api/current.txt
index acea3e7..569b206 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -259,6 +259,7 @@
     field public static final int borderlessButtonStyle = 16843563; // 0x101032b
     field public static final int bottom = 16843184; // 0x10101b0
     field public static final int bottomBright = 16842957; // 0x10100cd
+    field public static final int bottomChevronDrawable = 16843661; // 0x101038d
     field public static final int bottomDark = 16842953; // 0x10100c9
     field public static final int bottomLeftRadius = 16843179; // 0x10101ab
     field public static final int bottomMedium = 16842958; // 0x10100ce
@@ -425,7 +426,7 @@
     field public static final int fastScrollTextColor = 16843609; // 0x1010359
     field public static final int fastScrollThumbDrawable = 16843574; // 0x1010336
     field public static final int fastScrollTrackDrawable = 16843577; // 0x1010339
-    field public static final int feedbackCount = 16843665; // 0x1010391
+    field public static final int feedbackCount = 16843667; // 0x1010393
     field public static final int fillAfter = 16843197; // 0x10101bd
     field public static final int fillBefore = 16843196; // 0x10101bc
     field public static final int fillEnabled = 16843343; // 0x101024f
@@ -488,12 +489,12 @@
     field public static final int headerDividersEnabled = 16843310; // 0x101022e
     field public static final int height = 16843093; // 0x1010155
     field public static final int hint = 16843088; // 0x1010150
-    field public static final int hitRadius = 16843662; // 0x101038e
+    field public static final int hitRadius = 16843664; // 0x1010390
     field public static final int homeAsUpIndicator = 16843531; // 0x101030b
     field public static final int homeLayout = 16843549; // 0x101031d
     field public static final int horizontalDivider = 16843053; // 0x101012d
     field public static final int horizontalGap = 16843327; // 0x101023f
-    field public static final int horizontalOffset = 16843667; // 0x1010393
+    field public static final int horizontalOffset = 16843669; // 0x1010395
     field public static final int horizontalScrollViewStyle = 16843603; // 0x1010353
     field public static final int horizontalSpacing = 16843028; // 0x1010114
     field public static final int host = 16842792; // 0x1010028
@@ -686,7 +687,7 @@
     field public static final int orderingFromXml = 16843239; // 0x10101e7
     field public static final int orientation = 16842948; // 0x10100c4
     field public static final int outAnimation = 16843128; // 0x1010178
-    field public static final int outerRadius = 16843661; // 0x101038d
+    field public static final int outerRadius = 16843663; // 0x101038f
     field public static final int overScrollFooter = 16843459; // 0x10102c3
     field public static final int overScrollHeader = 16843458; // 0x10102c2
     field public static final int overScrollMode = 16843457; // 0x10102c1
@@ -851,7 +852,7 @@
     field public static final int smallIcon = 16843422; // 0x101029e
     field public static final int smallScreens = 16843396; // 0x1010284
     field public static final int smoothScrollbar = 16843313; // 0x1010231
-    field public static final int snapMargin = 16843664; // 0x1010390
+    field public static final int snapMargin = 16843666; // 0x1010392
     field public static final int soundEffectsEnabled = 16843285; // 0x1010215
     field public static final int spacing = 16843027; // 0x1010113
     field public static final int spinnerDropDownItemStyle = 16842887; // 0x1010087
@@ -1006,6 +1007,7 @@
     field public static final int toYScale = 16843205; // 0x10101c5
     field public static final int top = 16843182; // 0x10101ae
     field public static final int topBright = 16842955; // 0x10100cb
+    field public static final int topChevronDrawable = 16843660; // 0x101038c
     field public static final int topDark = 16842951; // 0x10100c7
     field public static final int topLeftRadius = 16843177; // 0x10101a9
     field public static final int topOffset = 16843352; // 0x1010258
@@ -1035,10 +1037,10 @@
     field public static final int verticalCorrection = 16843322; // 0x101023a
     field public static final int verticalDivider = 16843054; // 0x101012e
     field public static final int verticalGap = 16843328; // 0x1010240
-    field public static final int verticalOffset = 16843666; // 0x1010392
+    field public static final int verticalOffset = 16843668; // 0x1010394
     field public static final int verticalScrollbarPosition = 16843572; // 0x1010334
     field public static final int verticalSpacing = 16843029; // 0x1010115
-    field public static final int vibrationDuration = 16843663; // 0x101038f
+    field public static final int vibrationDuration = 16843665; // 0x1010391
     field public static final int visibility = 16842972; // 0x10100dc
     field public static final int visible = 16843156; // 0x1010194
     field public static final int vmSafeMode = 16843448; // 0x10102b8
@@ -1055,7 +1057,7 @@
     field public static final int wallpaperIntraOpenExitAnimation = 16843416; // 0x1010298
     field public static final int wallpaperOpenEnterAnimation = 16843411; // 0x1010293
     field public static final int wallpaperOpenExitAnimation = 16843412; // 0x1010294
-    field public static final int waveDrawable = 16843660; // 0x101038c
+    field public static final int waveDrawable = 16843662; // 0x101038e
     field public static final int webTextViewStyle = 16843449; // 0x10102b9
     field public static final int webViewStyle = 16842885; // 0x1010085
     field public static final int weekDayTextAppearance = 16843592; // 0x1010348
@@ -17601,7 +17603,7 @@
     method public boolean isSpeaking();
     method public int playEarcon(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>);
     method public int playSilence(long, int, java.util.HashMap<java.lang.String, java.lang.String>);
-    method public int setEngineByPackageName(java.lang.String);
+    method public deprecated int setEngineByPackageName(java.lang.String);
     method public int setLanguage(java.util.Locale);
     method public int setOnUtteranceCompletedListener(android.speech.tts.TextToSpeech.OnUtteranceCompletedListener);
     method public int setPitch(float);
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 01262fa..ca77185 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -66,6 +66,7 @@
 static long gMaxNumFrames;  // 0 means decode all available.
 static long gReproduceBug;  // if not -1.
 static bool gPreferSoftwareCodec;
+static bool gForceToUseHardwareCodec;
 static bool gPlaybackAudio;
 static bool gWriteMP4;
 static bool gDisplayHistogram;
@@ -144,10 +145,18 @@
     if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_RAW, mime)) {
         rawSource = source;
     } else {
+        int flags = 0;
+        if (gPreferSoftwareCodec) {
+            flags |= OMXCodec::kPreferSoftwareCodecs;
+        }
+        if (gForceToUseHardwareCodec) {
+            CHECK(!gPreferSoftwareCodec);
+            flags |= OMXCodec::kHardwareCodecsOnly;
+        }
         rawSource = OMXCodec::Create(
             client->interface(), meta, false /* createEncoder */, source,
             NULL /* matchComponentName */,
-            gPreferSoftwareCodec ? OMXCodec::kPreferSoftwareCodecs : 0,
+            flags,
             gSurface);
 
         if (rawSource == NULL) {
@@ -545,6 +554,7 @@
     fprintf(stderr, "       -p(rofiles) dump decoder profiles supported\n");
     fprintf(stderr, "       -t(humbnail) extract video thumbnail or album art\n");
     fprintf(stderr, "       -s(oftware) prefer software codec\n");
+    fprintf(stderr, "       -r(hardware) force to use hardware codec\n");
     fprintf(stderr, "       -o playback audio\n");
     fprintf(stderr, "       -w(rite) filename (write to .mp4 file)\n");
     fprintf(stderr, "       -k seek test\n");
@@ -566,6 +576,7 @@
     gMaxNumFrames = 0;
     gReproduceBug = -1;
     gPreferSoftwareCodec = false;
+    gForceToUseHardwareCodec = false;
     gPlaybackAudio = false;
     gWriteMP4 = false;
     gDisplayHistogram = false;
@@ -575,7 +586,7 @@
     sp<LiveSession> liveSession;
 
     int res;
-    while ((res = getopt(argc, argv, "han:lm:b:ptsow:kxS")) >= 0) {
+    while ((res = getopt(argc, argv, "han:lm:b:ptsrow:kxS")) >= 0) {
         switch (res) {
             case 'a':
             {
@@ -636,6 +647,12 @@
                 break;
             }
 
+            case 'r':
+            {
+                gForceToUseHardwareCodec = true;
+                break;
+            }
+
             case 'o':
             {
                 gPlaybackAudio = true;
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
index 55850c9..6f92247 100644
--- a/core/java/android/net/EthernetDataTracker.java
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -63,6 +63,7 @@
     private Context mContext;
 
     private static EthernetDataTracker sInstance;
+    private static String sIfaceMatch = "";
     private static String mIface = "";
 
     private static class InterfaceObserver extends INetworkManagementEventObserver.Stub {
@@ -96,7 +97,7 @@
     }
 
     private void interfaceAdded(String iface) {
-        if (!iface.matches("eth\\d"))
+        if (!iface.matches(sIfaceMatch))
             return;
 
         Log.d(TAG, "Adding " + iface);
@@ -187,6 +188,22 @@
         } catch (RemoteException e) {
             Log.e(TAG, "Could not register InterfaceObserver " + e);
         }
+
+        // connect to an ethernet interface that already exists
+        sIfaceMatch = context.getResources().getString(
+            com.android.internal.R.string.config_ethernet_iface_regex);
+        try {
+            final String[] ifaces = service.listInterfaces();
+            for (String iface : ifaces) {
+                if (iface.matches(sIfaceMatch)) {
+                    mIface = iface;
+                    reconnect();
+                    break;
+                }
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Could not get list of interfaces " + e);
+        }
     }
 
     /**
diff --git a/core/java/android/provider/Calendar.java b/core/java/android/provider/Calendar.java
index 3b2e6b6..8359144 100644
--- a/core/java/android/provider/Calendar.java
+++ b/core/java/android/provider/Calendar.java
@@ -39,8 +39,52 @@
 import android.util.Log;
 
 /**
- * The Calendar provider contains all calendar events.
- *
+ * <p>
+ * The contract between the calendar provider and applications. Contains
+ * definitions for the supported URIs and data columns.
+ * </p>
+ * <h3>Overview</h3>
+ * <p>
+ * CalendarContract defines the data model of calendar and event related
+ * information. This data is stored in a number of tables:
+ * </p>
+ * <ul>
+ * <li>The {@link Calendars} table holds the calendar specific information. Each
+ * row in this table contains the details for a single calendar, such as the
+ * name, color, sync info, etc.</li>
+ * <li>The {@link Events} table holds the event specific information. Each row
+ * in this table has the info for a single event. It contains information such
+ * as event title, location, start time, end time, etc. The event can occur
+ * one-time or can recur multiple times. Attendees, reminders, and extended
+ * properties are stored on separate tables and reference the {@link Events#_ID}
+ * to link them with the event.</li>
+ * <li>The {@link Instances} table holds the start and end time for occurrences
+ * of an event. Each row in this table represents a single occurrence. For
+ * one-time events there will be a 1:1 mapping of instances to events. For
+ * recurring events, multiple rows will automatically be generated which
+ * correspond to multiple occurrences of that event.</li>
+ * <li>The {@link Attendees} table holds the event attendee or guest
+ * information. Each row represents a single guest of an event. It specifies the
+ * type of guest they are and their attendance response for the event.</li>
+ * <li>The {@link Reminders} table holds the alert/notification data. Each row
+ * represents a single alert for an event. An event can have multiple reminders.
+ * The number of reminders per event is specified in
+ * {@link Calendars#MAX_REMINDERS} which is set by the Sync Adapter that owns
+ * the given calendar. Reminders are specified in minutes before the event and
+ * have a type.</li>
+ * <li>The {@link ExtendedProperties} table hold opaque data fields used by the
+ * sync adapter. The provider takes no action with items in this table except to
+ * delete them when their related events are deleted.</li>
+ * </ul>
+ * <p>
+ * Other tables include:
+ * </p>
+ * <ul>
+ * <li>
+ * {@link SyncState}, which contains free-form data maintained by the sync
+ * adapters</li>
+ * </ul>
+ * 
  * @hide
  */
 public final class Calendar {
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 6c14119..00e2998 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -6300,9 +6300,10 @@
      * <p>
      * Example:
      * <pre>
-     * Uri uri = DataUsageFeedback.UPDATE_URI.buildUpon()
+     * Uri uri = DataUsageFeedback.FEEDBACK_URI.buildUpon()
      *         .appendPath(TextUtils.join(",", dataIds))
-     *         .appendQueryParameter(DataUsageFeedback.METHOD, DataUsageFeedback.METHOD_CALL)
+     *         .appendQueryParameter(DataUsageFeedback.USAGE_TYPE,
+     *                 DataUsageFeedback.USAGE_TYPE_CALL)
      *         .build();
      * boolean successful = resolver.update(uri, new ContentValues(), null, null) > 0;
      * </pre>
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 1025b20..01e028e7 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1768,12 +1768,6 @@
         public static final String UNLOCK_SOUND = "unlock_sound";
 
         /**
-         * True if we should appear as a PTP device instead of MTP.
-         * @hide
-         */
-        public static final String USE_PTP_INTERFACE = "use_ptp_interface";
-
-        /**
          * Receive incoming SIP calls?
          * 0 = no
          * 1 = yes
@@ -1879,7 +1873,6 @@
             LOCKSCREEN_SOUNDS_ENABLED,
             SHOW_WEB_SUGGESTIONS,
             NOTIFICATION_LIGHT_PULSE,
-            USE_PTP_INTERFACE,
             SIP_CALL_OPTIONS,
             SIP_RECEIVE_CALLS,
             POINTER_SPEED,
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 23fd96f..6823b73 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -505,12 +505,14 @@
 
         // Try requested engine
         if (connectToEngine(engine)) {
+            mCurrentEngine = engine;
             return SUCCESS;
         }
 
         // Fall back to user's default engine if different from the already tested one
         if (!engine.equals(defaultEngine)) {
             if (connectToEngine(defaultEngine)) {
+                mCurrentEngine = engine;
                 return SUCCESS;
             }
         }
@@ -520,10 +522,12 @@
         if (!defaultEngine.equals(highestRanked)
                 && !engine.equals(highestRanked)) {
             if (connectToEngine(highestRanked)) {
+                mCurrentEngine = engine;
                 return SUCCESS;
             }
         }
 
+        dispatchOnInit(ERROR);
         return ERROR;
     }
 
@@ -534,10 +538,9 @@
         boolean bound = mContext.bindService(intent, connection, Context.BIND_AUTO_CREATE);
         if (!bound) {
             Log.e(TAG, "Failed to bind to " + engine);
-            dispatchOnInit(ERROR);
             return false;
         } else {
-            mCurrentEngine = engine;
+            Log.i(TAG, "Sucessfully bound to " + engine);
             return true;
         }
     }
@@ -1052,13 +1055,15 @@
     /**
      * Sets the TTS engine to use.
      *
+     * @deprecated This doesn't inform callers when the TTS engine has been
+     *        initialized. {@link #TextToSpeech(Context, OnInitListener, String)}
+     *        can be used with the appropriate engine name.
+     *
      * @param enginePackageName The package name for the synthesis engine (e.g. "com.svox.pico")
      *
      * @return {@link #ERROR} or {@link #SUCCESS}.
      */
-    // TODO: add @Deprecated{This method does not tell the caller when the new engine
-    // has been initialized. You should create a new TextToSpeech object with the new
-    // engine instead.}
+    @Deprecated
     public int setEngineByPackageName(String enginePackageName) {
         mRequestedEngine = enginePackageName;
         return initTts();
diff --git a/core/java/android/speech/tts/TtsEngines.java b/core/java/android/speech/tts/TtsEngines.java
index e8d74eb..715894f 100644
--- a/core/java/android/speech/tts/TtsEngines.java
+++ b/core/java/android/speech/tts/TtsEngines.java
@@ -48,14 +48,14 @@
     }
 
     /**
-     * @return the default TTS engine. If the user has set a default, that
-     *         value is returned else the highest ranked engine is returned,
-     *         as per {@link EngineInfoComparator}.
+     * @return the default TTS engine. If the user has set a default, and the engine
+     *         is available on the device, the default is returned. Otherwise,
+     *         the highest ranked engine is returned as per {@link EngineInfoComparator}.
      */
     public String getDefaultEngine() {
         String engine = Settings.Secure.getString(mContext.getContentResolver(),
                 Settings.Secure.TTS_DEFAULT_SYNTH);
-        return engine != null ? engine : getHighestRankedEngineName();
+        return isEngineInstalled(engine) ? engine : getHighestRankedEngineName();
     }
 
     /**
@@ -124,7 +124,14 @@
     public boolean isEngineEnabled(String engine) {
         // System engines are enabled by default always.
         EngineInfo info = getEngineInfo(engine);
-        if (info != null && info.system) {
+        if (info == null) {
+            // The engine is not installed, and therefore cannot
+            // be enabled.
+            return false;
+        }
+
+        if (info.system) {
+            // All system engines are enabled by default.
             return true;
         }
 
@@ -141,6 +148,25 @@
         return appInfo != null && (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
     }
 
+    /**
+     * @return true if a given engine is installed on the system. Useful to deal
+     *         with cases where an engine has been uninstalled by the user or removed
+     *         for any other reason.
+     */
+    private boolean isEngineInstalled(String engine) {
+        if (engine == null) {
+            return false;
+        }
+
+        for (EngineInfo info : getEngines()) {
+            if (engine.equals(info.name)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
     private EngineInfo getEngineInfo(ResolveInfo resolve, PackageManager pm) {
         ServiceInfo service = resolve.serviceInfo;
         if (service != null) {
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index b0181bb..6b6aee3 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -685,7 +685,19 @@
 
         // ----- HIDDEN FLAGS.
         // These start at the high bit and go down.
-        
+
+        /** Window flag: Enable touches to slide out of a window into neighboring
+         * windows in mid-gesture instead of being captured for the duration of
+         * the gesture.
+         *
+         * This flag changes the behavior of touch focus for this window only.
+         * Touches can slide out of the window but they cannot necessarily slide
+         * back in (unless the other window with touch focus permits it).
+         *
+         * {@hide}
+         */
+        public static final int FLAG_SLIPPERY = 0x04000000;
+
         /**
          * Flag for a window belonging to an activity that responds to {@link KeyEvent#KEYCODE_MENU}
          * and therefore needs a Menu key. For devices where Menu is a physical button this flag is
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
index 026ad27..1e98827 100644
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
@@ -134,18 +134,26 @@
         mTapRadius = mHandleDrawable.getWidth()/2;
         mOuterRing = new TargetDrawable(res, a.getDrawable(R.styleable.MultiWaveView_waveDrawable));
 
-        // Read animation drawables
+        // Read chevron animation drawables
         Drawable leftChevron = a.getDrawable(R.styleable.MultiWaveView_leftChevronDrawable);
-        if (leftChevron != null) {
-            for (int i = 0; i < mFeedbackCount; i++) {
-                mChevronDrawables.add(new TargetDrawable(res, leftChevron));
-            }
+        for (int i = 0; i < mFeedbackCount; i++) {
+            mChevronDrawables.add(
+                    leftChevron != null ? new TargetDrawable(res, leftChevron) : null);
         }
         Drawable rightChevron = a.getDrawable(R.styleable.MultiWaveView_rightChevronDrawable);
-        if (rightChevron != null) {
-            for (int i = 0; i < mFeedbackCount; i++) {
-                mChevronDrawables.add(new TargetDrawable(res, rightChevron));
-            }
+        for (int i = 0; i < mFeedbackCount; i++) {
+            mChevronDrawables.add(
+                    rightChevron != null ? new TargetDrawable(res, rightChevron) : null);
+        }
+        Drawable topChevron = a.getDrawable(R.styleable.MultiWaveView_topChevronDrawable);
+        for (int i = 0; i < mFeedbackCount; i++) {
+            mChevronDrawables.add(
+                    topChevron != null ? new TargetDrawable(res, topChevron) : null);
+        }
+        Drawable bottomChevron = a.getDrawable(R.styleable.MultiWaveView_bottomChevronDrawable);
+        for (int i = 0; i < mFeedbackCount; i++) {
+            mChevronDrawables.add(
+                    bottomChevron != null ? new TargetDrawable(res, bottomChevron) : null);
         }
 
         // Read array of target drawables
@@ -190,7 +198,6 @@
     private void switchToState(int state, float x, float y) {
         switch (state) {
             case STATE_IDLE:
-                stopChevronAnimation();
                 deactivateTargets();
                 mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
                 break;
@@ -221,33 +228,32 @@
      * followed by right chevrons.
      */
     private void startChevronAnimation() {
-        final int icons = mChevronDrawables.size();
-        for (Tweener tween : mChevronAnimations) {
-            tween.animator.cancel();
-        }
-        for (int i = 0; i < icons; i++) {
-            TargetDrawable icon = mChevronDrawables.get(i);
-            icon.setY(mWaveCenterY);
-            icon.setAlpha(1.0f);
-            mChevronAnimations.clear();
-            int delay = (int) (Math.abs(0.5f + i - icons / 2) * CHEVRON_INCREMENTAL_DELAY);
-            if (i < icons/2) {
-                // Left chevrons
-                icon.setX(mWaveCenterX - mHandleDrawable.getWidth() / 2);
+        final float r = mHandleDrawable.getWidth() / 2;
+        final float from[][] = {
+                {mWaveCenterX - r, mWaveCenterY},  // left
+                {mWaveCenterX + r, mWaveCenterY},  // right
+                {mWaveCenterX, mWaveCenterY - r},  // top
+                {mWaveCenterX, mWaveCenterY + r} }; // bottom
+        final float to[][] = {
+                {mWaveCenterX - mOuterRadius, mWaveCenterY},  // left
+                {mWaveCenterX + mOuterRadius, mWaveCenterY},  // right
+                {mWaveCenterX, mWaveCenterY - mOuterRadius},  // top
+                {mWaveCenterX, mWaveCenterY + mOuterRadius} }; // bottom
+
+        mChevronAnimations.clear();
+        for (int direction = 0; direction < 4; direction++) {
+            for (int count = 0; count < mFeedbackCount; count++) {
+                int delay = count * CHEVRON_INCREMENTAL_DELAY;
+                final TargetDrawable icon = mChevronDrawables.get(direction*mFeedbackCount + count);
+                if (icon == null) {
+                    continue;
+                }
                 mChevronAnimations.add(Tweener.to(icon, CHEVRON_ANIMATION_DURATION,
                         "ease", mChevronAnimationInterpolator,
                         "delay", delay,
-                        "x", mWaveCenterX - mOuterRadius,
-                        "alpha", 0.0f,
-                        "onUpdate", this));
-            } else {
-                // Right chevrons
-                icon.setX(mWaveCenterX + mHandleDrawable.getWidth() / 2);
-                mChevronAnimations.add(Tweener.to(icon, CHEVRON_ANIMATION_DURATION,
-                        "ease", mChevronAnimationInterpolator,
-                        "delay", delay,
-                        "x", mWaveCenterX + mOuterRadius,
-                        "alpha", 0.0f,
+                        "x", new float[] { from[direction][0], to[direction][0] },
+                        "y", new float[] { from[direction][1], to[direction][1] },
+                        "alpha", new float[] {1.0f, 0.0f},
                         "onUpdate", this));
             }
         }
@@ -330,8 +336,6 @@
         if (targetHit) {
             mTargetDrawables.get(activeTarget).setState(TargetDrawable.STATE_ACTIVE);
         }
-
-        stopChevronAnimation();
     }
 
     private void hideTargets(boolean animate) {
@@ -392,11 +396,12 @@
         Resources res = getContext().getResources();
         TypedArray array = res.obtainTypedArray(resourceId);
         int count = array.length();
-        mTargetDrawables = new ArrayList<TargetDrawable>(count);
+        ArrayList<TargetDrawable> targetDrawables = new ArrayList<TargetDrawable>(count);
         for (int i = 0; i < count; i++) {
             Drawable drawable = array.getDrawable(i);
-            mTargetDrawables.add(new TargetDrawable(res, drawable));
+            targetDrawables.add(new TargetDrawable(res, drawable));
         }
+        mTargetDrawables = targetDrawables;
     }
 
     /**
@@ -472,12 +477,19 @@
         return handled ? true : super.onTouchEvent(event);
     }
 
+    private void moveHandleTo(float x, float y, boolean animate) {
+        // TODO: animate the handle based on the current state/position
+        mHandleDrawable.setX(x);
+        mHandleDrawable.setY(y);
+    }
+
     private void handleDown(float x, float y) {
         final float dx = x - mWaveCenterX;
         final float dy = y - mWaveCenterY;
         if (dist2(dx,dy) <= square(mTapRadius)) {
             if (DEBUG) Log.v(TAG, "** Handle HIT");
             switchToState(STATE_FIRST_TOUCH, x, y);
+            moveHandleTo(x, y, false);
             mDragging = true;
         } else {
             mDragging = false;
@@ -528,11 +540,14 @@
                     best = dist2;
                 }
             }
+            x = limitX;
+            y = limitY;
         }
         if (activeTarget != -1) {
             switchToState(STATE_SNAP, x,y);
-            mHandleDrawable.setX(singleTarget ? limitX : mTargetDrawables.get(activeTarget).getX());
-            mHandleDrawable.setY(singleTarget ? limitY : mTargetDrawables.get(activeTarget).getY());
+            float newX = singleTarget ? limitX : mTargetDrawables.get(activeTarget).getX();
+            float newY = singleTarget ? limitY : mTargetDrawables.get(activeTarget).getY();
+            moveHandleTo(newX, newY, false);
             TargetDrawable currentTarget = mTargetDrawables.get(activeTarget);
             if (currentTarget.hasState(TargetDrawable.STATE_FOCUSED)) {
                 currentTarget.setState(TargetDrawable.STATE_FOCUSED);
@@ -540,8 +555,7 @@
             }
         } else {
             switchToState(STATE_TRACKING, x, y);
-            mHandleDrawable.setX(x);
-            mHandleDrawable.setY(y);
+            moveHandleTo(x, y, false);
             mHandleDrawable.setAlpha(1.0f);
         }
         // Draw handle outside parent's bounds
@@ -577,8 +591,7 @@
 
         mWaveCenterX = mHorizontalOffset + Math.max(width, mOuterRing.getWidth() ) / 2;
         mWaveCenterY = mVerticalOffset + Math.max(height, mOuterRing.getHeight()) / 2;
-        mHandleDrawable.setX(mWaveCenterX);
-        mHandleDrawable.setY(mWaveCenterY);
+        moveHandleTo(mWaveCenterX, mWaveCenterY, false);
         mOuterRing.setX(mWaveCenterX);
         mOuterRing.setY(Math.max(mWaveCenterY, mWaveCenterY));
         mOuterRing.setAlpha(0.0f);
@@ -609,7 +622,9 @@
 
     private void hideChevrons() {
         for (TargetDrawable chevron : mChevronDrawables) {
-            chevron.setAlpha(0.0f);
+            if (chevron != null) {
+                chevron.setAlpha(0.0f);
+            }
         }
     }
 
@@ -617,10 +632,14 @@
     protected void onDraw(Canvas canvas) {
         mOuterRing.draw(canvas);
         for (TargetDrawable target : mTargetDrawables) {
-            target.draw(canvas);
+            if (target != null) {
+                target.draw(canvas);
+            }
         }
         for (TargetDrawable target : mChevronDrawables) {
-            target.draw(canvas);
+            if (target != null) {
+                target.draw(canvas);
+            }
         }
         mHandleDrawable.draw(canvas);
     }
diff --git a/core/java/com/android/internal/widget/multiwaveview/Tweener.java b/core/java/com/android/internal/widget/multiwaveview/Tweener.java
index c2746d9..0cff00a 100644
--- a/core/java/com/android/internal/widget/multiwaveview/Tweener.java
+++ b/core/java/com/android/internal/widget/multiwaveview/Tweener.java
@@ -63,14 +63,15 @@
                 delay = ((Number) value).longValue();
             } else if ("syncWith".equals(key)) {
                 // TODO
-            } else if (value instanceof Number[]) {
-                // TODO: support Tween.from()
+            } else if (value instanceof float[]) {
+                props.add(PropertyValuesHolder.ofFloat(key,
+                        ((float[])value)[0], ((float[])value)[1]));
             } else if (value instanceof Number) {
                 float floatValue = ((Number)value).floatValue();
                 props.add(PropertyValuesHolder.ofFloat(key, floatValue));
             } else {
                 throw new IllegalArgumentException(
-                        "Bad argument for key \"" + key + "with value" + value);
+                        "Bad argument for key \"" + key + "\" with value " + value.getClass());
             }
         }
 
diff --git a/core/jni/android/graphics/ParcelSurfaceTexture.cpp b/core/jni/android/graphics/ParcelSurfaceTexture.cpp
index 517d7e2..40966e1 100644
--- a/core/jni/android/graphics/ParcelSurfaceTexture.cpp
+++ b/core/jni/android/graphics/ParcelSurfaceTexture.cpp
@@ -19,6 +19,7 @@
 #include <gui/SurfaceTextureClient.h>
 
 #include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/android_graphics_SurfaceTexture.h>
 
 #include <utils/Log.h>
 
@@ -27,7 +28,6 @@
 #include "android_util_Binder.h"
 #include "jni.h"
 #include "JNIHelp.h"
-#include "SurfaceTexture.h"
 
 // ----------------------------------------------------------------------------
 
@@ -59,7 +59,7 @@
     env->SetIntField(thiz, fields.iSurfaceTexture, (int)iSurfaceTexture.get());
 }
 
-static sp<ISurfaceTexture> ParcelSurfaceTexture_getISurfaceTexture(
+sp<ISurfaceTexture> ParcelSurfaceTexture_getISurfaceTexture(
         JNIEnv* env, jobject thiz)
 {
     sp<ISurfaceTexture> iSurfaceTexture(
diff --git a/core/jni/android/graphics/SurfaceTexture.h b/core/jni/android/graphics/SurfaceTexture.h
deleted file mode 100644
index 79d8dd3..0000000
--- a/core/jni/android/graphics/SurfaceTexture.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#ifndef _ANDROID_GRAPHICS_SURFACETEXTURE_H
-#define _ANDROID_GRAPHICS_SURFACETEXTURE_H
-
-#include <gui/SurfaceTexture.h>
-#include <utils/StrongPointer.h>
-#include "jni.h"
-
-namespace android {
-
-/* Gets the underlying SurfaceTexture from a SurfaceTexture Java object. */
-sp<SurfaceTexture> SurfaceTexture_getSurfaceTexture(JNIEnv* env, jobject thiz);
-
-} // namespace android
-
-#endif // _ANDROID_GRAPHICS_SURFACETEXTURE_H
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 246c0e5..0c5101f 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -31,7 +31,7 @@
 #include <media/AudioTrack.h>
 
 #include <system/audio.h>
-#include <hardware/audio_policy.h>
+#include <system/audio_policy.h>
 
 // ----------------------------------------------------------------------------
 
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_down.png b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_down.png
new file mode 100644
index 0000000..620844e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_down.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_up.png b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_up.png
new file mode 100644
index 0000000..4ffa833
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_up.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_down.png b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_down.png
new file mode 100644
index 0000000..d3cfd17
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_down.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_up.png b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_up.png
new file mode 100644
index 0000000..35aca4e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_up.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_down.png b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_down.png
new file mode 100644
index 0000000..c655d93
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_down.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_up.png b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_up.png
new file mode 100644
index 0000000..53794fd
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_up.png
Binary files differ
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
index 24891dc..7ae357a 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -176,7 +176,6 @@
         android:snapMargin="@*android:dimen/multiwaveview_snap_margin"
         android:hitRadius="@*android:dimen/multiwaveview_hit_radius"
         android:vibrationDuration="20"
-        android:leftChevronDrawable="@drawable/ic_lockscreen_chevron_left"
         android:rightChevronDrawable="@drawable/ic_lockscreen_chevron_right"
         android:feedbackCount="3"
         android:horizontalOffset="0dip"
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
index 02994a9..df29a4b 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -176,8 +176,7 @@
         android:snapMargin="@*android:dimen/multiwaveview_snap_margin"
         android:hitRadius="@*android:dimen/multiwaveview_hit_radius"
         android:vibrationDuration="20"
-        android:leftChevronDrawable="@drawable/ic_lockscreen_chevron_left"
-        android:rightChevronDrawable="@drawable/ic_lockscreen_chevron_right"
+        android:topChevronDrawable="@drawable/ic_lockscreen_chevron_up"
         android:feedbackCount="3"
         android:horizontalOffset="60dip"
         android:verticalOffset="0dip"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index acfdfc9..5d357c5 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5019,12 +5019,18 @@
         <!-- Sets a drawable as the drag center. -->
         <attr name="handleDrawable" format="reference" />
 
-        <!-- Drawable to use for chevron animation on the left. -->
+        <!-- Drawable to use for chevron animation on the left. May be null. -->
         <attr name="leftChevronDrawable" format="reference" />
 
-        <!-- Drawable to use for chevron animation on the right. -->
+        <!-- Drawable to use for chevron animation on the right. May be null. -->
         <attr name="rightChevronDrawable" format="reference" />
 
+        <!-- Drawable to use for chevron animation on the top. May be null. -->
+        <attr name="topChevronDrawable" format="reference" />
+
+        <!-- Drawable to use for chevron animation on the bottom. May be null. -->
+        <attr name="bottomChevronDrawable" format="reference" />
+
         <!-- Drawable to use for wave ripple animation. -->
         <attr name="waveDrawable" format="reference" />
 
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index c95b0ae..3b4798e 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -160,6 +160,9 @@
     <string-array translatable="false" name="config_tether_upstream_regexs">
     </string-array>
 
+    <!-- Regex of wired ethernet ifaces -->
+    <string translatable="false" name="config_ethernet_iface_regex">eth\\d</string>
+
     <!-- Boolean indicating if we require the use of DUN on mobile for tethering.
          Note that this defaults to false so that if you move to a carrier that
          hasn't configured anything tethering will still work.  If you'd rather
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 4108c1b..17b23da 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1756,6 +1756,8 @@
   <public type="attr" name="handleDrawable" />
   <public type="attr" name="leftChevronDrawable" />
   <public type="attr" name="rightChevronDrawable" />
+  <public type="attr" name="topChevronDrawable" />
+  <public type="attr" name="bottomChevronDrawable" />
   <public type="attr" name="waveDrawable" />
   <public type="attr" name="outerRadius" />
   <public type="attr" name="hitRadius" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b264b41..966dbe5 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1788,6 +1788,8 @@
     <string name="lockscreen_missing_sim_message" product="default">No SIM card in phone.</string>
     <!-- Shown in the lock screen to ask the user to insert a SIM card. -->
     <string name="lockscreen_missing_sim_instructions">Please insert a SIM card.</string>
+    <!-- Shown in the lock screen to ask the user to insert a SIM card when sim is missing or not readable. -->
+    <string name="lockscreen_missing_sim_instructions_long">The SIM card is missing or not readable. Please insert a SIM card.</string>
 
     <!-- Shown in the lock screen when there is emergency calls only mode. -->
     <string name="emergency_calls_only" msgid="2485604591272668370">Emergency calls only</string>
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
index d430f72..3cbd8f1 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
@@ -455,11 +455,14 @@
         } else {
             LOGD("FwdLockEngine::onOpenDecryptSession Integrity Check failed for the fd");
             FwdLockFile_detach(fileDesc);
-            ::close(fileDesc);
             delete decodeSession;
         }
     }
 
+    if (DRM_NO_ERROR != result && -1 < fileDesc) {
+        ::close(fileDesc);
+    }
+
     LOGD("FwdLockEngine::onOpenDecryptSession Exit. result = %d", result);
 
     return result;
diff --git a/include/android_runtime/android_graphics_ParcelSurfaceTexture.h b/include/android_runtime/android_graphics_ParcelSurfaceTexture.h
index 22f1c12..b94ac9b 100644
--- a/include/android_runtime/android_graphics_ParcelSurfaceTexture.h
+++ b/include/android_runtime/android_graphics_ParcelSurfaceTexture.h
@@ -23,10 +23,15 @@
 
 namespace android {
 
+class ISurfaceTexture;
+
 extern sp<ANativeWindow> android_ParcelSurfaceTexture_getNativeWindow(
         JNIEnv* env, jobject thiz);
 extern bool android_ParcelSurfaceTexture_isInstanceOf(JNIEnv* env, jobject thiz);
 
+/* Gets the underlying ISurfaceTexture from a ParcelSurfaceTexture Java object. */
+extern sp<ISurfaceTexture> ParcelSurfaceTexture_getISurfaceTexture(JNIEnv* env, jobject thiz);
+
 } // namespace android
 
 #endif // _ANDROID_GRAPHICS_PARCELSURFACETEXTURE_H
diff --git a/include/android_runtime/android_graphics_SurfaceTexture.h b/include/android_runtime/android_graphics_SurfaceTexture.h
index acf1ca8..badf22c 100644
--- a/include/android_runtime/android_graphics_SurfaceTexture.h
+++ b/include/android_runtime/android_graphics_SurfaceTexture.h
@@ -23,10 +23,14 @@
 
 namespace android {
 
+class SurfaceTexture;
+
 extern sp<ANativeWindow> android_SurfaceTexture_getNativeWindow(
         JNIEnv* env, jobject thiz);
 extern bool android_SurfaceTexture_isInstanceOf(JNIEnv* env, jobject thiz);
 
+/* Gets the underlying SurfaceTexture from a SurfaceTexture Java object. */
+extern sp<SurfaceTexture> SurfaceTexture_getSurfaceTexture(JNIEnv* env, jobject thiz);
 
 } // namespace android
 
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 68cd188..89213b7 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -22,7 +22,7 @@
 #include <media/IAudioFlinger.h>
 
 #include <system/audio.h>
-#include <hardware/audio_policy.h>
+#include <system/audio_policy.h>
 
 /* XXX: Should be include by all the users instead */
 #include <media/AudioParameter.h>
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index 09b2bfe..0fc8dbf 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -26,7 +26,7 @@
 #include <binder/IInterface.h>
 #include <media/AudioSystem.h>
 
-#include <hardware/audio_policy.h>
+#include <system/audio_policy.h>
 
 namespace android {
 
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 4044c5d..deade5e 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -55,6 +55,7 @@
     kKeyIsSyncFrame       = 'sync',  // int32_t (bool)
     kKeyIsCodecConfig     = 'conf',  // int32_t (bool)
     kKeyTime              = 'time',  // int64_t (usecs)
+    kKeyDecodingTime      = 'decT',  // int64_t (decoding timestamp in usecs)
     kKeyNTPTime           = 'ntpT',  // uint64_t (ntp-timestamp)
     kKeyTargetTime        = 'tarT',  // int64_t (usecs)
     kKeyDriftTime         = 'dftT',  // int64_t (usecs)
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 70daafa..589cefd 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -202,6 +202,10 @@
     bool mOnlySubmitOneBufferAtOneTime;
     bool mEnableGrallocUsageProtected;
 
+    // Used to record the decoding time for an output picture from
+    // a video encoder.
+    List<int64_t> mDecodingTimeList;
+
     OMXCodec(const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks,
              bool isEncoder, const char *mime, const char *componentName,
              const sp<MediaSource> &source,
@@ -317,6 +321,8 @@
 
     status_t applyRotation();
 
+    int64_t retrieveDecodingTimeUs(bool isCodecSpecific);
+
     OMXCodec(const OMXCodec &);
     OMXCodec &operator=(const OMXCodec &);
 };
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 6c9c0eb..5343a05 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -476,13 +476,8 @@
                         snapshot->height - bounds.bottom, bounds.getWidth(), bounds.getHeight());
             }
 
-            // Clear the framebuffer where the layer will draw
-            glScissor(bounds.left, mSnapshot->height - bounds.bottom,
-                    bounds.getWidth(), bounds.getHeight());
-            glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-            glClear(GL_COLOR_BUFFER_BIT);
-
-            dirtyClip();
+            // Enqueue the buffer coordinates to clear the corresponding region later
+            mLayers.push(new Rect(bounds));
         }
     }
 
@@ -817,6 +812,58 @@
 #endif
 }
 
+void OpenGLRenderer::clearLayerRegions() {
+    const size_t count = mLayers.size();
+    if (count == 0) return;
+
+    if (!mSnapshot->isIgnored()) {
+        // Doing several glScissor/glClear here can negatively impact
+        // GPUs with a tiler architecture, instead we draw quads with
+        // the Clear blending mode
+
+        // The list contains bounds that have already been clipped
+        // against their initial clip rect, and the current clip
+        // is likely different so we need to disable clipping here
+        glDisable(GL_SCISSOR_TEST);
+
+        Vertex mesh[count * 6];
+        Vertex* vertex = mesh;
+
+        for (uint32_t i = 0; i < count; i++) {
+            Rect* bounds = mLayers.itemAt(i);
+
+            Vertex::set(vertex++, bounds->left, bounds->bottom);
+            Vertex::set(vertex++, bounds->left, bounds->top);
+            Vertex::set(vertex++, bounds->right, bounds->top);
+            Vertex::set(vertex++, bounds->left, bounds->bottom);
+            Vertex::set(vertex++, bounds->right, bounds->top);
+            Vertex::set(vertex++, bounds->right, bounds->bottom);
+
+            delete bounds;
+        }
+
+        setupDraw(false);
+        setupDrawColor(0.0f, 0.0f, 0.0f, 1.0f);
+        setupDrawBlending(true, SkXfermode::kClear_Mode);
+        setupDrawProgram();
+        setupDrawPureColorUniforms();
+        setupDrawModelViewTranslate(0.0f, 0.0f, 0.0f, 0.0f, true);
+
+        mCaches.unbindMeshBuffer();
+        glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE,
+                gVertexStride, &mesh[0].position[0]);
+        glDrawArrays(GL_TRIANGLES, 0, count * 6);
+
+        glEnable(GL_SCISSOR_TEST);
+    } else {
+        for (uint32_t i = 0; i < count; i++) {
+            delete mLayers.itemAt(i);
+        }
+    }
+
+    mLayers.clear();
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // Transforms
 ///////////////////////////////////////////////////////////////////////////////
@@ -901,7 +948,8 @@
 // Drawing commands
 ///////////////////////////////////////////////////////////////////////////////
 
-void OpenGLRenderer::setupDraw() {
+void OpenGLRenderer::setupDraw(bool clear) {
+    if (clear) clearLayerRegions();
     if (mDirtyClip) {
         setScissorFromClip();
     }
@@ -994,7 +1042,7 @@
     if (mColorSet && mode == SkXfermode::kClear_Mode) {
         mColorA = 1.0f;
         mColorR = mColorG = mColorB = 0.0f;
-        mSetShaderColor = mDescription.setAlpha8Color(mColorR, mColorG, mColorB, mColorA);
+        mSetShaderColor = mDescription.modulate = true;
     }
 }
 
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 549d6e9..b9e3ddc 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -249,6 +249,18 @@
      */
     void composeLayerRect(Layer* layer, const Rect& rect, bool swap = false);
 
+    /**
+     * Clears all the regions corresponding to the current list of layers.
+     * This method MUST be invoked before any drawing operation.
+     */
+    void clearLayerRegions();
+
+    /**
+     * Renders the specified layer as a textured quad.
+     *
+     * @param layer The layer to render
+     * @param rect The bounds of the layer
+     */
     void drawTextureLayer(Layer* layer, const Rect& rect);
 
     /**
@@ -280,11 +292,53 @@
     void drawColorRect(float left, float top, float right, float bottom,
             int color, SkXfermode::Mode mode, bool ignoreTransform = false);
 
+    /**
+     * Draws the shape represented by the specified path texture.
+     * This method invokes drawPathTexture() but takes into account
+     * the extra left/top offset and the texture offset to correctly
+     * position the final shape.
+     *
+     * @param left The left coordinate of the shape to render
+     * @param top The top coordinate of the shape to render
+     * @param texture The texture reprsenting the shape
+     * @param paint The paint to draw the shape with
+     */
     void drawShape(float left, float top, const PathTexture* texture, SkPaint* paint);
+
+    /**
+     * Renders the rect defined by the specified bounds as a shape.
+     * This will render the rect using a path texture, which is used to render
+     * rects with stroke effects.
+     *
+     * @param left The left coordinate of the rect to draw
+     * @param top The top coordinate of the rect to draw
+     * @param right The right coordinate of the rect to draw
+     * @param bottom The bottom coordinate of the rect to draw
+     * @param p The paint to draw the rect with
+     */
     void drawRectAsShape(float left, float top, float right, float bottom, SkPaint* p);
 
+    /**
+     * Draws the specified texture as an alpha bitmap. Alpha bitmaps obey
+     * different compositing rules.
+     *
+     * @param texture The texture to draw with
+     * @param left The x coordinate of the bitmap
+     * @param top The y coordinate of the bitmap
+     * @param paint The paint to render with
+     */
     void drawAlphaBitmap(Texture* texture, float left, float top, SkPaint* paint);
 
+    /**
+     * Renders the rect defined by the specified bounds as an anti-aliased rect.
+     *
+     * @param left The left coordinate of the rect to draw
+     * @param top The top coordinate of the rect to draw
+     * @param right The right coordinate of the rect to draw
+     * @param bottom The bottom coordinate of the rect to draw
+     * @param color The color of the rect
+     * @param mode The blending mode to draw the rect
+     */
     void drawAARect(float left, float top, float right, float bottom,
             int color, SkXfermode::Mode mode);
 
@@ -359,6 +413,15 @@
     void drawTextDecorations(const char* text, int bytesCount, float length,
             float x, float y, SkPaint* paint);
 
+    /**
+     * Draws a path texture. Path textures are alpha8 bitmaps that need special
+     * compositing to apply colors/filters/etc.
+     *
+     * @param texture The texture to render
+     * @param x The x coordinate where the texture will be drawn
+     * @param y The y coordinate where the texture will be drawn
+     * @param paint The paint to draw the texture with
+     */
     void drawPathTexture(const PathTexture* texture, float x, float y, SkPaint* paint);
 
     /**
@@ -434,7 +497,7 @@
     /**
      * Invoked before any drawing operation. This sets required state.
      */
-    void setupDraw();
+    void setupDraw(bool clear = true);
     /**
      * Various methods to setup OpenGL rendering.
      */
@@ -522,6 +585,9 @@
     // Various caches
     Caches& mCaches;
 
+    // List of rectagnles to clear after saveLayer() is invoked
+    Vector<Rect*> mLayers;
+
     // Indentity matrix
     const mat4 mIdentity;
 
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 8f7dd60..e34d75cc 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -30,6 +30,7 @@
 import android.view.Surface;
 import android.view.SurfaceHolder;
 import android.graphics.Bitmap;
+import android.graphics.ParcelSurfaceTexture;
 import android.graphics.SurfaceTexture;
 import android.media.AudioManager;
 
@@ -509,7 +510,7 @@
     private int mListenerContext; // accessed by native methods
     private Surface mSurface; // accessed by native methods
     private SurfaceHolder  mSurfaceHolder;
-    private SurfaceTexture mSurfaceTexture; // accessed by native methods
+    private ParcelSurfaceTexture mParcelSurfaceTexture; // accessed by native methods
     private EventHandler mEventHandler;
     private PowerManager.WakeLock mWakeLock = null;
     private boolean mScreenOnWhilePlaying;
@@ -541,7 +542,7 @@
 
     /*
      * Update the MediaPlayer ISurface and ISurfaceTexture.
-     * Call after updating mSurface and/or mSurfaceTexture.
+     * Call after updating mSurface and/or mParcelSurfaceTexture.
      */
     private native void _setVideoSurfaceOrSurfaceTexture();
 
@@ -607,7 +608,7 @@
         } else {
             mSurface = null;
         }
-        mSurfaceTexture = null;
+        mParcelSurfaceTexture = null;
         _setVideoSurfaceOrSurfaceTexture();
         updateSurfaceScreenOn();
     }
@@ -630,12 +631,32 @@
      * program.
      */
     public void setTexture(SurfaceTexture st) {
-        if (mScreenOnWhilePlaying && st != null && mSurfaceTexture == null) {
+        ParcelSurfaceTexture pst = null;
+        if (st != null) {
+            pst = ParcelSurfaceTexture.fromSurfaceTexture(st);
+        }
+        setParcelSurfaceTexture(pst);
+    }
+
+    /**
+     * Sets the {@link ParcelSurfaceTexture} to be used as the sink for the video portion of
+     * the media. This is similar to {@link #setTexture(SurfaceTexture)}, but supports using
+     * a {@link ParcelSurfaceTexture} to transport the texture to be used via Binder. Setting
+     * a parceled surface texture will un-set any surface or surface texture that was previously
+     * set. See {@link #setTexture(SurfaceTexture)} for more details.
+     *
+     * @param pst The {@link ParcelSurfaceTexture} to be used as the sink for
+     * the video portion of the media.
+     *
+     * @hide Pending review by API council.
+     */
+    public void setParcelSurfaceTexture(ParcelSurfaceTexture pst) {
+        if (mScreenOnWhilePlaying && pst != null && mParcelSurfaceTexture == null) {
             Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective for SurfaceTexture");
         }
         mSurfaceHolder = null;
         mSurface = null;
-        mSurfaceTexture = st;
+        mParcelSurfaceTexture = pst;
         _setVideoSurfaceOrSurfaceTexture();
         updateSurfaceScreenOn();
     }
@@ -962,7 +983,7 @@
      */
     public void setScreenOnWhilePlaying(boolean screenOn) {
         if (mScreenOnWhilePlaying != screenOn) {
-            if (screenOn && mSurfaceTexture != null) {
+            if (screenOn && mParcelSurfaceTexture != null) {
                 Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective for SurfaceTexture");
             }
             mScreenOnWhilePlaying = screenOn;
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index b03aa38..5663683 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -30,6 +30,7 @@
 #include "jni.h"
 #include "JNIHelp.h"
 #include "android_runtime/AndroidRuntime.h"
+#include "android_runtime/android_graphics_ParcelSurfaceTexture.h"
 #include "utils/Errors.h"  // for status_t
 #include "utils/KeyedVector.h"
 #include "utils/String8.h"
@@ -37,7 +38,6 @@
 
 #include "android_util_Binder.h"
 #include <binder/Parcel.h>
-#include <gui/SurfaceTexture.h>
 #include <gui/ISurfaceTexture.h>
 #include <surfaceflinger/Surface.h>
 #include <binder/IPCThreadState.h>
@@ -52,11 +52,9 @@
 struct fields_t {
     jfieldID    context;
     jfieldID    surface;
-    jfieldID    surfaceTexture;
+    jfieldID    parcelSurfaceTexture;
     /* actually in android.view.Surface XXX */
     jfieldID    surface_native;
-    // actually in android.graphics.SurfaceTexture
-    jfieldID    surfaceTexture_native;
 
     jmethodID   post_event;
 };
@@ -130,13 +128,6 @@
     return (Surface*)env->GetIntField(clazz, fields.surface_native);
 }
 
-sp<ISurfaceTexture> getSurfaceTexture(JNIEnv* env, jobject clazz)
-{
-    sp<ISurfaceTexture> surfaceTexture(
-        (ISurfaceTexture*)env->GetIntField(clazz, fields.surfaceTexture_native));
-    return surfaceTexture;
-}
-
 static sp<MediaPlayer> getMediaPlayer(JNIEnv* env, jobject thiz)
 {
     Mutex::Autolock l(sLock);
@@ -257,8 +248,8 @@
         const sp<MediaPlayer>& mp, JNIEnv *env, jobject thiz, const char *prefix)
 {
     // The Java MediaPlayer class makes sure that at most one of mSurface and
-    // mSurfaceTexture is non-null.  But just in case, we give priority to
-    // mSurface over mSurfaceTexture.
+    // mParcelSurfaceTexture is non-null.  But just in case, we give priority to
+    // mSurface over mParcelSurfaceTexture.
     jobject surface = env->GetObjectField(thiz, fields.surface);
     if (surface != NULL) {
         sp<Surface> native_surface(get_surface(env, surface));
@@ -266,10 +257,10 @@
              native_surface.get(), native_surface->getIdentity());
         mp->setVideoSurface(native_surface);
     } else {
-        jobject surfaceTexture = env->GetObjectField(thiz, fields.surfaceTexture);
-        if (surfaceTexture != NULL) {
+        jobject parcelSurfaceTexture = env->GetObjectField(thiz, fields.parcelSurfaceTexture);
+        if (parcelSurfaceTexture != NULL) {
             sp<ISurfaceTexture> native_surfaceTexture(
-                    getSurfaceTexture(env, surfaceTexture));
+                    ParcelSurfaceTexture_getISurfaceTexture(env, parcelSurfaceTexture));
             LOGV("%s: texture=%p", prefix, native_surfaceTexture.get());
             mp->setVideoSurfaceTexture(native_surfaceTexture);
         }
@@ -610,23 +601,11 @@
         return;
     }
 
-    fields.surfaceTexture = env->GetFieldID(clazz, "mSurfaceTexture",
-            "Landroid/graphics/SurfaceTexture;");
-    if (fields.surfaceTexture == NULL) {
+    fields.parcelSurfaceTexture = env->GetFieldID(clazz, "mParcelSurfaceTexture",
+            "Landroid/graphics/ParcelSurfaceTexture;");
+    if (fields.parcelSurfaceTexture == NULL) {
         return;
     }
-
-    jclass surfaceTexture = env->FindClass("android/graphics/SurfaceTexture");
-    if (surfaceTexture == NULL) {
-        return;
-    }
-
-    fields.surfaceTexture_native = env->GetFieldID(surfaceTexture,
-            ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID, "I");
-    if (fields.surfaceTexture_native == NULL) {
-        return;
-    }
-
 }
 
 static void
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 6b4391b..37fe182 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -40,7 +40,7 @@
 #include <cutils/bitops.h>
 
 #include <system/audio.h>
-#include <hardware/audio_policy.h>
+#include <system/audio_policy.h>
 
 #define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
 #define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index a953487..b8ae79c 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -128,7 +128,6 @@
     size_t        mNumStssTableEntries;
     List<int32_t> mStssTableEntries;
 
-    size_t        mNumSttsTableEntries;
     struct SttsTableEntry {
 
         SttsTableEntry(uint32_t count, uint32_t duration)
@@ -137,8 +136,20 @@
         uint32_t sampleCount;
         uint32_t sampleDuration;  // time scale based
     };
+    size_t        mNumSttsTableEntries;
     List<SttsTableEntry> mSttsTableEntries;
 
+    struct CttsTableEntry {
+        CttsTableEntry(uint32_t count, int32_t timescaledDur)
+            : sampleCount(count), sampleDuration(timescaledDur) {}
+
+        uint32_t sampleCount;
+        int32_t sampleDuration;  // time scale based
+    };
+    bool          mHasNegativeCttsDeltaDuration;
+    size_t        mNumCttsTableEntries;
+    List<CttsTableEntry> mCttsTableEntries;
+
     // Sequence parameter set or picture parameter set
     struct AVCParamSet {
         AVCParamSet(uint16_t length, const uint8_t *data)
@@ -219,6 +230,7 @@
 
     // Duration is time scale based
     void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
+    void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
     void sendTrackSummary(bool hasMultipleTracks);
 
     // Write the boxes
@@ -227,6 +239,7 @@
     void writeStszBox();
     void writeStssBox();
     void writeSttsBox();
+    void writeCttsBox();
     void writeD263Box();
     void writePaspBox();
     void writeAvccBox();
@@ -1147,6 +1160,7 @@
         mEstimatedTrackSizeBytes += mNumStscTableEntries * 12 +  // stsc box size
                                     mNumStssTableEntries * 4 +   // stss box size
                                     mNumSttsTableEntries * 8 +   // stts box size
+                                    mNumCttsTableEntries * 8 +   // ctts box size
                                     stcoBoxSizeBytes +           // stco box size
                                     stszBoxSizeBytes;            // stsz box size
     }
@@ -1173,6 +1187,20 @@
     ++mNumSttsTableEntries;
 }
 
+void MPEG4Writer::Track::addOneCttsTableEntry(
+        size_t sampleCount, int32_t duration) {
+
+    if (mIsAudio) {
+        return;
+    }
+    if (duration < 0 && !mHasNegativeCttsDeltaDuration) {
+        mHasNegativeCttsDeltaDuration = true;
+    }
+    CttsTableEntry cttsEntry(sampleCount, duration);
+    mCttsTableEntries.push_back(cttsEntry);
+    ++mNumCttsTableEntries;
+}
+
 void MPEG4Writer::Track::addChunkOffset(off64_t offset) {
     ++mNumStcoTableEntries;
     mChunkOffsets.push_back(offset);
@@ -1483,6 +1511,7 @@
     mNumStssTableEntries = 0;
     mNumStscTableEntries = 0;
     mNumSttsTableEntries = 0;
+    mNumCttsTableEntries = 0;
     mMdatSizeBytes = 0;
     mIsMediaTimeAdjustmentOn = false;
     mPrevMediaTimeAdjustTimestampUs = 0;
@@ -1491,6 +1520,7 @@
     mTotalDriftTimeToAdjustUs = 0;
     mPrevTotalAccumDriftTimeUs = 0;
     mMaxChunkDurationUs = 0;
+    mHasNegativeCttsDeltaDuration = false;
 
     pthread_create(&mThread, &attr, ThreadWrapper, this);
     pthread_attr_destroy(&attr);
@@ -1932,14 +1962,19 @@
     int64_t chunkTimestampUs = 0;
     int32_t nChunks = 0;
     int32_t nZeroLengthFrames = 0;
-    int64_t lastTimestampUs = 0;  // Previous sample time stamp in ms
-    int64_t lastDurationUs = 0;   // Between the previous two samples in ms
-    int64_t currDurationTicks = 0;  // Timescale based ticks
-    int64_t lastDurationTicks = 0;  // Timescale based ticks
-    int32_t sampleCount = 1;      // Sample count in the current stts table entry
-    uint32_t previousSampleSize = 0;  // Size of the previous sample
+    int64_t lastTimestampUs = 0;      // Previous sample time stamp
+    int64_t lastCttsTimeUs = 0;       // Previous sample time stamp
+    int64_t lastDurationUs = 0;       // Between the previous two samples
+    int64_t currDurationTicks = 0;    // Timescale based ticks
+    int64_t lastDurationTicks = 0;    // Timescale based ticks
+    int32_t sampleCount = 1;          // Sample count in the current stts table entry
+    int64_t currCttsDurTicks = 0;     // Timescale based ticks
+    int64_t lastCttsDurTicks = 0;     // Timescale based ticks
+    int32_t cttsSampleCount = 1;      // Sample count in the current ctts table entry
+    uint32_t previousSampleSize = 0;      // Size of the previous sample
     int64_t previousPausedDurationUs = 0;
-    int64_t timestampUs;
+    int64_t timestampUs = 0;
+    int64_t cttsDeltaTimeUs = 0;
 
     if (mIsAudio) {
         prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
@@ -2063,7 +2098,6 @@
          *
          */
         CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
-        LOGV("%s timestampUs: %lld", mIsAudio? "Audio": "Video", timestampUs);
 
 ////////////////////////////////////////////////////////////////////////////////
         if (mNumSamples == 0) {
@@ -2084,6 +2118,24 @@
 
         timestampUs -= previousPausedDurationUs;
         CHECK(timestampUs >= 0);
+        if (!mIsAudio) {
+            /*
+             * Composition time: timestampUs
+             * Decoding time: decodingTimeUs
+             * Composition time delta = composition time - decoding time
+             *
+             * We save picture decoding time stamp delta in stts table entries,
+             * and composition time delta duration in ctts table entries.
+             */
+            int64_t decodingTimeUs;
+            CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
+            decodingTimeUs -= previousPausedDurationUs;
+            int64_t timeUs = decodingTimeUs;
+            cttsDeltaTimeUs = timestampUs - decodingTimeUs;
+            timestampUs = decodingTimeUs;
+            LOGV("decoding time: %lld and ctts delta time: %lld",
+                timestampUs, cttsDeltaTimeUs);
+        }
 
         // Media time adjustment for real-time applications
         if (mIsRealTimeRecording) {
@@ -2139,6 +2191,18 @@
             } else {
                 ++sampleCount;
             }
+
+            if (!mIsAudio) {
+                currCttsDurTicks =
+                     ((cttsDeltaTimeUs * mTimeScale + 500000LL) / 1000000LL -
+                     (lastCttsTimeUs * mTimeScale + 500000LL) / 1000000LL);
+                if (currCttsDurTicks != lastCttsDurTicks) {
+                    addOneCttsTableEntry(cttsSampleCount, lastCttsDurTicks);
+                    cttsSampleCount = 1;
+                } else {
+                    ++cttsSampleCount;
+                }
+            }
         }
         if (mSamplesHaveSameSize) {
             if (mNumSamples >= 2 && previousSampleSize != sampleSize) {
@@ -2152,6 +2216,11 @@
         lastDurationTicks = currDurationTicks;
         lastTimestampUs = timestampUs;
 
+        if (!mIsAudio) {
+            lastCttsDurTicks = currCttsDurTicks;
+            lastCttsTimeUs = cttsDeltaTimeUs;
+        }
+
         if (isSync != 0) {
             addOneStssTableEntry(mNumSamples);
         }
@@ -2221,8 +2290,10 @@
     if (mNumSamples == 1) {
         lastDurationUs = 0;  // A single sample's duration
         lastDurationTicks = 0;
+        lastCttsDurTicks = 0;
     } else {
         ++sampleCount;  // Count for the last sample
+        ++cttsSampleCount;
     }
 
     if (mNumSamples <= 2) {
@@ -2234,6 +2305,7 @@
         addOneSttsTableEntry(sampleCount, lastDurationTicks);
     }
 
+    addOneCttsTableEntry(cttsSampleCount, lastCttsDurTicks);
     mTrackDurationUs += lastDurationUs;
     mReachedEOS = true;
 
@@ -2432,6 +2504,7 @@
     }
     mOwner->endBox();  // stsd
     writeSttsBox();
+    writeCttsBox();
     if (!mIsAudio) {
         writeStssBox();
     }
@@ -2782,13 +2855,49 @@
     int32_t dur = (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL;
     mOwner->writeInt32(dur + it->sampleDuration);
 
+    int64_t totalCount = 1;
     while (++it != mSttsTableEntries.end()) {
         mOwner->writeInt32(it->sampleCount);
         mOwner->writeInt32(it->sampleDuration);
+        totalCount += it->sampleCount;
     }
+    CHECK(totalCount == mNumSamples);
     mOwner->endBox();  // stts
 }
 
+void MPEG4Writer::Track::writeCttsBox() {
+    if (mIsAudio) {  // ctts is not for audio
+        return;
+    }
+
+    // Do not write ctts box when there is no need to have it.
+    if ((mNumCttsTableEntries == 1 &&
+        mCttsTableEntries.begin()->sampleDuration == 0) ||
+        mNumCttsTableEntries == 0) {
+        return;
+    }
+
+    LOGV("ctts box has %d entries", mNumCttsTableEntries);
+
+    mOwner->beginBox("ctts");
+    if (mHasNegativeCttsDeltaDuration) {
+        mOwner->writeInt32(0x00010000);  // version=1, flags=0
+    } else {
+        mOwner->writeInt32(0);  // version=0, flags=0
+    }
+    mOwner->writeInt32(mNumCttsTableEntries);
+
+    int64_t totalCount = 0;
+    for (List<CttsTableEntry>::iterator it = mCttsTableEntries.begin();
+         it != mCttsTableEntries.end(); ++it) {
+        mOwner->writeInt32(it->sampleCount);
+        mOwner->writeInt32(it->sampleDuration);
+        totalCount += it->sampleCount;
+    }
+    CHECK(totalCount == mNumSamples);
+    mOwner->endBox();  // ctts
+}
+
 void MPEG4Writer::Track::writeStssBox() {
     mOwner->beginBox("stss");
     mOwner->writeInt32(0);  // version=0, flags=0
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 72d0d08..c4fcc79 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1981,6 +1981,20 @@
     return bufInfo;
 }
 
+int64_t OMXCodec::retrieveDecodingTimeUs(bool isCodecSpecific) {
+    CHECK(mIsEncoder);
+    CHECK(!mDecodingTimeList.empty());
+    List<int64_t>::iterator it = mDecodingTimeList.begin();
+    int64_t timeUs = *it;
+
+    // If the output buffer is codec specific configuration,
+    // do not remove the decoding time from the list.
+    if (!isCodecSpecific) {
+        mDecodingTimeList.erase(it);
+    }
+    return timeUs;
+}
+
 void OMXCodec::on_message(const omx_message &msg) {
     if (mState == ERROR) {
         LOGW("Dropping OMX message - we're in ERROR state.");
@@ -2128,14 +2142,21 @@
                 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_SYNCFRAME) {
                     buffer->meta_data()->setInt32(kKeyIsSyncFrame, true);
                 }
+                bool isCodecSpecific = false;
                 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_CODECCONFIG) {
                     buffer->meta_data()->setInt32(kKeyIsCodecConfig, true);
+                    isCodecSpecific = true;
                 }
 
                 if (isGraphicBuffer || mQuirks & kOutputBuffersAreUnreadable) {
                     buffer->meta_data()->setInt32(kKeyIsUnreadable, true);
                 }
 
+                if (mIsEncoder) {
+                    int64_t decodingTimeUs = retrieveDecodingTimeUs(isCodecSpecific);
+                    buffer->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs);
+                }
+
                 buffer->meta_data()->setPointer(
                         kKeyPlatformPrivate,
                         msg.u.extended_buffer_data.platform_private);
@@ -2938,6 +2959,9 @@
         int64_t lastBufferTimeUs;
         CHECK(srcBuffer->meta_data()->findInt64(kKeyTime, &lastBufferTimeUs));
         CHECK(lastBufferTimeUs >= 0);
+        if (mIsEncoder) {
+            mDecodingTimeList.push_back(lastBufferTimeUs);
+        }
 
         if (offset == 0) {
             timestampUs = lastBufferTimeUs;
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 2e2768f..b349030 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -77,8 +77,6 @@
     <!-- Default for Settings.System.VIBRATE_IN_SILENT -->
     <bool name="def_vibrate_in_silent">true</bool>
 
-    <bool name="def_use_ptp_interface">false</bool>
-
     <!-- Default for Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION -->
     <bool name="def_accessibility_script_injection">false</bool>
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 9cbf704..47ab150 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -1209,9 +1209,6 @@
             loadBooleanSetting(stmt, Settings.System.VIBRATE_IN_SILENT,
                     R.bool.def_vibrate_in_silent);
 
-            loadBooleanSetting(stmt, Settings.System.USE_PTP_INTERFACE,
-                    R.bool.def_use_ptp_interface);
-
             // Set notification volume to follow ringer volume by default
             loadBooleanSetting(stmt, Settings.System.NOTIFICATIONS_USE_RING_VOLUME,
                     R.bool.def_notifications_use_ring_volume);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 3d15a1d..687de07 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -349,7 +349,8 @@
                     | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                     | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                     | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
+                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+                    | WindowManager.LayoutParams.FLAG_SLIPPERY,
                 PixelFormat.TRANSLUCENT);
 
         lp.setTitle("NavigationBar");
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index 0178395..08f9ebb 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -587,7 +587,7 @@
             case SimMissing:
                 // text
                 mStatusView.setCarrierText(R.string.lockscreen_missing_sim_message_short);
-                mScreenLocked.setText(R.string.lockscreen_missing_sim_instructions);
+                mScreenLocked.setText(R.string.lockscreen_missing_sim_instructions_long);
 
                 // layout
                 mScreenLocked.setVisibility(View.VISIBLE);
@@ -710,11 +710,17 @@
         if (mEnergyWave != null) {
             mEnergyWave.reset();
         }
+        if (mMultiWaveView != null) {
+            mMultiWaveView.reset(false);
+        }
     }
 
     /** {@inheritDoc} */
     public void onResume() {
         resetStatusInfo(mUpdateMonitor);
+        if (mMultiWaveView != null) {
+            mMultiWaveView.ping();
+        }
     }
 
     /** {@inheritDoc} */
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index d4a8ddb..44df5b5 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -44,7 +44,7 @@
 #include <private/media/AudioEffectShared.h>
 
 #include <system/audio.h>
-#include <hardware/audio_hal.h>
+#include <hardware/audio.h>
 
 #include "AudioMixer.h"
 #include "AudioFlinger.h"
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index f3371bf..1fad987 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -39,7 +39,7 @@
 #include <binder/MemoryDealer.h>
 
 #include <system/audio.h>
-#include <hardware/audio_hal.h>
+#include <hardware/audio.h>
 
 #include "AudioBufferProvider.h"
 
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index dd91788..47ca3a0 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -36,8 +36,8 @@
 
 #include <hardware/hardware.h>
 #include <system/audio.h>
+#include <system/audio_policy.h>
 #include <hardware/audio_policy.h>
-#include <hardware/audio_policy_hal.h>
 
 namespace android {
 
diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h
index d9b5ada..b830120 100644
--- a/services/audioflinger/AudioPolicyService.h
+++ b/services/audioflinger/AudioPolicyService.h
@@ -23,8 +23,8 @@
 #include <binder/BinderService.h>
 
 #include <system/audio.h>
+#include <system/audio_policy.h>
 #include <hardware/audio_policy.h>
-#include <hardware/audio_policy_hal.h>
 
 namespace android {
 
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index eff65c2..28df3fb 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -1412,6 +1412,50 @@
             injectionResult = INPUT_EVENT_INJECTION_FAILED;
             goto Failed;
         }
+
+        // Check whether touches should slip outside of the current foreground window.
+        if (maskedAction == AMOTION_EVENT_ACTION_MOVE
+                && entry->pointerCount == 1
+                && mTempTouchState.isSlippery()) {
+            const MotionSample* sample = &entry->firstSample;
+            int32_t x = int32_t(sample->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X));
+            int32_t y = int32_t(sample->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
+
+            const InputWindow* oldTouchedWindow = mTempTouchState.getFirstForegroundWindow();
+            const InputWindow* newTouchedWindow = findTouchedWindowAtLocked(x, y);
+            if (oldTouchedWindow != newTouchedWindow && newTouchedWindow) {
+#if DEBUG_FOCUS
+                LOGD("Touch is slipping out of window %s into window %s.",
+                        oldTouchedWindow->name.string(), newTouchedWindow->name.string());
+#endif
+                // Make a slippery exit from the old window.
+                mTempTouchState.addOrUpdateWindow(oldTouchedWindow,
+                        InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT, BitSet32(0));
+
+                // Make a slippery entrance into the new window.
+                if (newTouchedWindow->supportsSplitTouch()) {
+                    isSplit = true;
+                }
+
+                int32_t targetFlags = InputTarget::FLAG_FOREGROUND
+                        | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER;
+                if (isSplit) {
+                    targetFlags |= InputTarget::FLAG_SPLIT;
+                }
+                if (isWindowObscuredAtPointLocked(newTouchedWindow, x, y)) {
+                    targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
+                }
+
+                BitSet32 pointerIds;
+                if (isSplit) {
+                    pointerIds.markBit(entry->pointerProperties[0].id);
+                }
+                mTempTouchState.addOrUpdateWindow(newTouchedWindow, targetFlags, pointerIds);
+
+                // Split the batch here so we send exactly one sample.
+                *outSplitBatchAfterSample = &entry->firstSample;
+            }
+        }
     }
 
     if (newHoverWindow != mLastHoverWindow) {
@@ -1884,6 +1928,10 @@
             resumeWithAppendedMotionSample, InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);
     enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
             resumeWithAppendedMotionSample, InputTarget::FLAG_DISPATCH_AS_IS);
+    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
+            resumeWithAppendedMotionSample, InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);
+    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
+            resumeWithAppendedMotionSample, InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);
 
     // If the outbound queue was previously empty, start the dispatch cycle going.
     if (wasEmpty && !connection->outboundQueue.isEmpty()) {
@@ -1985,6 +2033,10 @@
             action = AMOTION_EVENT_ACTION_HOVER_EXIT;
         } else if (dispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER) {
             action = AMOTION_EVENT_ACTION_HOVER_ENTER;
+        } else if (dispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
+            action = AMOTION_EVENT_ACTION_CANCEL;
+        } else if (dispatchEntry->targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER) {
+            action = AMOTION_EVENT_ACTION_DOWN;
         }
         if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
             flags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
@@ -4386,6 +4438,9 @@
         TouchedWindow& touchedWindow = windows.editItemAt(i);
         if (touchedWindow.window == window) {
             touchedWindow.targetFlags |= targetFlags;
+            if (targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
+                touchedWindow.targetFlags &= ~InputTarget::FLAG_DISPATCH_AS_IS;
+            }
             touchedWindow.pointerIds.value |= pointerIds.value;
             return;
         }
@@ -4403,7 +4458,8 @@
 void InputDispatcher::TouchState::filterNonAsIsTouchWindows() {
     for (size_t i = 0 ; i < windows.size(); ) {
         TouchedWindow& window = windows.editItemAt(i);
-        if (window.targetFlags & InputTarget::FLAG_DISPATCH_AS_IS) {
+        if (window.targetFlags & (InputTarget::FLAG_DISPATCH_AS_IS
+                | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER)) {
             window.targetFlags &= ~InputTarget::FLAG_DISPATCH_MASK;
             window.targetFlags |= InputTarget::FLAG_DISPATCH_AS_IS;
             i += 1;
@@ -4413,15 +4469,32 @@
     }
 }
 
-const InputWindow* InputDispatcher::TouchState::getFirstForegroundWindow() {
+const InputWindow* InputDispatcher::TouchState::getFirstForegroundWindow() const {
     for (size_t i = 0; i < windows.size(); i++) {
-        if (windows[i].targetFlags & InputTarget::FLAG_FOREGROUND) {
-            return windows[i].window;
+        const TouchedWindow& window = windows.itemAt(i);
+        if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
+            return window.window;
         }
     }
     return NULL;
 }
 
+bool InputDispatcher::TouchState::isSlippery() const {
+    // Must have exactly one foreground window.
+    bool haveSlipperyForegroundWindow = false;
+    for (size_t i = 0; i < windows.size(); i++) {
+        const TouchedWindow& window = windows.itemAt(i);
+        if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
+            if (haveSlipperyForegroundWindow
+                    || !(window.window->layoutParamsFlags & InputWindow::FLAG_SLIPPERY)) {
+                return false;
+            }
+            haveSlipperyForegroundWindow = true;
+        }
+    }
+    return haveSlipperyForegroundWindow;
+}
+
 
 // --- InputDispatcherThread ---
 
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index 39d4aeb..676d162 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -121,11 +121,23 @@
          * The event is transmuted into ACTION_HOVER_ENTER. */
         FLAG_DISPATCH_AS_HOVER_EXIT = 1 << 11,
 
+        /* This flag indicates that the event should be canceled.
+         * It is used to transmute ACTION_MOVE into ACTION_CANCEL when a touch slips
+         * outside of a window. */
+        FLAG_DISPATCH_AS_SLIPPERY_EXIT = 1 << 12,
+
+        /* This flag indicates that the event should be dispatched as an initial down.
+         * It is used to transmute ACTION_MOVE into ACTION_DOWN when a touch slips
+         * into a new window. */
+        FLAG_DISPATCH_AS_SLIPPERY_ENTER = 1 << 13,
+
         /* Mask for all dispatch modes. */
         FLAG_DISPATCH_MASK = FLAG_DISPATCH_AS_IS
                 | FLAG_DISPATCH_AS_OUTSIDE
                 | FLAG_DISPATCH_AS_HOVER_ENTER
-                | FLAG_DISPATCH_AS_HOVER_EXIT,
+                | FLAG_DISPATCH_AS_HOVER_EXIT
+                | FLAG_DISPATCH_AS_SLIPPERY_EXIT
+                | FLAG_DISPATCH_AS_SLIPPERY_ENTER,
     };
 
     // The input channel to be targeted.
@@ -950,9 +962,10 @@
         ~TouchState();
         void reset();
         void copyFrom(const TouchState& other);
-        void addOrUpdateWindow(const InputWindow* window, int32_t targetFlags, BitSet32 pointerIds);
+        void addOrUpdateWindow(const InputWindow* window,int32_t targetFlags, BitSet32 pointerIds);
         void filterNonAsIsTouchWindows();
-        const InputWindow* getFirstForegroundWindow();
+        const InputWindow* getFirstForegroundWindow() const;
+        bool isSlippery() const;
     };
 
     TouchState mTouchState;
diff --git a/services/input/InputWindow.h b/services/input/InputWindow.h
index d7d819d..93c9b5f 100644
--- a/services/input/InputWindow.h
+++ b/services/input/InputWindow.h
@@ -80,6 +80,10 @@
         FLAG_TURN_SCREEN_ON = 0x00200000,
         FLAG_DISMISS_KEYGUARD = 0x00400000,
         FLAG_SPLIT_TOUCH = 0x00800000,
+        FLAG_HARDWARE_ACCELERATED = 0x01000000,
+        FLAG_HARDWARE_ACCELERATED_SYSTEM = 0x02000000,
+        FLAG_SLIPPERY = 0x04000000,
+        FLAG_NEEDS_MENU_KEY = 0x08000000,
         FLAG_KEEP_SURFACE_WHILE_ANIMATING = 0x10000000,
         FLAG_COMPATIBLE_WINDOW = 0x20000000,
         FLAG_SYSTEM_ERROR = 0x40000000,
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 367c802..4ecdfed 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -27,7 +27,6 @@
 import android.app.PendingIntent;
 import android.app.StatusBarManager;
 import android.content.BroadcastReceiver;
-import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -37,7 +36,6 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
 import android.database.ContentObserver;
-import android.hardware.usb.UsbManager;
 import android.media.AudioManager;
 import android.net.Uri;
 import android.os.Binder;
@@ -47,7 +45,6 @@
 import android.os.Message;
 import android.os.Process;
 import android.os.RemoteException;
-import android.os.SystemProperties;
 import android.os.Vibrator;
 import android.provider.Settings;
 import android.telephony.TelephonyManager;
@@ -112,10 +109,6 @@
     // This is reset to false when the screen is turned on.
     private boolean mPendingPulseNotification;
 
-    // for adb connected notifications
-    private boolean mAdbNotificationShown = false;
-    private Notification mAdbNotification;
-
     private final ArrayList<NotificationRecord> mNotificationList =
             new ArrayList<NotificationRecord>();
 
@@ -330,12 +323,7 @@
 
             boolean queryRestart = false;
             
-            if (action.equals(UsbManager.ACTION_USB_STATE)) {
-                Bundle extras = intent.getExtras();
-                boolean usbConnected = extras.getBoolean(UsbManager.USB_CONNECTED);
-                boolean adbEnabled = extras.getBoolean(UsbManager.USB_FUNCTION_ADB);
-                updateAdbNotification(usbConnected && adbEnabled);
-            } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
+            if (action.equals(Intent.ACTION_PACKAGE_REMOVED)
                     || action.equals(Intent.ACTION_PACKAGE_RESTARTED)
                     || (queryRestart=action.equals(Intent.ACTION_QUERY_PACKAGE_RESTART))
                     || action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
@@ -436,7 +424,6 @@
 
         // register for various Intents
         IntentFilter filter = new IntentFilter();
-        filter.addAction(UsbManager.ACTION_USB_STATE);
         filter.addAction(Intent.ACTION_SCREEN_ON);
         filter.addAction(Intent.ACTION_SCREEN_OFF);
         filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
@@ -1116,67 +1103,6 @@
         return -1;
     }
 
-    // This is here instead of StatusBarPolicy because it is an important
-    // security feature that we don't want people customizing the platform
-    // to accidentally lose.
-    private void updateAdbNotification(boolean adbEnabled) {
-        if (adbEnabled) {
-            if ("0".equals(SystemProperties.get("persist.adb.notify"))) {
-                return;
-            }
-            if (!mAdbNotificationShown) {
-                NotificationManager notificationManager = (NotificationManager) mContext
-                        .getSystemService(Context.NOTIFICATION_SERVICE);
-                if (notificationManager != null) {
-                    Resources r = mContext.getResources();
-                    CharSequence title = r.getText(
-                            com.android.internal.R.string.adb_active_notification_title);
-                    CharSequence message = r.getText(
-                            com.android.internal.R.string.adb_active_notification_message);
-
-                    if (mAdbNotification == null) {
-                        mAdbNotification = new Notification();
-                        mAdbNotification.icon = com.android.internal.R.drawable.stat_sys_adb;
-                        mAdbNotification.when = 0;
-                        mAdbNotification.flags = Notification.FLAG_ONGOING_EVENT;
-                        mAdbNotification.tickerText = title;
-                        mAdbNotification.defaults = 0; // please be quiet
-                        mAdbNotification.sound = null;
-                        mAdbNotification.vibrate = null;
-                    }
-
-                    Intent intent = new Intent(
-                            Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
-                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
-                            Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
-                    // Note: we are hard-coding the component because this is
-                    // an important security UI that we don't want anyone
-                    // intercepting.
-                    intent.setComponent(new ComponentName("com.android.settings",
-                            "com.android.settings.DevelopmentSettings"));
-                    PendingIntent pi = PendingIntent.getActivity(mContext, 0,
-                            intent, 0);
-
-                    mAdbNotification.setLatestEventInfo(mContext, title, message, pi);
-
-                    mAdbNotificationShown = true;
-                    notificationManager.notify(
-                            com.android.internal.R.string.adb_active_notification_title,
-                            mAdbNotification);
-                }
-            }
-
-        } else if (mAdbNotificationShown) {
-            NotificationManager notificationManager = (NotificationManager) mContext
-                    .getSystemService(Context.NOTIFICATION_SERVICE);
-            if (notificationManager != null) {
-                mAdbNotificationShown = false;
-                notificationManager.cancel(
-                        com.android.internal.R.string.adb_active_notification_title);
-            }
-        }
-    }
-
     private void updateNotificationPulse() {
         synchronized (mNotificationList) {
             updateLightsLocked();
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 3484baf..a820139 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -26,7 +26,6 @@
 import android.content.Intent;
 import android.content.pm.IPackageManager;
 import android.content.res.Configuration;
-import android.database.ContentObserver;
 import android.media.AudioService;
 import android.os.Looper;
 import android.os.RemoteException;
@@ -66,19 +65,6 @@
 
     ContentResolver mContentResolver;
 
-    private class AdbSettingsObserver extends ContentObserver {
-        public AdbSettingsObserver() {
-            super(null);
-        }
-        @Override
-        public void onChange(boolean selfChange) {
-            boolean enableAdb = (Settings.Secure.getInt(mContentResolver,
-                Settings.Secure.ADB_ENABLED, 0) > 0);
-            // setting this secure property will start or stop adbd
-           SystemProperties.set("persist.service.adb.enable", enableAdb ? "1" : "0");
-        }
-    }
-
     @Override
     public void run() {
         EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN,
@@ -485,14 +471,6 @@
             }
         }
 
-        // make sure the ADB_ENABLED setting value matches the secure property value
-        Settings.Secure.putInt(mContentResolver, Settings.Secure.ADB_ENABLED,
-                "1".equals(SystemProperties.get("persist.service.adb.enable")) ? 1 : 0);
-
-        // register observer to listen for settings changes
-        mContentResolver.registerContentObserver(Settings.Secure.getUriFor(Settings.Secure.ADB_ENABLED),
-                false, new AdbSettingsObserver());
-
         // Before things start rolling, be sure we have decided whether
         // we are in safe mode.
         final boolean safeMode = wm.detectSafeMode();
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index e7d60638..99569a8 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -385,10 +385,6 @@
     private void ensureActiveMobilePolicyLocked() {
         if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()");
         final String subscriberId = getActiveSubscriberId();
-        if (subscriberId == null) {
-            if (LOGV) Slog.v(TAG, "no active mobile network, ignoring policy check");
-            return;
-        }
 
         // examine to see if any policy is defined for active mobile
         boolean mobileDefined = false;
@@ -412,6 +408,7 @@
 
             mNetworkPolicy.add(new NetworkPolicy(
                     TEMPLATE_MOBILE_ALL, subscriberId, cycleDay, 4 * GB_IN_BYTES, LIMIT_DISABLED));
+            writePolicyLocked();
         }
     }
 
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index 95008e5..ca8a184 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -17,12 +17,17 @@
 package com.android.server.usb;
 
 import android.app.PendingIntent;
+import android.app.Notification;
+import android.app.NotificationManager;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.database.ContentObserver;
 import android.hardware.usb.UsbAccessory;
 import android.hardware.usb.UsbManager;
 import android.net.Uri;
@@ -32,6 +37,7 @@
 import android.os.Message;
 import android.os.Parcelable;
 import android.os.ParcelFileDescriptor;
+import android.os.SystemProperties;
 import android.os.UEventObserver;
 import android.provider.Settings;
 import android.util.Log;
@@ -92,10 +98,81 @@
     private final ArrayList<String> mDefaultFunctions = new ArrayList<String>();
 
     private final Context mContext;
+    ContentResolver mContentResolver;
     private final Object mLock = new Object();
     private final UsbSettingsManager mSettingsManager;
+    private NotificationManager mNotificationManager;
     private final boolean mHasUsbAccessory;
 
+    // for adb connected notifications
+    private boolean mAdbNotificationShown = false;
+    private Notification mAdbNotification;
+    private boolean mAdbEnabled;
+
+    private class AdbSettingsObserver extends ContentObserver {
+        public AdbSettingsObserver() {
+            super(null);
+        }
+        @Override
+        public void onChange(boolean selfChange) {
+            mAdbEnabled = (Settings.Secure.getInt(mContentResolver,
+                Settings.Secure.ADB_ENABLED, 0) > 0);
+            // setting this secure property will start or stop adbd
+           SystemProperties.set("persist.service.adb.enable", mAdbEnabled ? "1" : "0");
+           updateAdbNotification();
+        }
+    }
+
+    private void updateAdbNotification() {
+        if (mNotificationManager == null) return;
+        boolean adbEnabled = mAdbEnabled && (mConnected == 1);
+        if (adbEnabled) {
+            if ("0".equals(SystemProperties.get("persist.adb.notify"))) return;
+
+            if (!mAdbNotificationShown) {
+                Resources r = mContext.getResources();
+                CharSequence title = r.getText(
+                        com.android.internal.R.string.adb_active_notification_title);
+                CharSequence message = r.getText(
+                        com.android.internal.R.string.adb_active_notification_message);
+
+                if (mAdbNotification == null) {
+                    mAdbNotification = new Notification();
+                    mAdbNotification.icon = com.android.internal.R.drawable.stat_sys_adb;
+                    mAdbNotification.when = 0;
+                    mAdbNotification.flags = Notification.FLAG_ONGOING_EVENT;
+                    mAdbNotification.tickerText = title;
+                    mAdbNotification.defaults = 0; // please be quiet
+                    mAdbNotification.sound = null;
+                    mAdbNotification.vibrate = null;
+                }
+
+                Intent intent = new Intent(
+                        Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
+                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+                        Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+                // Note: we are hard-coding the component because this is
+                // an important security UI that we don't want anyone
+                // intercepting.
+                intent.setComponent(new ComponentName("com.android.settings",
+                        "com.android.settings.DevelopmentSettings"));
+                PendingIntent pi = PendingIntent.getActivity(mContext, 0,
+                        intent, 0);
+
+                mAdbNotification.setLatestEventInfo(mContext, title, message, pi);
+
+                mAdbNotificationShown = true;
+                mNotificationManager.notify(
+                        com.android.internal.R.string.adb_active_notification_title,
+                        mAdbNotification);
+            }
+        } else if (mAdbNotificationShown) {
+            mAdbNotificationShown = false;
+            mNotificationManager.cancel(
+                    com.android.internal.R.string.adb_active_notification_title);
+        }
+    }
+
     private final void readCurrentAccessoryLocked() {
         if (mHasUsbAccessory) {
             String[] strings = nativeGetAccessoryStrings();
@@ -191,6 +268,7 @@
 
     public UsbDeviceManager(Context context, UsbSettingsManager settingsManager) {
         mContext = context;
+        mContentResolver = context.getContentResolver();
         mSettingsManager = settingsManager;
         PackageManager pm = mContext.getPackageManager();
         mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY);
@@ -198,6 +276,16 @@
         synchronized (mLock) {
             init();  // set initial status
 
+            // make sure the ADB_ENABLED setting value matches the secure property value
+            mAdbEnabled = "1".equals(SystemProperties.get("persist.service.adb.enable"));
+            Settings.Secure.putInt(mContentResolver, Settings.Secure.ADB_ENABLED,
+                    mAdbEnabled ? 1 : 0);
+
+            // register observer to listen for settings changes
+            mContentResolver.registerContentObserver(
+                    Settings.Secure.getUriFor(Settings.Secure.ADB_ENABLED),
+                            false, new AdbSettingsObserver());
+
             // Watch for USB configuration changes
             if (mConfiguration >= 0) {
                 mUEventObserver.startObserving(USB_CONNECTED_MATCH);
@@ -281,6 +369,9 @@
 
     public void systemReady() {
         synchronized (mLock) {
+                mNotificationManager = (NotificationManager)
+                        mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+
             update(false);
             if (mCurrentAccessory != null) {
                 Log.d(TAG, "accessoryAttached at systemReady");
@@ -335,6 +426,7 @@
                 switch (msg.what) {
                     case MSG_UPDATE_STATE:
                         if (mConnected != mLastConnected || mConfiguration != mLastConfiguration) {
+                            updateAdbNotification();
                             if (mConnected == 0) {
                                 if (UsbManager.isFunctionEnabled(
                                             UsbManager.USB_FUNCTION_ACCESSORY)) {
diff --git a/services/jni/com_android_server_connectivity_Vpn.cpp b/services/jni/com_android_server_connectivity_Vpn.cpp
index b3d38dc..206df25 100644
--- a/services/jni/com_android_server_connectivity_Vpn.cpp
+++ b/services/jni/com_android_server_connectivity_Vpn.cpp
@@ -46,14 +46,6 @@
     return &((sockaddr_in *)sa)->sin_addr.s_addr;
 }
 
-static inline in_addr_t *as_in_addr(sockaddr_storage *ss) {
-    return &((sockaddr_in *)ss)->sin_addr.s_addr;
-}
-
-static inline in6_addr *as_in6_addr(sockaddr_storage *ss) {
-    return &((sockaddr_in6 *)&ss)->sin6_addr;
-}
-
 //------------------------------------------------------------------------------
 
 #define SYSTEM_ERROR -1
@@ -193,7 +185,6 @@
     rt4.rt_flags = RTF_UP;
     rt4.rt_dst.sa_family = AF_INET;
     rt4.rt_genmask.sa_family = AF_INET;
-    rt4.rt_gateway.sa_family = AF_INET;
 
     in6_rtmsg rt6;
     memset(&rt6, 0, sizeof(rt6));
@@ -202,60 +193,50 @@
 
     char address[65];
     int prefix;
-    char gateway[65];
 
     int chars;
     int count = 0;
 
-    while (sscanf(routes, " %64[^/]/%d>%64[^ ] %n",
-            address, &prefix, gateway, &chars) == 3) {
+    while (sscanf(routes, " %64[^/]/%d %n", address, &prefix, &chars) == 2) {
         routes += chars;
 
         if (strchr(address, ':')) {
             // Add an IPv6 route.
-            if (inet_pton(AF_INET6, gateway, &rt6.rtmsg_gateway) != 1 ||
-                    inet_pton(AF_INET6, address, &rt6.rtmsg_dst) != 1 ||
-                    prefix < 0 || prefix > 128) {
+            if (inet_pton(AF_INET6, address, &rt6.rtmsg_dst) != 1 ||
+                    prefix < 1 || prefix > 128) {
                 count = BAD_ARGUMENT;
                 break;
             }
 
             rt6.rtmsg_dst_len = prefix;
-            if (memcmp(&rt6.rtmsg_gateway, &in6addr_any, sizeof(in6addr_any))) {
-                rt6.rtmsg_flags |= RTF_GATEWAY;
-            }
             if (ioctl(inet6, SIOCADDRT, &rt6) && errno != EEXIST) {
                 count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR;
                 break;
             }
         } else {
             // Add an IPv4 route.
-            if (inet_pton(AF_INET, gateway, as_in_addr(&rt4.rt_gateway)) != 1 ||
-                    inet_pton(AF_INET, address, as_in_addr(&rt4.rt_dst)) != 1 ||
-                    prefix < 0 || prefix > 32) {
+            if (inet_pton(AF_INET, address, as_in_addr(&rt4.rt_dst)) != 1 ||
+                    prefix < 1 || prefix > 32) {
                 count = BAD_ARGUMENT;
                 break;
             }
 
             in_addr_t mask = prefix ? (~0 << (32 - prefix)) : 0;
             *as_in_addr(&rt4.rt_genmask) = htonl(mask);
-            if (*as_in_addr(&rt4.rt_gateway)) {
-                rt4.rt_flags |= RTF_GATEWAY;
-            }
             if (ioctl(inet4, SIOCADDRT, &rt4) && errno != EEXIST) {
                 count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR;
                 break;
             }
         }
-        LOGV("Route added on %s: %s/%d -> %s", name, address, prefix, gateway);
+        LOGV("Route added on %s: %s/%d", name, address, prefix);
         ++count;
     }
 
     if (count == BAD_ARGUMENT) {
-        LOGE("Invalid route: %s/%d -> %s", address, prefix, gateway);
+        LOGE("Invalid route: %s/%d", address, prefix);
     } else if (count == SYSTEM_ERROR) {
-        LOGE("Cannot add route: %s/%d -> %s: %s",
-                address, prefix, gateway, strerror(errno));
+        LOGE("Cannot add route: %s/%d: %s",
+                address, prefix, strerror(errno));
     } else if (*routes) {
         LOGE("Invalid route: %s", routes);
         count = BAD_ARGUMENT;
diff --git a/services/sensorservice/Fusion.cpp b/services/sensorservice/Fusion.cpp
index b5f97e0..d706af5 100644
--- a/services/sensorservice/Fusion.cpp
+++ b/services/sensorservice/Fusion.cpp
@@ -24,10 +24,28 @@
 
 // -----------------------------------------------------------------------
 
-static const float gyroSTDEV = 3.16e-4; // rad/s^3/2
+/*
+ * gyroVAR gives the measured variance of the gyro's output per
+ * Hz (or variance at 1 Hz). This is an "intrinsic" parameter of the gyro,
+ * which is independent of the sampling frequency.
+ *
+ * The variance of gyro's output at a given sampling period can be
+ * calculated as:
+ *      variance(T) = gyroVAR / T
+ *
+ * The variance of the INTEGRATED OUTPUT at a given sampling period can be
+ * calculated as:
+ *       variance_integrate_output(T) = gyroVAR * T
+ *
+ */
+static const float gyroVAR = 1e-7;      // (rad/s)^2 / Hz
+static const float biasVAR = 1e-8;      // (rad/s)^2 / s (guessed)
+
+/*
+ * Standard deviations of accelerometer and magnetometer
+ */
 static const float accSTDEV  = 0.05f;   // m/s^2 (measured 0.08 / CDD 0.05)
 static const float magSTDEV  = 0.5f;    // uT    (measured 0.7  / CDD 0.5)
-static const float biasSTDEV = 3.16e-5; // rad/s^1/2 (guessed)
 
 static const float FREE_FALL_THRESHOLD = 0.981f;
 
@@ -129,23 +147,34 @@
     x0 = q;
     x1 = 0;
 
-    // process noise covariance matrix
-    //  G = | -1 0 |
-    //      |  0 1 |
+    // process noise covariance matrix: G.Q.Gt, with
+    //
+    //  G = | -1 0 |        Q = | q00 q10 |
+    //      |  0 1 |            | q01 q11 |
+    //
+    // q00 = sv^2.dt + 1/3.su^2.dt^3
+    // q10 = q01 = 1/2.su^2.dt^2
+    // q11 = su^2.dt
+    //
 
-    const float v = gyroSTDEV;
-    const float u = biasSTDEV;
-    const float q00 = v*v*dT + 0.33333f*(dT*dT*dT)*u*u;
-    const float q10 =              0.5f*(dT*dT)   *u*u;
+    // variance of integrated output at 1/dT Hz
+    // (random drift)
+    const float q00 = gyroVAR * dT;
+
+    // variance of drift rate ramp
+    const float q11 = biasVAR * dT;
+
+    const float u   = q11 / dT;
+    const float q10 = 0.5f*u*dT*dT;
     const float q01 = q10;
-    const float q11 = u*u*dT;
-    GQGt[0][0] =  q00;
+
+    GQGt[0][0] =  q00;      // rad^2
     GQGt[1][0] = -q10;
     GQGt[0][1] = -q01;
-    GQGt[1][1] =  q11;
-
+    GQGt[1][1] =  q11;      // (rad/s)^2
 
     // initial covariance: Var{ x(t0) }
+    // TODO: initialize P correctly
     P = 0;
 }
 
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ClearActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ClearActivity.java
index b49db7c5..1c82e9b 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ClearActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ClearActivity.java
@@ -20,7 +20,6 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import android.graphics.BitmapShader;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Path;
@@ -79,6 +78,9 @@
                 }
                 canvas.restore();
                 canvas.drawText("OpenGLRenderer", 50.0f, 50.0f, mClearPaint);
+                mClearPaint.setColor(0xff000000);
+                canvas.drawRect(800.0f, 100.0f, 900.0f, 200.0f, mClearPaint);
+                mClearPaint.setColor(0x0000ff00);
             }
             canvas.restore();
         }