Merge "Remove dead code in StringPool."
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index ba79c9f..aa95b35 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -124,6 +124,24 @@
         dump_file("VM TRACES AT LAST ANR", anr_traces_path);
     }
 
+    /* slow traces for slow operations */
+    if (anr_traces_path[0] != 0) {
+        int tail = strlen(anr_traces_path)-1;
+        while (tail > 0 && anr_traces_path[tail] != '/') {
+            tail--;
+        }
+        int i = 0;
+        while (1) {
+            sprintf(anr_traces_path+tail+1, "slow%02d.txt", i);
+            if (stat(anr_traces_path, &st)) {
+                // No traces file at this index, done with the files.
+                break;
+            }
+            dump_file("VM TRACES WHEN SLOW", anr_traces_path);
+            i++;
+        }
+    }
+
     dump_file("NETWORK DEV INFO", "/proc/net/dev");
     dump_file("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
     dump_file("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
diff --git a/cmds/stagefright/sf2.cpp b/cmds/stagefright/sf2.cpp
index 1d28793..e47cdc0 100644
--- a/cmds/stagefright/sf2.cpp
+++ b/cmds/stagefright/sf2.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "sf2"
+#include <utils/Log.h>
+
 #include <binder/ProcessState.h>
 
 #include <media/stagefright/foundation/hexdump.h>
@@ -205,6 +209,12 @@
                     }
 
                     looper()->stop();
+                } else if (what == ACodec::kWhatError) {
+                    ALOGE("something went wrong, codec reported an error.");
+
+                    printf("E\n");
+
+                    (new AMessage(kWhatStop, id()))->post();
                 }
                 break;
             }
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index f69120a..e2b8ce4 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -557,12 +557,22 @@
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case ANIMATION_START:
-                    doAnimationStart();
+                    // If there are already active animations, or if another ANIMATION_START
+                    // message was processed during this frame, then the pending list may already
+                    // have been cleared. If that's the case, we've already processed the
+                    // active animations for this frame - don't do it again.
+                    if (mPendingAnimations.size() > 0) {
+                        doAnimationFrame();
+                    }
                     break;
             }
         }
 
-        private void doAnimationStart() {
+        private void doAnimationFrame() {
+            // currentTime holds the common time for all animations processed
+            // during this frame
+            long currentTime = AnimationUtils.currentAnimationTimeMillis();
+
             // mPendingAnimations holds any animations that have requested to be started
             // We're going to clear mPendingAnimations, but starting animation may
             // cause more to be added to the pending list (for example, if one animation
@@ -583,15 +593,7 @@
                     }
                 }
             }
-            doAnimationFrame();
-        }
-
-        private void doAnimationFrame() {
-            // currentTime holds the common time for all animations processed
-            // during this frame
-            long currentTime = AnimationUtils.currentAnimationTimeMillis();
-
-            // First, process animations currently sitting on the delayed queue, adding
+            // Next, process animations currently sitting on the delayed queue, adding
             // them to the active animations if they are ready
             int numDelayedAnims = mDelayedAnims.size();
             for (int i = 0; i < numDelayedAnims; ++i) {
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index 1a74abf..ee12989 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -31,6 +31,14 @@
  * @hide
  */
 public class NetworkIdentity {
+    /**
+     * When enabled, combine all {@link #mSubType} together under
+     * {@link #SUBTYPE_COMBINED}.
+     */
+    public static final boolean COMBINE_SUBTYPE_ENABLED = true;
+
+    public static final int SUBTYPE_COMBINED = -1;
+
     final int mType;
     final int mSubType;
     final String mSubscriberId;
@@ -38,7 +46,7 @@
 
     public NetworkIdentity(int type, int subType, String subscriberId, boolean roaming) {
         this.mType = type;
-        this.mSubType = subType;
+        this.mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType;
         this.mSubscriberId = subscriberId;
         this.mRoaming = roaming;
     }
@@ -52,9 +60,8 @@
     public boolean equals(Object obj) {
         if (obj instanceof NetworkIdentity) {
             final NetworkIdentity ident = (NetworkIdentity) obj;
-            return mType == ident.mType && mSubType == ident.mSubType
-                    && Objects.equal(mSubscriberId, ident.mSubscriberId)
-                    && mRoaming == ident.mRoaming;
+            return mType == ident.mType && mSubType == ident.mSubType && mRoaming == ident.mRoaming
+                    && Objects.equal(mSubscriberId, ident.mSubscriberId);
         }
         return false;
     }
@@ -63,7 +70,9 @@
     public String toString() {
         final String typeName = ConnectivityManager.getNetworkTypeName(mType);
         final String subTypeName;
-        if (ConnectivityManager.isNetworkTypeMobile(mType)) {
+        if (COMBINE_SUBTYPE_ENABLED) {
+            subTypeName = "COMBINED";
+        } else if (ConnectivityManager.isNetworkTypeMobile(mType)) {
             subTypeName = TelephonyManager.getNetworkTypeName(mSubType);
         } else {
             subTypeName = Integer.toString(mSubType);
@@ -130,5 +139,4 @@
         }
         return new NetworkIdentity(type, subType, subscriberId, roaming);
     }
-
 }
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index 8ebfd8d..e1fbdcc 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -20,6 +20,7 @@
 import static android.net.ConnectivityManager.TYPE_WIFI;
 import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
 import static android.net.ConnectivityManager.TYPE_WIMAX;
+import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED;
 import static android.net.NetworkIdentity.scrubSubscriberId;
 import static android.telephony.TelephonyManager.NETWORK_CLASS_2_G;
 import static android.telephony.TelephonyManager.NETWORK_CLASS_3_G;
@@ -199,6 +200,7 @@
      * Check if mobile network classified 3G or lower with matching IMSI.
      */
     private boolean matchesMobile3gLower(NetworkIdentity ident) {
+        ensureSubtypeAvailable();
         if (ident.mType == TYPE_WIMAX) {
             return false;
         } else if (matchesMobile(ident)) {
@@ -216,6 +218,7 @@
      * Check if mobile network classified 4G with matching IMSI.
      */
     private boolean matchesMobile4g(NetworkIdentity ident) {
+        ensureSubtypeAvailable();
         if (ident.mType == TYPE_WIMAX) {
             // TODO: consider matching against WiMAX subscriber identity
             return true;
@@ -268,6 +271,13 @@
         }
     }
 
+    private static void ensureSubtypeAvailable() {
+        if (COMBINE_SUBTYPE_ENABLED) {
+            throw new IllegalArgumentException(
+                    "Unable to enforce 3G_LOWER template on combined data.");
+        }
+    }
+
     public static final Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() {
         public NetworkTemplate createFromParcel(Parcel in) {
             return new NetworkTemplate(in);
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 759be91..ce213fb 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -1201,7 +1201,7 @@
             // throttled back to 60fps via SurfaceFlinger/View
             // invalidates, _not_ by posting frame updates every 16
             // milliseconds.
-            threadHandler.get().post(new Runnable() {
+            threadHandler.get().postAtFrontOfQueue(new Runnable() {
                     public void run() {
                         long loopFinishTime = SystemClock.uptimeMillis();
 
diff --git a/core/java/android/webkit/FindActionModeCallback.java b/core/java/android/webkit/FindActionModeCallback.java
index 964cf3e..6c331ac 100644
--- a/core/java/android/webkit/FindActionModeCallback.java
+++ b/core/java/android/webkit/FindActionModeCallback.java
@@ -45,7 +45,6 @@
     private int mNumberOfMatches;
     private int mActiveMatchIndex;
     private ActionMode mActionMode;
-    private String mLastFind;
 
     FindActionModeCallback(Context context) {
         mCustomView = LayoutInflater.from(context).inflate(
@@ -134,13 +133,12 @@
             mWebView.clearMatches();
             mMatches.setVisibility(View.GONE);
             mMatchesFound = false;
-            mLastFind = null;
+            mWebView.findAll(null);
         } else {
             mMatchesFound = true;
             mMatches.setVisibility(View.INVISIBLE);
             mNumberOfMatches = 0;
-            mLastFind = find.toString();
-            mWebView.findAllAsync(mLastFind);
+            mWebView.findAllAsync(find.toString());
         }
     }
 
@@ -150,9 +148,8 @@
         mInput.showSoftInput(mEditText, 0);
     }
 
-    public void updateMatchCount(int matchIndex, int matchCount,
-        String findText) {
-        if (mLastFind != null && mLastFind.equals(findText)) {
+    public void updateMatchCount(int matchIndex, int matchCount, boolean isNewFind) {
+        if (!isNewFind) {
             mNumberOfMatches = matchCount;
             mActiveMatchIndex = matchIndex;
             updateMatchesString();
diff --git a/core/java/android/webkit/FindListener.java b/core/java/android/webkit/FindListener.java
new file mode 100644
index 0000000..124f737
--- /dev/null
+++ b/core/java/android/webkit/FindListener.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+/**
+ * @hide
+ */
+public interface FindListener {
+    /**
+     * Notify the host application that a find result is available.
+     *
+     * @param numberOfMatches How many matches have been found
+     * @param activeMatchOrdinal The ordinal of the currently selected match
+     * @param isDoneCounting Whether we have finished counting matches
+     */
+    public void onFindResultReceived(int numberOfMatches,
+        int activeMatchOrdinal, boolean isDoneCounting);
+}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index a561577..5e09416 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1226,7 +1226,19 @@
 
     }
 
-    /*
+    /**
+     * Register the interface to be used when a find-on-page result has become
+     * available. This will replace the current handler.
+     *
+     * @param listener An implementation of FindListener
+     * @hide
+     */
+    public void setFindListener(FindListener listener) {
+        checkThread();
+        mProvider.setFindListener(listener);
+    }
+
+    /**
      * Highlight and scroll to the next occurance of String in findAll.
      * Wraps the page infinitely, and scrolls.  Must be called after
      * calling findAll.
@@ -1238,8 +1250,9 @@
         mProvider.findNext(forward);
     }
 
-    /*
+    /**
      * Find all instances of find on the page and highlight them.
+     *
      * @param find  String to find.
      * @return int  The number of occurances of the String "find"
      *              that were found.
@@ -1250,6 +1263,18 @@
     }
 
     /**
+     * Find all instances of find on the page and highlight them,
+     * asynchronously.
+     *
+     * @param find  String to find.
+     * @hide
+     */
+    public void findAllAsync(String find) {
+        checkThread();
+        mProvider.findAllAsync(find);
+    }
+
+    /**
      * Start an ActionMode for finding text in this WebView.  Only works if this
      *              WebView is attached to the view system.
      * @param text If non-null, will be the initial text to search for.
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index ed43043..e5434ce 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -1440,6 +1440,9 @@
     // Used to notify listeners of a new picture.
     private PictureListener mPictureListener;
 
+    // Used to notify listeners about find-on-page results.
+    private FindListener mFindListener;
+
     /**
      * Refer to {@link WebView#requestFocusNodeHref(Message)} for more information
      */
@@ -3695,6 +3698,17 @@
     }
 
     /**
+     * Register the interface to be used when a find-on-page result has become
+     * available. This will replace the current handler.
+     *
+     * @param listener An implementation of FindListener
+     */
+     public void setFindListener(FindListener listener) {
+         checkThread();
+         mFindListener = listener;
+     }
+
+    /**
      * See {@link WebView#findNext(boolean)}
      */
     @Override
@@ -3723,6 +3737,7 @@
         checkThread();
         if (0 == mNativeClass) return 0; // client isn't initialized
         mLastFind = find;
+        if (find == null) return 0;
         mWebViewCore.removeMessages(EventHub.FIND_ALL);
         WebViewCore.FindAllRequest request = new
             WebViewCore.FindAllRequest(find);
@@ -4909,11 +4924,9 @@
      */
     private void getSelectionHandles(int[] handles) {
         handles[0] = mSelectCursorBase.right;
-        handles[1] = mSelectCursorBase.bottom -
-                (mSelectCursorBase.height() / 4);
+        handles[1] = mSelectCursorBase.bottom;
         handles[2] = mSelectCursorExtent.left;
-        handles[3] = mSelectCursorExtent.bottom
-                - (mSelectCursorExtent.height() / 4);
+        handles[3] = mSelectCursorExtent.bottom;
         if (!nativeIsBaseFirst(mNativeClass)) {
             int swap = handles[0];
             handles[0] = handles[2];
@@ -8478,10 +8491,11 @@
                 }
 
                 case UPDATE_MATCH_COUNT: {
-                    if (mFindCallback != null) {
-                        mFindCallback.updateMatchCount(msg.arg1, msg.arg2,
-                            (String) msg.obj);
-                    }
+                    boolean isNewFind = mLastFind == null || !mLastFind.equals(msg.obj);
+                    if (mFindCallback != null)
+                        mFindCallback.updateMatchCount(msg.arg1, msg.arg2, isNewFind);
+                    if (mFindListener != null)
+                        mFindListener.onFindResultReceived(msg.arg1, msg.arg2, true);
                     break;
                 }
                 case CLEAR_CARET_HANDLE:
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 2e8ad6d..9016fbc 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -191,10 +191,14 @@
 
     public WebBackForwardList copyBackForwardList();
 
+    public void setFindListener(FindListener listener);
+
     public void findNext(boolean forward);
 
     public int findAll(String find);
 
+    public void findAllAsync(String find);
+
     public boolean showFindDialog(String text, boolean showIme);
 
     public void clearMatches();
diff --git a/core/res/res/anim/screen_rotate_finish_exit.xml b/core/res/res/anim/screen_rotate_finish_exit.xml
index 3d9c569..003940e 100644
--- a/core/res/res/anim/screen_rotate_finish_exit.xml
+++ b/core/res/res/anim/screen_rotate_finish_exit.xml
@@ -24,12 +24,14 @@
             android:pivotX="50%" android:pivotY="50%"
             android:interpolator="@interpolator/accelerate_decelerate"
             android:fillEnabled="true"
-            android:fillBefore="false" android:fillAfter="true"
+            android:fillBefore="true" android:fillAfter="true"
             android:duration="@android:integer/config_shortAnimTime"/>
     <scale android:fromXScale="100%" android:toXScale="100%p"
             android:fromYScale="100%" android:toYScale="100%p"
             android:pivotX="50%" android:pivotY="50%"
             android:interpolator="@interpolator/accelerate_decelerate"
+            android:fillEnabled="true"
+            android:fillBefore="true" android:fillAfter="true"
             android:duration="@android:integer/config_mediumAnimTime" />
     <alpha android:fromAlpha="1.0" android:toAlpha="0"
             android:interpolator="@interpolator/accelerate_decelerate"
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 09e4e45..e5ad4b7 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -746,6 +746,10 @@
             "audio_decoder.aac", "audio_encoder.aac" },
         { MEDIA_MIMETYPE_AUDIO_VORBIS,
             "audio_decoder.vorbis", "audio_encoder.vorbis" },
+        { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
+            "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" },
+        { MEDIA_MIMETYPE_AUDIO_G711_ALAW,
+            "audio_decoder.g711alaw", "audio_encoder.g711alaw" },
         { MEDIA_MIMETYPE_VIDEO_AVC,
             "video_decoder.avc", "video_encoder.avc" },
         { MEDIA_MIMETYPE_VIDEO_MPEG4,
@@ -855,10 +859,6 @@
         }
     }
 
-    if (err != OK) {
-        return err;
-    }
-
     int32_t maxInputSize;
     if (msg->findInt32("max-input-size", &maxInputSize)) {
         err = setMinBufferSize(kPortIndexInput, (size_t)maxInputSize);
@@ -2770,6 +2770,9 @@
     status_t err = mCodec->configureCodec(mime.c_str(), msg);
 
     if (err != OK) {
+        ALOGE("[%s] configureCodec returning error %d",
+              mCodec->mComponentName.c_str(), err);
+
         mCodec->signalError(OMX_ErrorUndefined, err);
         return false;
     }
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 278e3a2..d5e6bec 100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1332,8 +1332,6 @@
             "audio_decoder.mp1", "audio_encoder.mp1" },
         { MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II,
             "audio_decoder.mp2", "audio_encoder.mp2" },
-        { MEDIA_MIMETYPE_AUDIO_MPEG,
-            "audio_decoder.mp3", "audio_encoder.mp3" },
         { MEDIA_MIMETYPE_AUDIO_AMR_NB,
             "audio_decoder.amrnb", "audio_encoder.amrnb" },
         { MEDIA_MIMETYPE_AUDIO_AMR_WB,
@@ -1342,6 +1340,10 @@
             "audio_decoder.aac", "audio_encoder.aac" },
         { MEDIA_MIMETYPE_AUDIO_VORBIS,
             "audio_decoder.vorbis", "audio_encoder.vorbis" },
+        { MEDIA_MIMETYPE_AUDIO_G711_MLAW,
+            "audio_decoder.g711mlaw", "audio_encoder.g711mlaw" },
+        { MEDIA_MIMETYPE_AUDIO_G711_ALAW,
+            "audio_decoder.g711alaw", "audio_encoder.g711alaw" },
         { MEDIA_MIMETYPE_VIDEO_AVC,
             "video_decoder.avc", "video_encoder.avc" },
         { MEDIA_MIMETYPE_VIDEO_MPEG4,
diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
index 7602f2d..796caa4 100644
--- a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
@@ -236,6 +236,18 @@
             return OMX_ErrorNone;
         }
 
+        case OMX_IndexParamAudioPcm:
+        {
+            const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
+                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+
+            if (pcmParams->nPortIndex != 1) {
+                return OMX_ErrorUndefined;
+            }
+
+            return OMX_ErrorNone;
+        }
+
         default:
             return SimpleSoftOMXComponent::internalSetParameter(index, params);
     }
diff --git a/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp
deleted file mode 100644
index 27d7e4d..0000000
--- a/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "AMRNBEncoder.h"
-
-#include "gsmamr_enc.h"
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
-
-namespace android {
-
-static const int32_t kNumSamplesPerFrame = 160;
-static const int32_t kSampleRate = 8000;
-
-AMRNBEncoder::AMRNBEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta)
-    : mSource(source),
-      mMeta(meta),
-      mStarted(false),
-      mBufferGroup(NULL),
-      mEncState(NULL),
-      mSidState(NULL),
-      mAnchorTimeUs(0),
-      mNumFramesOutput(0),
-      mInputBuffer(NULL),
-      mMode(MR475),
-      mNumInputSamples(0) {
-}
-
-AMRNBEncoder::~AMRNBEncoder() {
-    if (mStarted) {
-        stop();
-    }
-}
-
-static Mode PickModeFromBitrate(int32_t bps) {
-    if (bps <= 4750) {
-        return MR475;
-    } else if (bps <= 5150) {
-        return MR515;
-    } else if (bps <= 5900) {
-        return MR59;
-    } else if (bps <= 6700) {
-        return MR67;
-    } else if (bps <= 7400) {
-        return MR74;
-    } else if (bps <= 7950) {
-        return MR795;
-    } else if (bps <= 10200) {
-        return MR102;
-    } else {
-        return MR122;
-    }
-}
-
-status_t AMRNBEncoder::start(MetaData *params) {
-    if (mStarted) {
-        ALOGW("Call start() when encoder already started");
-        return OK;
-    }
-
-    mBufferGroup = new MediaBufferGroup;
-    mBufferGroup->add_buffer(new MediaBuffer(32));
-
-    CHECK_EQ(AMREncodeInit(
-                &mEncState, &mSidState, false /* dtx_enable */),
-             0);
-
-    status_t err = mSource->start(params);
-    if (err != OK) {
-        ALOGE("AudioSource is not available");
-        return err;
-    }
-
-    mAnchorTimeUs = 0;
-    mNumFramesOutput = 0;
-    mStarted = true;
-    mNumInputSamples = 0;
-
-    int32_t bitrate;
-    if (params && params->findInt32(kKeyBitRate, &bitrate)) {
-        mMode = PickModeFromBitrate(bitrate);
-    } else {
-        mMode = MR475;
-    }
-
-    return OK;
-}
-
-status_t AMRNBEncoder::stop() {
-    if (!mStarted) {
-        ALOGW("Call stop() when encoder has not started.");
-        return OK;
-    }
-
-    if (mInputBuffer) {
-        mInputBuffer->release();
-        mInputBuffer = NULL;
-    }
-
-    delete mBufferGroup;
-    mBufferGroup = NULL;
-
-    mSource->stop();
-
-    AMREncodeExit(&mEncState, &mSidState);
-    mEncState = mSidState = NULL;
-
-    mStarted = false;
-
-    return OK;
-}
-
-sp<MetaData> AMRNBEncoder::getFormat() {
-    sp<MetaData> srcFormat = mSource->getFormat();
-
-    mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
-
-    int64_t durationUs;
-    if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
-        mMeta->setInt64(kKeyDuration, durationUs);
-    }
-
-    mMeta->setCString(kKeyDecoderComponent, "AMRNBEncoder");
-
-    return mMeta;
-}
-
-status_t AMRNBEncoder::read(
-        MediaBuffer **out, const ReadOptions *options) {
-    status_t err;
-
-    *out = NULL;
-
-    int64_t seekTimeUs;
-    ReadOptions::SeekMode mode;
-    CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode));
-    bool readFromSource = false;
-    int64_t wallClockTimeUs = -1;
-
-    while (mNumInputSamples < kNumSamplesPerFrame) {
-        if (mInputBuffer == NULL) {
-            err = mSource->read(&mInputBuffer, options);
-
-            if (err != OK) {
-                if (mNumInputSamples == 0) {
-                    return ERROR_END_OF_STREAM;
-                }
-                memset(&mInputFrame[mNumInputSamples],
-                       0,
-                       sizeof(int16_t)
-                            * (kNumSamplesPerFrame - mNumInputSamples));
-                mNumInputSamples = kNumSamplesPerFrame;
-                break;
-            }
-
-            size_t align = mInputBuffer->range_length() % sizeof(int16_t);
-            CHECK_EQ(align, 0);
-            readFromSource = true;
-
-            int64_t timeUs;
-            if (mInputBuffer->meta_data()->findInt64(kKeyDriftTime, &timeUs)) {
-                wallClockTimeUs = timeUs;
-            }
-            if (mInputBuffer->meta_data()->findInt64(kKeyAnchorTime, &timeUs)) {
-                mAnchorTimeUs = timeUs;
-            }
-        } else {
-            readFromSource = false;
-        }
-
-        size_t copy =
-            (kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t);
-
-        if (copy > mInputBuffer->range_length()) {
-            copy = mInputBuffer->range_length();
-        }
-
-        memcpy(&mInputFrame[mNumInputSamples],
-               (const uint8_t *)mInputBuffer->data()
-                    + mInputBuffer->range_offset(),
-               copy);
-
-        mNumInputSamples += copy / sizeof(int16_t);
-
-        mInputBuffer->set_range(
-                mInputBuffer->range_offset() + copy,
-                mInputBuffer->range_length() - copy);
-
-        if (mInputBuffer->range_length() == 0) {
-            mInputBuffer->release();
-            mInputBuffer = NULL;
-        }
-    }
-
-    MediaBuffer *buffer;
-    CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), (status_t)OK);
-
-    uint8_t *outPtr = (uint8_t *)buffer->data();
-
-    Frame_Type_3GPP frameType;
-    int res = AMREncode(
-            mEncState, mSidState, (Mode)mMode,
-            mInputFrame, outPtr, &frameType, AMR_TX_WMF);
-
-    CHECK(res >= 0);
-    CHECK((size_t)res < buffer->size());
-
-    // Convert header byte from WMF to IETF format.
-    outPtr[0] = ((outPtr[0] << 3) | 4) & 0x7c;
-
-    buffer->set_range(0, res);
-
-    // Each frame of 160 samples is 20ms long.
-    int64_t mediaTimeUs = mNumFramesOutput * 20000LL;
-    buffer->meta_data()->setInt64(
-            kKeyTime, mAnchorTimeUs + mediaTimeUs);
-
-    if (readFromSource && wallClockTimeUs != -1) {
-        buffer->meta_data()->setInt64(kKeyDriftTime,
-            mediaTimeUs - wallClockTimeUs);
-    }
-
-    ++mNumFramesOutput;
-
-    *out = buffer;
-
-    mNumInputSamples = 0;
-
-    return OK;
-}
-
-}  // namespace android
diff --git a/media/libstagefright/codecs/amrnb/enc/Android.mk b/media/libstagefright/codecs/amrnb/enc/Android.mk
index 21937bf..28246ae 100644
--- a/media/libstagefright/codecs/amrnb/enc/Android.mk
+++ b/media/libstagefright/codecs/amrnb/enc/Android.mk
@@ -2,7 +2,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := \
-        AMRNBEncoder.cpp \
 	src/amrencode.cpp \
  	src/autocorr.cpp \
  	src/c1035pf.cpp \
diff --git a/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp
deleted file mode 100644
index 7fd3a95..0000000
--- a/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "AMRWBEncoder"
-#include <utils/Log.h>
-
-#include "AMRWBEncoder.h"
-#include "voAMRWB.h"
-#include "cmnMemory.h"
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
-
-namespace android {
-
-static const int32_t kNumSamplesPerFrame = 320;
-static const int32_t kBitsPerSample = 16;
-static const int32_t kInputBufferSize = (kBitsPerSample / 8) * kNumSamplesPerFrame;
-static const int32_t kSampleRate = 16000;
-static const int32_t kNumChannels = 1;
-
-AMRWBEncoder::AMRWBEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta)
-    : mSource(source),
-      mMeta(meta),
-      mStarted(false),
-      mBufferGroup(NULL),
-      mInputBuffer(NULL),
-      mEncoderHandle(NULL),
-      mApiHandle(NULL),
-      mMemOperator(NULL),
-      mAnchorTimeUs(0),
-      mNumFramesOutput(0),
-      mNumInputSamples(0) {
-}
-
-static VOAMRWBMODE pickModeFromBitRate(int32_t bps) {
-    CHECK(bps >= 0);
-    if (bps <= 6600) {
-        return VOAMRWB_MD66;
-    } else if (bps <= 8850) {
-        return VOAMRWB_MD885;
-    } else if (bps <= 12650) {
-        return VOAMRWB_MD1265;
-    } else if (bps <= 14250) {
-        return VOAMRWB_MD1425;
-    } else if (bps <= 15850) {
-        return VOAMRWB_MD1585;
-    } else if (bps <= 18250) {
-        return VOAMRWB_MD1825;
-    } else if (bps <= 19850) {
-        return VOAMRWB_MD1985;
-    } else if (bps <= 23050) {
-        return VOAMRWB_MD2305;
-    }
-    return VOAMRWB_MD2385;
-}
-
-status_t AMRWBEncoder::initCheck() {
-    CHECK(mApiHandle == NULL && mEncoderHandle == NULL);
-    CHECK(mMeta->findInt32(kKeyBitRate, &mBitRate));
-
-    mApiHandle = new VO_AUDIO_CODECAPI;
-    CHECK(mApiHandle);
-
-    if (VO_ERR_NONE != voGetAMRWBEncAPI(mApiHandle)) {
-        ALOGE("Failed to get api handle");
-        return UNKNOWN_ERROR;
-    }
-
-    mMemOperator = new VO_MEM_OPERATOR;
-    CHECK(mMemOperator != NULL);
-    mMemOperator->Alloc = cmnMemAlloc;
-    mMemOperator->Copy = cmnMemCopy;
-    mMemOperator->Free = cmnMemFree;
-    mMemOperator->Set = cmnMemSet;
-    mMemOperator->Check = cmnMemCheck;
-
-    VO_CODEC_INIT_USERDATA userData;
-    memset(&userData, 0, sizeof(userData));
-    userData.memflag = VO_IMF_USERMEMOPERATOR;
-    userData.memData = (VO_PTR) mMemOperator;
-    if (VO_ERR_NONE != mApiHandle->Init(&mEncoderHandle, VO_AUDIO_CodingAMRWB, &userData)) {
-        ALOGE("Failed to init AMRWB encoder");
-        return UNKNOWN_ERROR;
-    }
-
-    // Configure AMRWB encoder$
-    VOAMRWBMODE mode = pickModeFromBitRate(mBitRate);
-    if (VO_ERR_NONE != mApiHandle->SetParam(mEncoderHandle, VO_PID_AMRWB_MODE,  &mode)) {
-        ALOGE("Failed to set AMRWB encoder mode to %d", mode);
-        return UNKNOWN_ERROR;
-    }
-
-    VOAMRWBFRAMETYPE type = VOAMRWB_RFC3267;
-    if (VO_ERR_NONE != mApiHandle->SetParam(mEncoderHandle, VO_PID_AMRWB_FRAMETYPE, &type)) {
-        ALOGE("Failed to set AMRWB encoder frame type to %d", type);
-        return UNKNOWN_ERROR;
-    }
-
-    return OK;
-}
-
-AMRWBEncoder::~AMRWBEncoder() {
-    if (mStarted) {
-        stop();
-    }
-}
-
-status_t AMRWBEncoder::start(MetaData *params) {
-    if (mStarted) {
-        ALOGW("Call start() when encoder already started");
-        return OK;
-    }
-
-    mBufferGroup = new MediaBufferGroup;
-
-    // The largest buffer size is header + 477 bits
-    mBufferGroup->add_buffer(new MediaBuffer(1024));
-
-    CHECK_EQ((status_t)OK, initCheck());
-
-    mNumFramesOutput = 0;
-
-    status_t err = mSource->start(params);
-    if (err != OK) {
-        ALOGE("AudioSource is not available");
-        return err;
-    }
-    mStarted = true;
-
-    return OK;
-}
-
-status_t AMRWBEncoder::stop() {
-    if (!mStarted) {
-        ALOGW("Call stop() when encoder has not started");
-        return OK;
-    }
-
-    if (mInputBuffer) {
-        mInputBuffer->release();
-        mInputBuffer = NULL;
-    }
-
-    delete mBufferGroup;
-    mBufferGroup = NULL;
-
-
-    CHECK_EQ((VO_U32)VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle));
-    mEncoderHandle = NULL;
-
-    delete mApiHandle;
-    mApiHandle = NULL;
-
-    delete mMemOperator;
-    mMemOperator;
-
-    mStarted = false;
-
-    mSource->stop();
-    return OK;
-}
-
-sp<MetaData> AMRWBEncoder::getFormat() {
-    sp<MetaData> srcFormat = mSource->getFormat();
-
-    mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
-
-    int64_t durationUs;
-    if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
-        mMeta->setInt64(kKeyDuration, durationUs);
-    }
-
-    mMeta->setCString(kKeyDecoderComponent, "AMRWBEncoder");
-
-    return mMeta;
-}
-
-status_t AMRWBEncoder::read(
-        MediaBuffer **out, const ReadOptions *options) {
-    status_t err;
-
-    *out = NULL;
-
-    int64_t seekTimeUs;
-    ReadOptions::SeekMode mode;
-    CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode));
-    bool readFromSource = false;
-    int64_t wallClockTimeUs = -1;
-
-    while (mNumInputSamples < kNumSamplesPerFrame) {
-        if (mInputBuffer == NULL) {
-            err = mSource->read(&mInputBuffer, options);
-
-            if (err != OK) {
-                if (mNumInputSamples == 0) {
-                    return ERROR_END_OF_STREAM;
-                }
-                memset(&mInputFrame[mNumInputSamples],
-                       0,
-                       sizeof(int16_t)
-                            * (kNumSamplesPerFrame - mNumInputSamples));
-                mNumInputSamples = 0;
-                break;
-            }
-
-            size_t align = mInputBuffer->range_length() % sizeof(int16_t);
-            CHECK_EQ(align, (size_t)0);
-
-            int64_t timeUs;
-            if (mInputBuffer->meta_data()->findInt64(kKeyDriftTime, &timeUs)) {
-                wallClockTimeUs = timeUs;
-            }
-            if (mInputBuffer->meta_data()->findInt64(kKeyAnchorTime, &timeUs)) {
-                mAnchorTimeUs = timeUs;
-            }
-            readFromSource = true;
-        } else {
-            readFromSource = false;
-        }
-
-        size_t copy =
-            (kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t);
-
-        if (copy > mInputBuffer->range_length()) {
-            copy = mInputBuffer->range_length();
-        }
-
-        memcpy(&mInputFrame[mNumInputSamples],
-               (const uint8_t *)mInputBuffer->data()
-                    + mInputBuffer->range_offset(),
-               copy);
-
-        mInputBuffer->set_range(
-                mInputBuffer->range_offset() + copy,
-                mInputBuffer->range_length() - copy);
-
-        if (mInputBuffer->range_length() == 0) {
-            mInputBuffer->release();
-            mInputBuffer = NULL;
-        }
-
-        mNumInputSamples += copy / sizeof(int16_t);
-        if (mNumInputSamples >= kNumSamplesPerFrame) {
-            mNumInputSamples %= kNumSamplesPerFrame;
-            break;  // Get a whole input frame 640 bytes
-        }
-    }
-
-    VO_CODECBUFFER inputData;
-    memset(&inputData, 0, sizeof(inputData));
-    inputData.Buffer = (unsigned char*) mInputFrame;
-    inputData.Length = kInputBufferSize;
-    CHECK(VO_ERR_NONE == mApiHandle->SetInputData(mEncoderHandle,&inputData));
-
-    MediaBuffer *buffer;
-    CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), (status_t)OK);
-    uint8_t *outPtr = (uint8_t *)buffer->data();
-
-    VO_CODECBUFFER outputData;
-    memset(&outputData, 0, sizeof(outputData));
-    VO_AUDIO_OUTPUTINFO outputInfo;
-    memset(&outputInfo, 0, sizeof(outputInfo));
-
-    VO_U32 ret = VO_ERR_NONE;
-    outputData.Buffer = outPtr;
-    outputData.Length = buffer->size();
-    ret = mApiHandle->GetOutputData(mEncoderHandle, &outputData, &outputInfo);
-    CHECK(ret == VO_ERR_NONE || ret == VO_ERR_INPUT_BUFFER_SMALL);
-
-    buffer->set_range(0, outputData.Length);
-    ++mNumFramesOutput;
-
-    int64_t mediaTimeUs = mNumFramesOutput * 20000LL;
-    buffer->meta_data()->setInt64(kKeyTime, mAnchorTimeUs + mediaTimeUs);
-    if (readFromSource && wallClockTimeUs != -1) {
-        buffer->meta_data()->setInt64(kKeyDriftTime, mediaTimeUs - wallClockTimeUs);
-    }
-
-    *out = buffer;
-    return OK;
-}
-
-}  // namespace android
diff --git a/media/libstagefright/codecs/amrwbenc/Android.mk b/media/libstagefright/codecs/amrwbenc/Android.mk
index 3a46ec8..d3c3041 100644
--- a/media/libstagefright/codecs/amrwbenc/Android.mk
+++ b/media/libstagefright/codecs/amrwbenc/Android.mk
@@ -5,7 +5,6 @@
 
 
 LOCAL_SRC_FILES := \
-	AMRWBEncoder.cpp \
 	src/autocorr.c \
 	src/az_isp.c \
 	src/bits.c \
diff --git a/media/libstagefright/codecs/g711/dec/SoftG711.cpp b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
index 32ef003..bcdd3c7 100644
--- a/media/libstagefright/codecs/g711/dec/SoftG711.cpp
+++ b/media/libstagefright/codecs/g711/dec/SoftG711.cpp
@@ -140,7 +140,7 @@
             OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
                 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
 
-            if (pcmParams->nPortIndex != 0) {
+            if (pcmParams->nPortIndex != 0 && pcmParams->nPortIndex != 1) {
                 return OMX_ErrorUndefined;
             }
 
@@ -148,7 +148,9 @@
                 return OMX_ErrorUndefined;
             }
 
-            mNumChannels = pcmParams->nChannels;
+            if(pcmParams->nPortIndex == 0) {
+                mNumChannels = pcmParams->nChannels;
+            }
 
             return OMX_ErrorNone;
         }
diff --git a/media/libstagefright/include/AACDecoder.h b/media/libstagefright/include/AACDecoder.h
deleted file mode 100644
index 886a3b7..0000000
--- a/media/libstagefright/include/AACDecoder.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2009 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 AAC_DECODER_H_
-
-#define AAC_DECODER_H_
-
-#include <media/stagefright/MediaSource.h>
-
-struct tPVMP4AudioDecoderExternal;
-
-namespace android {
-
-struct MediaBufferGroup;
-struct MetaData;
-
-struct AACDecoder : public MediaSource {
-    AACDecoder(const sp<MediaSource> &source);
-
-    virtual status_t start(MetaData *params);
-    virtual status_t stop();
-
-    virtual sp<MetaData> getFormat();
-
-    virtual status_t read(
-            MediaBuffer **buffer, const ReadOptions *options);
-
-protected:
-    virtual ~AACDecoder();
-
-private:
-    sp<MetaData>    mMeta;
-    sp<MediaSource> mSource;
-    bool mStarted;
-
-    MediaBufferGroup *mBufferGroup;
-
-    tPVMP4AudioDecoderExternal *mConfig;
-    void *mDecoderBuf;
-    int64_t mAnchorTimeUs;
-    int64_t mNumSamplesOutput;
-    status_t mInitCheck;
-    int64_t  mNumDecodedBuffers;
-    int32_t  mUpsamplingFactor;
-
-    MediaBuffer *mInputBuffer;
-
-    status_t initCheck();
-    AACDecoder(const AACDecoder &);
-    AACDecoder &operator=(const AACDecoder &);
-};
-
-}  // namespace android
-
-#endif  // AAC_DECODER_H_
diff --git a/media/libstagefright/include/AMRNBDecoder.h b/media/libstagefright/include/AMRNBDecoder.h
deleted file mode 100644
index cf24eda..0000000
--- a/media/libstagefright/include/AMRNBDecoder.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2009 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 AMR_NB_DECODER_H_
-
-#define AMR_NB_DECODER_H_
-
-#include <media/stagefright/MediaSource.h>
-
-namespace android {
-
-struct MediaBufferGroup;
-
-struct AMRNBDecoder : public MediaSource {
-    AMRNBDecoder(const sp<MediaSource> &source);
-
-    virtual status_t start(MetaData *params);
-    virtual status_t stop();
-
-    virtual sp<MetaData> getFormat();
-
-    virtual status_t read(
-            MediaBuffer **buffer, const ReadOptions *options);
-
-protected:
-    virtual ~AMRNBDecoder();
-
-private:
-    sp<MediaSource> mSource;
-    bool mStarted;
-
-    MediaBufferGroup *mBufferGroup;
-
-    void *mState;
-    int64_t mAnchorTimeUs;
-    int64_t mNumSamplesOutput;
-
-    MediaBuffer *mInputBuffer;
-
-    AMRNBDecoder(const AMRNBDecoder &);
-    AMRNBDecoder &operator=(const AMRNBDecoder &);
-};
-
-}  // namespace android
-
-#endif  // AMR_NB_DECODER_H_
diff --git a/media/libstagefright/include/AMRNBEncoder.h b/media/libstagefright/include/AMRNBEncoder.h
deleted file mode 100644
index 71160e6..0000000
--- a/media/libstagefright/include/AMRNBEncoder.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2009 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 AMR_NB_ENCODER_H_
-
-#define AMR_NB_ENCODER_H_
-
-#include <media/stagefright/MediaSource.h>
-#include <media/stagefright/MetaData.h>
-
-namespace android {
-
-struct MediaBufferGroup;
-
-struct AMRNBEncoder : public MediaSource {
-    AMRNBEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta);
-
-    virtual status_t start(MetaData *params);
-    virtual status_t stop();
-
-    virtual sp<MetaData> getFormat();
-
-    virtual status_t read(
-            MediaBuffer **buffer, const ReadOptions *options);
-
-protected:
-    virtual ~AMRNBEncoder();
-
-private:
-    sp<MediaSource> mSource;
-    sp<MetaData>    mMeta;
-    bool mStarted;
-
-    MediaBufferGroup *mBufferGroup;
-
-    void *mEncState;
-    void *mSidState;
-    int64_t mAnchorTimeUs;
-    int64_t mNumFramesOutput;
-
-    MediaBuffer *mInputBuffer;
-    int mMode;
-
-    int16_t mInputFrame[160];
-    int32_t mNumInputSamples;
-
-    AMRNBEncoder(const AMRNBEncoder &);
-    AMRNBEncoder &operator=(const AMRNBEncoder &);
-};
-
-}  // namespace android
-
-#endif  // AMR_NB_ENCODER_H_
diff --git a/media/libstagefright/include/AMRWBDecoder.h b/media/libstagefright/include/AMRWBDecoder.h
deleted file mode 100644
index 927c51c..0000000
--- a/media/libstagefright/include/AMRWBDecoder.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2009 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 AMR_WB_DECODER_H_
-
-#define AMR_WB_DECODER_H_
-
-#include <media/stagefright/MediaSource.h>
-
-namespace android {
-
-struct MediaBufferGroup;
-
-struct AMRWBDecoder : public MediaSource {
-    AMRWBDecoder(const sp<MediaSource> &source);
-
-    virtual status_t start(MetaData *params);
-    virtual status_t stop();
-
-    virtual sp<MetaData> getFormat();
-
-    virtual status_t read(
-            MediaBuffer **buffer, const ReadOptions *options);
-
-protected:
-    virtual ~AMRWBDecoder();
-
-private:
-    sp<MediaSource> mSource;
-    bool mStarted;
-
-    MediaBufferGroup *mBufferGroup;
-
-    void *mState;
-    void *mDecoderBuf;
-    int16_t *mDecoderCookie;
-    int64_t mAnchorTimeUs;
-    int64_t mNumSamplesOutput;
-    int16_t mInputSampleBuffer[477];
-
-    MediaBuffer *mInputBuffer;
-
-    AMRWBDecoder(const AMRWBDecoder &);
-    AMRWBDecoder &operator=(const AMRWBDecoder &);
-};
-
-}  // namespace android
-
-#endif  // AMR_WB_DECODER_H_
diff --git a/media/libstagefright/include/AMRWBEncoder.h b/media/libstagefright/include/AMRWBEncoder.h
deleted file mode 100644
index f2d155f..0000000
--- a/media/libstagefright/include/AMRWBEncoder.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef AMR_WB_ENCODER_H
-#define AMR_WB_ENCODER_H
-
-#include <media/stagefright/MediaSource.h>
-#include <media/stagefright/MetaData.h>
-
-struct VO_AUDIO_CODECAPI;
-struct VO_MEM_OPERATOR;
-
-namespace android {
-
-struct MediaBufferGroup;
-
-class AMRWBEncoder: public MediaSource {
-    public:
-        AMRWBEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta);
-
-        virtual status_t start(MetaData *params);
-        virtual status_t stop();
-        virtual sp<MetaData> getFormat();
-        virtual status_t read(
-                MediaBuffer **buffer, const ReadOptions *options);
-
-
-    protected:
-        virtual ~AMRWBEncoder();
-
-    private:
-        sp<MediaSource>   mSource;
-        sp<MetaData>      mMeta;
-        bool              mStarted;
-        MediaBufferGroup *mBufferGroup;
-        MediaBuffer      *mInputBuffer;
-        status_t          mInitCheck;
-        int32_t           mBitRate;
-        void             *mEncoderHandle;
-        VO_AUDIO_CODECAPI *mApiHandle;
-        VO_MEM_OPERATOR  *mMemOperator;
-
-        int64_t mAnchorTimeUs;
-        int64_t mNumFramesOutput;
-
-        int16_t mInputFrame[320];
-        int32_t mNumInputSamples;
-
-        status_t initCheck();
-
-        AMRWBEncoder& operator=(const AMRWBEncoder &rhs);
-        AMRWBEncoder(const AMRWBEncoder& copy);
-
-};
-
-}
-
-#endif  //#ifndef AMR_WB_ENCODER_H
-
diff --git a/media/libstagefright/include/AVCDecoder.h b/media/libstagefright/include/AVCDecoder.h
deleted file mode 100644
index eb3b142..0000000
--- a/media/libstagefright/include/AVCDecoder.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2009 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 AVC_DECODER_H_
-
-#define AVC_DECODER_H_
-
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/MediaSource.h>
-#include <utils/Vector.h>
-
-struct tagAVCHandle;
-
-namespace android {
-
-struct AVCDecoder : public MediaSource,
-                    public MediaBufferObserver {
-    AVCDecoder(const sp<MediaSource> &source);
-
-    virtual status_t start(MetaData *params);
-    virtual status_t stop();
-
-    virtual sp<MetaData> getFormat();
-
-    virtual status_t read(
-            MediaBuffer **buffer, const ReadOptions *options);
-
-    virtual void signalBufferReturned(MediaBuffer *buffer);
-
-protected:
-    virtual ~AVCDecoder();
-
-private:
-    sp<MediaSource> mSource;
-    bool mStarted;
-
-    sp<MetaData> mFormat;
-
-    Vector<MediaBuffer *> mCodecSpecificData;
-
-    tagAVCHandle *mHandle;
-    Vector<MediaBuffer *> mFrames;
-    MediaBuffer *mInputBuffer;
-
-    int64_t mAnchorTimeUs;
-    int64_t mNumSamplesOutput;
-    int64_t mPendingSeekTimeUs;
-    MediaSource::ReadOptions::SeekMode mPendingSeekMode;
-
-    int64_t mTargetTimeUs;
-
-    bool mSPSSeen;
-    bool mPPSSeen;
-
-    void addCodecSpecificData(const uint8_t *data, size_t size);
-
-    static int32_t ActivateSPSWrapper(
-            void *userData, unsigned int sizeInMbs, unsigned int numBuffers);
-
-    static int32_t BindFrameWrapper(
-            void *userData, int32_t index, uint8_t **yuv);
-
-    static void UnbindFrame(void *userData, int32_t index);
-
-    int32_t activateSPS(
-            unsigned int sizeInMbs, unsigned int numBuffers);
-
-    int32_t bindFrame(int32_t index, uint8_t **yuv);
-
-    void releaseFrames();
-
-    MediaBuffer *drainOutputBuffer();
-
-    AVCDecoder(const AVCDecoder &);
-    AVCDecoder &operator=(const AVCDecoder &);
-};
-
-}  // namespace android
-
-#endif  // AVC_DECODER_H_
diff --git a/media/libstagefright/include/G711Decoder.h b/media/libstagefright/include/G711Decoder.h
deleted file mode 100644
index 8b5143a..0000000
--- a/media/libstagefright/include/G711Decoder.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef G711_DECODER_H_
-
-#define G711_DECODER_H_
-
-#include <media/stagefright/MediaSource.h>
-
-namespace android {
-
-struct MediaBufferGroup;
-
-struct G711Decoder : public MediaSource {
-    G711Decoder(const sp<MediaSource> &source);
-
-    virtual status_t start(MetaData *params);
-    virtual status_t stop();
-
-    virtual sp<MetaData> getFormat();
-
-    virtual status_t read(
-            MediaBuffer **buffer, const ReadOptions *options);
-
-protected:
-    virtual ~G711Decoder();
-
-private:
-    sp<MediaSource> mSource;
-    bool mStarted;
-    bool mIsMLaw;
-
-    MediaBufferGroup *mBufferGroup;
-
-    static void DecodeALaw(int16_t *out, const uint8_t *in, size_t inSize);
-    static void DecodeMLaw(int16_t *out, const uint8_t *in, size_t inSize);
-
-    G711Decoder(const G711Decoder &);
-    G711Decoder &operator=(const G711Decoder &);
-};
-
-}  // namespace android
-
-#endif  // G711_DECODER_H_
diff --git a/media/libstagefright/include/M4vH263Decoder.h b/media/libstagefright/include/M4vH263Decoder.h
deleted file mode 100644
index 7d73e30..0000000
--- a/media/libstagefright/include/M4vH263Decoder.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2009 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 M4V_H263_DECODER_H_
-
-#define M4V_H263_DECODER_H_
-
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/MediaSource.h>
-
-struct tagvideoDecControls;
-
-namespace android {
-
-struct M4vH263Decoder : public MediaSource,
-                        public MediaBufferObserver {
-    M4vH263Decoder(const sp<MediaSource> &source);
-
-    virtual status_t start(MetaData *params);
-    virtual status_t stop();
-
-    virtual sp<MetaData> getFormat();
-
-    virtual status_t read(
-            MediaBuffer **buffer, const ReadOptions *options);
-
-    virtual void signalBufferReturned(MediaBuffer *buffer);
-
-protected:
-    virtual ~M4vH263Decoder();
-
-private:
-    sp<MediaSource> mSource;
-    bool mStarted;
-    int32_t mWidth, mHeight;
-
-    sp<MetaData> mFormat;
-
-    tagvideoDecControls *mHandle;
-    MediaBuffer *mFrames[2];
-    MediaBuffer *mInputBuffer;
-
-    int64_t mNumSamplesOutput;
-    int64_t mTargetTimeUs;
-
-    void allocateFrames(int32_t width, int32_t height);
-    void releaseFrames();
-
-    M4vH263Decoder(const M4vH263Decoder &);
-    M4vH263Decoder &operator=(const M4vH263Decoder &);
-};
-
-}  // namespace android
-
-#endif  // M4V_H263_DECODER_H_
diff --git a/media/libstagefright/include/MP3Decoder.h b/media/libstagefright/include/MP3Decoder.h
deleted file mode 100644
index 4086fb6..0000000
--- a/media/libstagefright/include/MP3Decoder.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2009 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 MP3_DECODER_H_
-
-#define MP3_DECODER_H_
-
-#include <media/stagefright/MediaSource.h>
-
-struct tPVMP3DecoderExternal;
-
-namespace android {
-
-struct MediaBufferGroup;
-
-struct MP3Decoder : public MediaSource {
-    MP3Decoder(const sp<MediaSource> &source);
-
-    virtual status_t start(MetaData *params);
-    virtual status_t stop();
-
-    virtual sp<MetaData> getFormat();
-
-    virtual status_t read(
-            MediaBuffer **buffer, const ReadOptions *options);
-
-protected:
-    virtual ~MP3Decoder();
-
-private:
-    sp<MediaSource> mSource;
-    sp<MetaData> mMeta;
-    int32_t mNumChannels;
-
-    bool mStarted;
-
-    MediaBufferGroup *mBufferGroup;
-
-    tPVMP3DecoderExternal *mConfig;
-    void *mDecoderBuf;
-    int64_t mAnchorTimeUs;
-    int64_t mNumFramesOutput;
-
-    MediaBuffer *mInputBuffer;
-
-    void init();
-
-    MP3Decoder(const MP3Decoder &);
-    MP3Decoder &operator=(const MP3Decoder &);
-};
-
-}  // namespace android
-
-#endif  // MP3_DECODER_H_
diff --git a/media/libstagefright/include/VPXDecoder.h b/media/libstagefright/include/VPXDecoder.h
deleted file mode 100644
index 3b8362d..0000000
--- a/media/libstagefright/include/VPXDecoder.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef VPX_DECODER_H_
-
-#define VPX_DECODER_H_
-
-#include <media/stagefright/MediaSource.h>
-#include <utils/Vector.h>
-
-namespace android {
-
-struct MediaBufferGroup;
-
-struct VPXDecoder : public MediaSource {
-    VPXDecoder(const sp<MediaSource> &source);
-
-    virtual status_t start(MetaData *params);
-    virtual status_t stop();
-
-    virtual sp<MetaData> getFormat();
-
-    virtual status_t read(
-            MediaBuffer **buffer, const ReadOptions *options);
-
-protected:
-    virtual ~VPXDecoder();
-
-private:
-    sp<MediaSource> mSource;
-    bool mStarted;
-    int32_t mWidth, mHeight;
-    size_t mBufferSize;
-
-    void *mCtx;
-    MediaBufferGroup *mBufferGroup;
-
-    int64_t mTargetTimeUs;
-
-    sp<MetaData> mFormat;
-
-    VPXDecoder(const VPXDecoder &);
-    VPXDecoder &operator=(const VPXDecoder &);
-};
-
-}  // namespace android
-
-#endif  // VPX_DECODER_H_
-
diff --git a/media/libstagefright/include/VorbisDecoder.h b/media/libstagefright/include/VorbisDecoder.h
deleted file mode 100644
index 13e8b77..0000000
--- a/media/libstagefright/include/VorbisDecoder.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef VORBIS_DECODER_H_
-
-#define VORBIS_DECODER_H_
-
-#include <media/stagefright/MediaSource.h>
-
-struct vorbis_dsp_state;
-struct vorbis_info;
-
-namespace android {
-
-struct MediaBufferGroup;
-
-struct VorbisDecoder : public MediaSource {
-    VorbisDecoder(const sp<MediaSource> &source);
-
-    virtual status_t start(MetaData *params);
-    virtual status_t stop();
-
-    virtual sp<MetaData> getFormat();
-
-    virtual status_t read(
-            MediaBuffer **buffer, const ReadOptions *options);
-
-protected:
-    virtual ~VorbisDecoder();
-
-private:
-    enum {
-        kMaxNumSamplesPerBuffer = 8192 * 2
-    };
-
-    sp<MediaSource> mSource;
-    bool mStarted;
-
-    MediaBufferGroup *mBufferGroup;
-
-    int32_t mNumChannels;
-    int32_t mSampleRate;
-    int64_t mAnchorTimeUs;
-    int64_t mNumFramesOutput;
-    int32_t mNumFramesLeftOnPage;
-
-    vorbis_dsp_state *mState;
-    vorbis_info *mVi;
-
-    int decodePacket(MediaBuffer *packet, MediaBuffer *out);
-
-    VorbisDecoder(const VorbisDecoder &);
-    VorbisDecoder &operator=(const VorbisDecoder &);
-};
-
-}  // namespace android
-
-#endif  // VORBIS_DECODER_H_
-
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 0c5a827..caee1ab 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -110,6 +110,7 @@
 import android.os.SystemProperties;
 import android.os.UserId;
 import android.provider.Settings;
+import android.text.format.Time;
 import android.util.EventLog;
 import android.util.Pair;
 import android.util.Slog;
@@ -197,6 +198,8 @@
     
     private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
 
+    static final boolean IS_USER_BUILD = "user".equals(Build.TYPE);
+
     // Maximum number of recent tasks that we can remember.
     static final int MAX_RECENT_TASKS = 20;
     
@@ -2962,6 +2965,12 @@
             return null;
         }
 
+        dumpStackTraces(tracesPath, firstPids, processStats, lastPids);
+        return tracesFile;
+    }
+
+    private static void dumpStackTraces(String tracesPath, ArrayList<Integer> firstPids,
+            ProcessStats processStats, SparseArray<Boolean> lastPids) {
         // Use a FileObserver to detect when traces finish writing.
         // The order of traces is considered important to maintain for legibility.
         FileObserver observer = new FileObserver(tracesPath, FileObserver.CLOSE_WRITE) {
@@ -2972,16 +2981,18 @@
             observer.startWatching();
 
             // First collect all of the stacks of the most important pids.
-            try {
-                int num = firstPids.size();
-                for (int i = 0; i < num; i++) {
-                    synchronized (observer) {
-                        Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
-                        observer.wait(200);  // Wait for write-close, give up after 200msec
+            if (firstPids != null) {
+                try {
+                    int num = firstPids.size();
+                    for (int i = 0; i < num; i++) {
+                        synchronized (observer) {
+                            Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
+                            observer.wait(200);  // Wait for write-close, give up after 200msec
+                        }
                     }
+                } catch (InterruptedException e) {
+                    Log.wtf(TAG, e);
                 }
-            } catch (InterruptedException e) {
-                Log.wtf(TAG, e);
             }
 
             // Next measure CPU usage.
@@ -3017,13 +3028,83 @@
                 }
             }
 
-            return tracesFile;
-
         } finally {
             observer.stopWatching();
         }
     }
 
+    final void logAppTooSlow(ProcessRecord app, long startTime, String msg) {
+        if (IS_USER_BUILD) {
+            return;
+        }
+        String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
+        if (tracesPath == null || tracesPath.length() == 0) {
+            return;
+        }
+
+        StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
+        StrictMode.allowThreadDiskWrites();
+        try {
+            final File tracesFile = new File(tracesPath);
+            final File tracesDir = tracesFile.getParentFile();
+            final File tracesTmp = new File(tracesDir, "__tmp__");
+            try {
+                if (!tracesDir.exists()) tracesFile.mkdirs();
+                FileUtils.setPermissions(tracesDir.getPath(), 0775, -1, -1);  // drwxrwxr-x
+
+                if (tracesFile.exists()) {
+                    tracesTmp.delete();
+                    tracesFile.renameTo(tracesTmp);
+                }
+                StringBuilder sb = new StringBuilder();
+                Time tobj = new Time();
+                tobj.set(System.currentTimeMillis());
+                sb.append(tobj.format("%Y-%m-%d %H:%M:%S"));
+                sb.append(": ");
+                TimeUtils.formatDuration(SystemClock.uptimeMillis()-startTime, sb);
+                sb.append(" since ");
+                sb.append(msg);
+                FileOutputStream fos = new FileOutputStream(tracesFile);
+                fos.write(sb.toString().getBytes());
+                if (app == null) {
+                    fos.write("\n*** No application process!".getBytes());
+                }
+                fos.close();
+                FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
+            } catch (IOException e) {
+                Slog.w(TAG, "Unable to prepare slow app traces file: " + tracesPath, e);
+                return;
+            }
+
+            if (app != null) {
+                ArrayList<Integer> firstPids = new ArrayList<Integer>();
+                firstPids.add(app.pid);
+                dumpStackTraces(tracesPath, firstPids, null, null);
+            }
+
+            File lastTracesFile = null;
+            File curTracesFile = null;
+            for (int i=9; i>=0; i--) {
+                String name = String.format("slow%02d.txt", i);
+                curTracesFile = new File(tracesDir, name);
+                if (curTracesFile.exists()) {
+                    if (lastTracesFile != null) {
+                        curTracesFile.renameTo(lastTracesFile);
+                    } else {
+                        curTracesFile.delete();
+                    }
+                }
+                lastTracesFile = curTracesFile;
+            }
+            tracesFile.renameTo(curTracesFile);
+            if (tracesTmp.exists()) {
+                tracesTmp.renameTo(tracesFile);
+            }
+        } finally {
+            StrictMode.setThreadPolicy(oldPolicy);
+        }
+    }
+
     final void appNotResponding(ProcessRecord app, ActivityRecord activity,
             ActivityRecord parent, final String annotation) {
         ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index a337b40..b42d98ea 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -85,6 +85,8 @@
     long startTime;         // last time this activity was started
     long lastVisibleTime;   // last time this activity became visible
     long cpuTimeAtResume;   // the cpu time of host process at the time of resuming activity
+    long pauseTime;         // last time we started pausing the activity
+    long launchTickTime;    // base time for launch tick messages
     Configuration configuration; // configuration activity was last running in
     CompatibilityInfo compat;// last used compatibility mode
     ActivityRecord resultTo; // who started this entry, so will get our reply
@@ -576,6 +578,32 @@
         }
     }
 
+    void startLaunchTickingLocked() {
+        if (ActivityManagerService.IS_USER_BUILD) {
+            return;
+        }
+        if (launchTickTime == 0) {
+            launchTickTime = SystemClock.uptimeMillis();
+            continueLaunchTickingLocked();
+        }
+    }
+
+    boolean continueLaunchTickingLocked() {
+        if (launchTickTime != 0) {
+            Message msg = stack.mHandler.obtainMessage(ActivityStack.LAUNCH_TICK_MSG);
+            msg.obj = this;
+            stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
+            stack.mHandler.sendMessageDelayed(msg, ActivityStack.LAUNCH_TICK);
+            return true;
+        }
+        return false;
+    }
+
+    void finishLaunchTickingLocked() {
+        launchTickTime = 0;
+        stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
+    }
+
     // IApplicationToken
 
     public boolean mayFreezeScreenLocked(ProcessRecord app) {
@@ -631,6 +659,7 @@
                 stack.mInitialStartTime = 0;
             }
             startTime = 0;
+            finishLaunchTickingLocked();
         }
     }
 
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index a375d30..13ee008 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -87,7 +87,10 @@
     // How long we wait until giving up on the last activity telling us it
     // is idle.
     static final int IDLE_TIMEOUT = 10*1000;
-    
+
+    // Ticks during which we check progress while waiting for an app to launch.
+    static final int LAUNCH_TICK = 500;
+
     // How long we wait until giving up on the last activity to pause.  This
     // is short because it directly impacts the responsiveness of starting the
     // next activity.
@@ -275,6 +278,7 @@
     static final int LAUNCH_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 4;
     static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 5;
     static final int RESUME_TOP_ACTIVITY_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 6;
+    static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 7;
     
     final Handler mHandler = new Handler() {
         //public Handler() {
@@ -297,6 +301,13 @@
                     // We don't at this point know if the activity is fullscreen,
                     // so we need to be conservative and assume it isn't.
                     Slog.w(TAG, "Activity pause timeout for " + r);
+                    synchronized (mService) {
+                        if (r.app != null) {
+                            mService.logAppTooSlow(r.app, r.pauseTime,
+                                    "pausing " + r);
+                        }
+                    }
+
                     activityPaused(r != null ? r.appToken : null, true);
                 } break;
                 case IDLE_TIMEOUT_MSG: {
@@ -313,6 +324,15 @@
                     Slog.w(TAG, "Activity idle timeout for " + r);
                     activityIdleInternal(r != null ? r.appToken : null, true, null);
                 } break;
+                case LAUNCH_TICK_MSG: {
+                    ActivityRecord r = (ActivityRecord)msg.obj;
+                    synchronized (mService) {
+                        if (r.continueLaunchTickingLocked()) {
+                            mService.logAppTooSlow(r.app, r.launchTickTime,
+                                    "launching " + r);
+                        }
+                    }
+                } break;
                 case DESTROY_TIMEOUT_MSG: {
                     ActivityRecord r = (ActivityRecord)msg.obj;
                     // We don't at this point know if the activity is fullscreen,
@@ -554,6 +574,9 @@
         r.startFreezingScreenLocked(app, 0);
         mService.mWindowManager.setAppVisibility(r.appToken, true);
 
+        // schedule launch ticks to collect information about slow apps.
+        r.startLaunchTickingLocked();
+
         // Have the window manager re-evaluate the orientation of
         // the screen based on the new activity order.  Note that
         // as a result of this, it can call back into the activity
@@ -936,6 +959,7 @@
             // responsiveness seen by the user.
             Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
             msg.obj = prev;
+            prev.pauseTime = SystemClock.uptimeMillis();
             mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
             if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
         } else {
@@ -1480,6 +1504,9 @@
             // This activity is now becoming visible.
             mService.mWindowManager.setAppVisibility(next.appToken, true);
 
+            // schedule launch ticks to collect information about slow apps.
+            next.startLaunchTickingLocked();
+
             ActivityRecord lastResumedActivity = mResumedActivity;
             ActivityState lastState = next.state;
 
@@ -3257,6 +3284,7 @@
             ActivityRecord r = ActivityRecord.forToken(token);
             if (r != null) {
                 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
+                r.finishLaunchTickingLocked();
             }
 
             // Get the activity record.
@@ -3627,6 +3655,7 @@
         mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
         mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
         mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
+        r.finishLaunchTickingLocked();
     }
 
     final void removeActivityFromHistoryLocked(ActivityRecord r) {
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index fd8d411..8796afc 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -26,6 +26,7 @@
 import static android.content.Intent.EXTRA_UID;
 import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
+import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED;
 import static android.net.NetworkStats.IFACE_ALL;
 import static android.net.NetworkStats.SET_ALL;
 import static android.net.NetworkStats.SET_DEFAULT;
@@ -304,7 +305,9 @@
 
         // watch for networkType changes that aren't broadcast through
         // CONNECTIVITY_ACTION_IMMEDIATE above.
-        mTeleManager.listen(mPhoneListener, LISTEN_DATA_CONNECTION_STATE);
+        if (!COMBINE_SUBTYPE_ENABLED) {
+            mTeleManager.listen(mPhoneListener, LISTEN_DATA_CONNECTION_STATE);
+        }
 
         registerPollAlarmLocked();
         registerGlobalAlert();
@@ -325,7 +328,9 @@
         mContext.unregisterReceiver(mRemovedReceiver);
         mContext.unregisterReceiver(mShutdownReceiver);
 
-        mTeleManager.listen(mPhoneListener, LISTEN_NONE);
+        if (!COMBINE_SUBTYPE_ENABLED) {
+            mTeleManager.listen(mPhoneListener, LISTEN_NONE);
+        }
 
         final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
                 : System.currentTimeMillis();
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index 5ca09e7..67b667a 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -240,8 +240,10 @@
                     animation.setStartTime(currentTime);
                     animating = true;
                 }
-                // we're done!
-                return stepAnimation(currentTime);
+                if (stepAnimation(currentTime)) {
+                    // we're done!
+                    return true;
+                }
             }
         } else if (animation != null) {
             // If the display is frozen, and there is a pending animation,
diff --git a/services/java/com/android/server/wm/BlackFrame.java b/services/java/com/android/server/wm/BlackFrame.java
index 26289c9..40e452a 100644
--- a/services/java/com/android/server/wm/BlackFrame.java
+++ b/services/java/com/android/server/wm/BlackFrame.java
@@ -157,6 +157,14 @@
         }
     }
 
+    public void setAlpha(float alpha) {
+        for (int i=0; i<mBlackSurfaces.length; i++) {
+            if (mBlackSurfaces[i] != null) {
+                mBlackSurfaces[i].surface.setAlpha(alpha);
+            }
+        }
+    }
+
     public void clearMatrix() {
         for (int i=0; i<mBlackSurfaces.length; i++) {
             if (mBlackSurfaces[i] != null) {
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index ab084f9..e460f7fd 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -33,12 +33,15 @@
     static final String TAG = "ScreenRotationAnimation";
     static final boolean DEBUG_STATE = false;
     static final boolean DEBUG_TRANSFORMS = false;
+    static final boolean USE_CUSTOM_BLACK_FRAME = false;
 
     static final int FREEZE_LAYER = WindowManagerService.TYPE_LAYER_MULTIPLIER * 200;
 
     final Context mContext;
     Surface mSurface;
-    BlackFrame mBlackFrame;
+    BlackFrame mCustomBlackFrame;
+    BlackFrame mExitingBlackFrame;
+    BlackFrame mEnteringBlackFrame;
     int mWidth, mHeight;
 
     int mSnapshotDeltaRotation;
@@ -104,6 +107,7 @@
     final Matrix mFrameInitialMatrix = new Matrix();
     final Matrix mSnapshotInitialMatrix = new Matrix();
     final Matrix mSnapshotFinalMatrix = new Matrix();
+    final Matrix mExitFrameFinalMatrix = new Matrix();
     final Matrix mTmpMatrix = new Matrix();
     final float[] mTmpFloats = new float[9];
     private boolean mMoreRotateEnter;
@@ -120,9 +124,19 @@
         pw.print(prefix); pw.print("mSurface="); pw.print(mSurface);
                 pw.print(" mWidth="); pw.print(mWidth);
                 pw.print(" mHeight="); pw.println(mHeight);
-        pw.print(prefix); pw.print("mBlackFrame="); pw.println(mBlackFrame);
-        if (mBlackFrame != null) {
-            mBlackFrame.printTo(prefix + "  ", pw);
+        if (USE_CUSTOM_BLACK_FRAME) {
+            pw.print(prefix); pw.print("mCustomBlackFrame="); pw.println(mCustomBlackFrame);
+            if (mCustomBlackFrame != null) {
+                mCustomBlackFrame.printTo(prefix + "  ", pw);
+            }
+        }
+        pw.print(prefix); pw.print("mExitingBlackFrame="); pw.println(mExitingBlackFrame);
+        if (mExitingBlackFrame != null) {
+            mExitingBlackFrame.printTo(prefix + "  ", pw);
+        }
+        pw.print(prefix); pw.print("mEnteringBlackFrame="); pw.println(mEnteringBlackFrame);
+        if (mEnteringBlackFrame != null) {
+            mEnteringBlackFrame.printTo(prefix + "  ", pw);
         }
         pw.print(prefix); pw.print(" mSnapshotDeltaRotation="); pw.print(mSnapshotDeltaRotation);
                 pw.print(" mCurRotation="); pw.println(mCurRotation);
@@ -164,6 +178,9 @@
                 mSnapshotInitialMatrix.printShortString(pw);
                 pw.print(" mSnapshotFinalMatrix="); mSnapshotFinalMatrix.printShortString(pw);
                 pw.println();
+        pw.print(prefix); pw.print("mExitFrameFinalMatrix=");
+                mExitFrameFinalMatrix.printShortString(pw);
+                pw.println();
     }
 
     public ScreenRotationAnimation(Context context, SurfaceSession session,
@@ -199,7 +216,7 @@
                     mSurface = null;
                     return;
                 }
-                mSurface.setLayer(FREEZE_LAYER);
+                mSurface.setLayer(FREEZE_LAYER + 1);
                 mSurface.show();
             } catch (Surface.OutOfResourcesException e) {
                 Slog.w(TAG, "Unable to allocate freeze surface", e);
@@ -320,14 +337,18 @@
                     com.android.internal.R.anim.screen_rotate_start_exit);
             mStartEnterAnimation = AnimationUtils.loadAnimation(mContext,
                     com.android.internal.R.anim.screen_rotate_start_enter);
-            mStartFrameAnimation = AnimationUtils.loadAnimation(mContext,
-                    com.android.internal.R.anim.screen_rotate_start_frame);
+            if (USE_CUSTOM_BLACK_FRAME) {
+                mStartFrameAnimation = AnimationUtils.loadAnimation(mContext,
+                        com.android.internal.R.anim.screen_rotate_start_frame);
+            }
             mFinishExitAnimation = AnimationUtils.loadAnimation(mContext,
                     com.android.internal.R.anim.screen_rotate_finish_exit);
             mFinishEnterAnimation = AnimationUtils.loadAnimation(mContext,
                     com.android.internal.R.anim.screen_rotate_finish_enter);
-            mFinishFrameAnimation = AnimationUtils.loadAnimation(mContext,
-                    com.android.internal.R.anim.screen_rotate_finish_frame);
+            if (USE_CUSTOM_BLACK_FRAME) {
+                mFinishFrameAnimation = AnimationUtils.loadAnimation(mContext,
+                        com.android.internal.R.anim.screen_rotate_finish_frame);
+            }
         }
 
         if (DEBUG_STATE) Slog.v(TAG, "Rotation delta: " + delta + " finalWidth="
@@ -340,16 +361,20 @@
                         com.android.internal.R.anim.screen_rotate_0_exit);
                 mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
                         com.android.internal.R.anim.screen_rotate_0_enter);
-                mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
-                        com.android.internal.R.anim.screen_rotate_0_frame);
+                if (USE_CUSTOM_BLACK_FRAME) {
+                    mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
+                            com.android.internal.R.anim.screen_rotate_0_frame);
+                }
                 break;
             case Surface.ROTATION_90:
                 mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
                         com.android.internal.R.anim.screen_rotate_plus_90_exit);
                 mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
                         com.android.internal.R.anim.screen_rotate_plus_90_enter);
-                mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
-                        com.android.internal.R.anim.screen_rotate_plus_90_frame);
+                if (USE_CUSTOM_BLACK_FRAME) {
+                    mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
+                            com.android.internal.R.anim.screen_rotate_plus_90_frame);
+                }
                 break;
             case Surface.ROTATION_180:
                 mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
@@ -364,8 +389,10 @@
                         com.android.internal.R.anim.screen_rotate_minus_90_exit);
                 mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
                         com.android.internal.R.anim.screen_rotate_minus_90_enter);
-                mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
-                        com.android.internal.R.anim.screen_rotate_minus_90_frame);
+                if (USE_CUSTOM_BLACK_FRAME) {
+                    mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
+                            com.android.internal.R.anim.screen_rotate_minus_90_frame);
+                }
                 break;
         }
 
@@ -385,18 +412,23 @@
                     halfWidth, halfHeight);
             mStartExitAnimation.initialize(halfWidth, halfHeight,
                     mOriginalWidth, mOriginalHeight);
-            mStartFrameAnimation.initialize(finalWidth, finalHeight,
-                    mOriginalWidth, mOriginalHeight);
             mFinishEnterAnimation.initialize(finalWidth, finalHeight,
                     halfWidth, halfHeight);
             mFinishExitAnimation.initialize(halfWidth, halfHeight,
                     mOriginalWidth, mOriginalHeight);
-            mFinishFrameAnimation.initialize(finalWidth, finalHeight,
-                    mOriginalWidth, mOriginalHeight);
+            if (USE_CUSTOM_BLACK_FRAME) {
+                mStartFrameAnimation.initialize(finalWidth, finalHeight,
+                        mOriginalWidth, mOriginalHeight);
+                mFinishFrameAnimation.initialize(finalWidth, finalHeight,
+                        mOriginalWidth, mOriginalHeight);
+            }
         }
         mRotateEnterAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
         mRotateExitAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
-        mRotateFrameAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
+        if (USE_CUSTOM_BLACK_FRAME) {
+            mRotateFrameAnimation.initialize(finalWidth, finalHeight, mOriginalWidth,
+                    mOriginalHeight);
+        }
         mAnimRunning = false;
         mFinishAnimReady = false;
         mFinishAnimStartTime = -1;
@@ -406,23 +438,27 @@
             mStartExitAnimation.scaleCurrentDuration(animationScale);
             mStartEnterAnimation.restrictDuration(maxAnimationDuration);
             mStartEnterAnimation.scaleCurrentDuration(animationScale);
-            mStartFrameAnimation.restrictDuration(maxAnimationDuration);
-            mStartFrameAnimation.scaleCurrentDuration(animationScale);
             mFinishExitAnimation.restrictDuration(maxAnimationDuration);
             mFinishExitAnimation.scaleCurrentDuration(animationScale);
             mFinishEnterAnimation.restrictDuration(maxAnimationDuration);
             mFinishEnterAnimation.scaleCurrentDuration(animationScale);
-            mFinishFrameAnimation.restrictDuration(maxAnimationDuration);
-            mFinishFrameAnimation.scaleCurrentDuration(animationScale);
+            if (USE_CUSTOM_BLACK_FRAME) {
+                mStartFrameAnimation.restrictDuration(maxAnimationDuration);
+                mStartFrameAnimation.scaleCurrentDuration(animationScale);
+                mFinishFrameAnimation.restrictDuration(maxAnimationDuration);
+                mFinishFrameAnimation.scaleCurrentDuration(animationScale);
+            }
         }
         mRotateExitAnimation.restrictDuration(maxAnimationDuration);
         mRotateExitAnimation.scaleCurrentDuration(animationScale);
         mRotateEnterAnimation.restrictDuration(maxAnimationDuration);
         mRotateEnterAnimation.scaleCurrentDuration(animationScale);
-        mRotateFrameAnimation.restrictDuration(maxAnimationDuration);
-        mRotateFrameAnimation.scaleCurrentDuration(animationScale);
+        if (USE_CUSTOM_BLACK_FRAME) {
+            mRotateFrameAnimation.restrictDuration(maxAnimationDuration);
+            mRotateFrameAnimation.scaleCurrentDuration(animationScale);
+        }
 
-        if (mBlackFrame == null) {
+        if (USE_CUSTOM_BLACK_FRAME && mCustomBlackFrame == null) {
             if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
                     WindowManagerService.TAG,
                     ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
@@ -440,8 +476,59 @@
                 Rect outer = new Rect(-mOriginalWidth*1, -mOriginalHeight*1,
                         mOriginalWidth*2, mOriginalHeight*2);
                 Rect inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight);
-                mBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 1);
-                mBlackFrame.setMatrix(mFrameInitialMatrix);
+                mCustomBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 3);
+                mCustomBlackFrame.setMatrix(mFrameInitialMatrix);
+            } catch (Surface.OutOfResourcesException e) {
+                Slog.w(TAG, "Unable to allocate black surface", e);
+            } finally {
+                Surface.closeTransaction();
+                if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
+                        WindowManagerService.TAG,
+                        "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
+            }
+        }
+
+        if (mExitingBlackFrame == null) {
+            if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
+                    WindowManagerService.TAG,
+                    ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
+            Surface.openTransaction();
+
+            // Compute the transformation matrix that must be applied
+            // the the black frame to make it stay in the initial position
+            // before the new screen rotation.  This is different than the
+            // snapshot transformation because the snapshot is always based
+            // of the native orientation of the screen, not the orientation
+            // we were last in.
+            createRotationMatrix(delta, mOriginalWidth, mOriginalHeight, mFrameInitialMatrix);
+
+            try {
+                Rect outer = new Rect(-mOriginalWidth*1, -mOriginalHeight*1,
+                        mOriginalWidth*2, mOriginalHeight*2);
+                Rect inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight);
+                mExitingBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 2);
+                mExitingBlackFrame.setMatrix(mFrameInitialMatrix);
+            } catch (Surface.OutOfResourcesException e) {
+                Slog.w(TAG, "Unable to allocate black surface", e);
+            } finally {
+                Surface.closeTransaction();
+                if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
+                        WindowManagerService.TAG,
+                        "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
+            }
+        }
+
+        if (false && mEnteringBlackFrame == null) {
+            if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
+                    WindowManagerService.TAG,
+                    ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
+            Surface.openTransaction();
+
+            try {
+                Rect outer = new Rect(-finalWidth*1, -finalHeight*1,
+                        finalWidth*2, finalHeight*2);
+                Rect inner = new Rect(0, 0, finalWidth, finalHeight);
+                mEnteringBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER);
             } catch (Surface.OutOfResourcesException e) {
                 Slog.w(TAG, "Unable to allocate black surface", e);
             } finally {
@@ -486,9 +573,17 @@
             mSurface.destroy();
             mSurface = null;
         }
-        if (mBlackFrame != null) {
-            mBlackFrame.kill();
-            mBlackFrame = null;
+        if (mCustomBlackFrame != null) {
+            mCustomBlackFrame.kill();
+            mCustomBlackFrame = null;
+        }
+        if (mExitingBlackFrame != null) {
+            mExitingBlackFrame.kill();
+            mExitingBlackFrame = null;
+        }
+        if (mEnteringBlackFrame != null) {
+            mEnteringBlackFrame.kill();
+            mEnteringBlackFrame = null;
         }
         if (mStartExitAnimation != null) {
             mStartExitAnimation.cancel();
@@ -544,123 +639,120 @@
             mFinishAnimStartTime = now;
         }
 
-        // If the start animation is no longer running, we want to keep its
-        // transformation intact until the finish animation also completes.
-
         mMoreStartExit = false;
         if (mStartExitAnimation != null) {
-            mStartExitTransformation.clear();
             mMoreStartExit = mStartExitAnimation.getTransformation(now, mStartExitTransformation);
             if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start exit: " + mStartExitTransformation);
-            if (!mMoreStartExit) {
-                if (DEBUG_STATE) Slog.v(TAG, "Start exit animation done!");
-                mStartExitAnimation.cancel();
-                mStartExitAnimation = null;
-            }
         }
 
         mMoreStartEnter = false;
         if (mStartEnterAnimation != null) {
-            mStartEnterTransformation.clear();
             mMoreStartEnter = mStartEnterAnimation.getTransformation(now, mStartEnterTransformation);
             if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start enter: " + mStartEnterTransformation);
-            if (!mMoreStartEnter) {
-                if (DEBUG_STATE) Slog.v(TAG, "Start enter animation done!");
-                mStartEnterAnimation.cancel();
-                mStartEnterAnimation = null;
-            }
         }
 
         mMoreStartFrame = false;
         if (mStartFrameAnimation != null) {
-            mStartFrameTransformation.clear();
             mMoreStartFrame = mStartFrameAnimation.getTransformation(now, mStartFrameTransformation);
             if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start frame: " + mStartFrameTransformation);
-            if (!mMoreStartFrame) {
-                if (DEBUG_STATE) Slog.v(TAG, "Start frame animation done!");
-                mStartFrameAnimation.cancel();
-                mStartFrameAnimation = null;
-            }
         }
 
         long finishNow = mFinishAnimReady ? (now - mFinishAnimStartTime) : 0;
         if (DEBUG_STATE) Slog.v(TAG, "Step: finishNow=" + finishNow);
 
-        mFinishExitTransformation.clear();
         mMoreFinishExit = false;
         if (mFinishExitAnimation != null) {
             mMoreFinishExit = mFinishExitAnimation.getTransformation(finishNow, mFinishExitTransformation);
             if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish exit: " + mFinishExitTransformation);
-            if (!mMoreStartExit && !mMoreFinishExit) {
-                if (DEBUG_STATE) Slog.v(TAG, "Finish exit animation done, clearing start/finish anims!");
-                mStartExitTransformation.clear();
-                mFinishExitAnimation.cancel();
-                mFinishExitAnimation = null;
-                mFinishExitTransformation.clear();
-            }
         }
 
-        mFinishEnterTransformation.clear();
         mMoreFinishEnter = false;
         if (mFinishEnterAnimation != null) {
             mMoreFinishEnter = mFinishEnterAnimation.getTransformation(finishNow, mFinishEnterTransformation);
             if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish enter: " + mFinishEnterTransformation);
-            if (!mMoreStartEnter && !mMoreFinishEnter) {
-                if (DEBUG_STATE) Slog.v(TAG, "Finish enter animation done, clearing start/finish anims!");
-                mStartEnterTransformation.clear();
-                mFinishEnterAnimation.cancel();
-                mFinishEnterAnimation = null;
-                mFinishEnterTransformation.clear();
-            }
         }
 
-        mFinishFrameTransformation.clear();
         mMoreFinishFrame = false;
         if (mFinishFrameAnimation != null) {
             mMoreFinishFrame = mFinishFrameAnimation.getTransformation(finishNow, mFinishFrameTransformation);
             if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish frame: " + mFinishFrameTransformation);
-            if (!mMoreStartFrame && !mMoreFinishFrame) {
-                if (DEBUG_STATE) Slog.v(TAG, "Finish frame animation done, clearing start/finish anims!");
-                mStartFrameTransformation.clear();
-                mFinishFrameAnimation.cancel();
-                mFinishFrameAnimation = null;
-                mFinishFrameTransformation.clear();
-            }
         }
 
-        mRotateExitTransformation.clear();
         mMoreRotateExit = false;
         if (mRotateExitAnimation != null) {
             mMoreRotateExit = mRotateExitAnimation.getTransformation(now, mRotateExitTransformation);
             if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate exit: " + mRotateExitTransformation);
-            if (!mMoreFinishExit && !mMoreRotateExit) {
-                if (DEBUG_STATE) Slog.v(TAG, "Rotate exit animation done!");
+        }
+
+        mMoreRotateEnter = false;
+        if (mRotateEnterAnimation != null) {
+            mMoreRotateEnter = mRotateEnterAnimation.getTransformation(now, mRotateEnterTransformation);
+            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate enter: " + mRotateEnterTransformation);
+        }
+
+        mMoreRotateFrame = false;
+        if (mRotateFrameAnimation != null) {
+            mMoreRotateFrame = mRotateFrameAnimation.getTransformation(now, mRotateFrameTransformation);
+            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate frame: " + mRotateFrameTransformation);
+        }
+
+        if (!mMoreStartExit && !mMoreRotateExit && !mMoreFinishExit) {
+            if (mStartExitAnimation != null) {
+                if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, clearing start exit anim!");
+                mStartExitAnimation.cancel();
+                mStartExitAnimation = null;
+                mStartExitTransformation.clear();
+            }
+            if (mFinishExitAnimation != null) {
+                if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, clearing finish exit anim!");
+                mFinishExitAnimation.cancel();
+                mFinishExitAnimation = null;
+                mFinishExitTransformation.clear();
+            }
+            if (mRotateExitAnimation != null) {
+                if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, clearing rotate exit anim!");
                 mRotateExitAnimation.cancel();
                 mRotateExitAnimation = null;
                 mRotateExitTransformation.clear();
             }
         }
 
-        mRotateEnterTransformation.clear();
-        mMoreRotateEnter = false;
-        if (mRotateEnterAnimation != null) {
-            mMoreRotateEnter = mRotateEnterAnimation.getTransformation(now, mRotateEnterTransformation);
-            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate enter: " + mRotateEnterTransformation);
-            if (!mMoreFinishEnter && !mMoreRotateEnter) {
-                if (DEBUG_STATE) Slog.v(TAG, "Rotate enter animation done!");
+        if (!mMoreStartEnter && !mMoreRotateEnter && !mMoreFinishEnter) {
+            if (mStartEnterAnimation != null) {
+                if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, clearing start enter anim!");
+                mStartEnterAnimation.cancel();
+                mStartEnterAnimation = null;
+                mStartEnterTransformation.clear();
+            }
+            if (mFinishEnterAnimation != null) {
+                if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, clearing finish enter anim!");
+                mFinishEnterAnimation.cancel();
+                mFinishEnterAnimation = null;
+                mFinishEnterTransformation.clear();
+            }
+            if (mRotateEnterAnimation != null) {
+                if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, clearing rotate enter anim!");
                 mRotateEnterAnimation.cancel();
                 mRotateEnterAnimation = null;
                 mRotateEnterTransformation.clear();
             }
         }
 
-        mRotateFrameTransformation.clear();
-        mMoreRotateFrame = false;
-        if (mRotateFrameAnimation != null) {
-            mMoreRotateFrame = mRotateFrameAnimation.getTransformation(now, mRotateFrameTransformation);
-            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate frame: " + mRotateFrameTransformation);
-            if (!mMoreFinishFrame && !mMoreRotateFrame) {
-                if (DEBUG_STATE) Slog.v(TAG, "Rotate frame animation done!");
+        if (USE_CUSTOM_BLACK_FRAME && !mMoreStartFrame && !mMoreRotateFrame && !mMoreFinishFrame) {
+            if (mStartFrameAnimation != null) {
+                if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, clearing start frame anim!");
+                mStartFrameAnimation.cancel();
+                mStartFrameAnimation = null;
+                mStartFrameTransformation.clear();
+            }
+            if (mFinishFrameAnimation != null) {
+                if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, clearing finish frame anim!");
+                mFinishFrameAnimation.cancel();
+                mFinishFrameAnimation = null;
+                mFinishFrameTransformation.clear();
+            }
+            if (mRotateFrameAnimation != null) {
+                if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, clearing rotate frame anim!");
                 mRotateFrameAnimation.cancel();
                 mRotateFrameAnimation = null;
                 mRotateFrameTransformation.clear();
@@ -675,17 +767,19 @@
         mEnterTransformation.compose(mStartEnterTransformation);
         mEnterTransformation.compose(mFinishEnterTransformation);
 
-        //mFrameTransformation.set(mRotateExitTransformation);
-        //mFrameTransformation.compose(mStartExitTransformation);
-        //mFrameTransformation.compose(mFinishExitTransformation);
-        mFrameTransformation.set(mRotateFrameTransformation);
-        mFrameTransformation.compose(mStartFrameTransformation);
-        mFrameTransformation.compose(mFinishFrameTransformation);
-        mFrameTransformation.getMatrix().preConcat(mFrameInitialMatrix);
-
         if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final exit: " + mExitTransformation);
         if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final enter: " + mEnterTransformation);
-        if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final frame: " + mFrameTransformation);
+
+        if (USE_CUSTOM_BLACK_FRAME) {
+            //mFrameTransformation.set(mRotateExitTransformation);
+            //mFrameTransformation.compose(mStartExitTransformation);
+            //mFrameTransformation.compose(mFinishExitTransformation);
+            mFrameTransformation.set(mRotateFrameTransformation);
+            mFrameTransformation.compose(mStartFrameTransformation);
+            mFrameTransformation.compose(mFinishFrameTransformation);
+            mFrameTransformation.getMatrix().preConcat(mFrameInitialMatrix);
+            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final frame: " + mFrameTransformation);
+        }
 
         final boolean more = mMoreStartEnter || mMoreStartExit || mMoreStartFrame
                 || mMoreFinishEnter || mMoreFinishExit || mMoreFinishFrame
@@ -707,12 +801,32 @@
             }
         }
 
-        if (mBlackFrame != null) {
+        if (mCustomBlackFrame != null) {
             if (!mMoreStartFrame && !mMoreFinishFrame && !mMoreRotateFrame) {
                 if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding black frame");
-                mBlackFrame.hide();
+                mCustomBlackFrame.hide();
             } else {
-                mBlackFrame.setMatrix(mFrameTransformation.getMatrix());
+                mCustomBlackFrame.setMatrix(mFrameTransformation.getMatrix());
+            }
+        }
+
+        if (mExitingBlackFrame != null) {
+            if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) {
+                if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding exiting frame");
+                mExitingBlackFrame.hide();
+            } else {
+                mExitFrameFinalMatrix.setConcat(mExitTransformation.getMatrix(), mFrameInitialMatrix);
+                mExitingBlackFrame.setMatrix(mExitFrameFinalMatrix);
+                mExitingBlackFrame.setAlpha(mExitTransformation.getAlpha());
+            }
+        }
+
+        if (mEnteringBlackFrame != null) {
+            if (!mMoreStartEnter && !mMoreFinishEnter && !mMoreRotateEnter) {
+                if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding entering frame");
+                mEnteringBlackFrame.hide();
+            } else {
+                mEnteringBlackFrame.setMatrix(mEnterTransformation.getMatrix());
             }
         }
 
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index f4c4069..6993657 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -7688,9 +7688,9 @@
         Surface.openTransaction();
 
         try {
+            updateWindowsAppsAndRotationAnimationsLocked(currentTime, innerDw, innerDh);
             mPendingLayoutChanges = performAnimationsLocked(currentTime, dw, dh,
                     innerDw, innerDh);
-            updateWindowsAppsAndRotationAnimationsLocked(currentTime, innerDw, innerDh);
         
             // THIRD LOOP: Update the surfaces of all windows.
             
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index 42ce291..57d0374 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -305,11 +305,6 @@
     int mAnimDw;
     int mAnimDh;
 
-    static final int ANIM_STATE_IDLE = 0;
-    static final int ANIM_STATE_RUNNING = 1;
-    static final int ANIM_STATE_STOPPING = 2;
-    int mAnimState = ANIM_STATE_IDLE;
-
     WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
            WindowState attachedWindow, int seq, WindowManager.LayoutParams a,
            int viewVisibility) {
@@ -653,7 +648,6 @@
             mLocalAnimating = false;
             mAnimation.cancel();
             mAnimation = null;
-            mAnimState = ANIM_STATE_IDLE;
         }
     }
 
@@ -665,7 +659,6 @@
             mAnimation.cancel();
             mAnimation = null;
             destroySurfaceLocked();
-            mAnimState = ANIM_STATE_IDLE;
         }
         mExiting = false;
     }
@@ -971,7 +964,8 @@
                 mAppToken.firstWindowDrawn = true;
 
                 if (mAppToken.startingData != null) {
-                    if (WindowManagerService.DEBUG_STARTING_WINDOW || WindowManagerService.DEBUG_ANIM) Slog.v(WindowManagerService.TAG,
+                    if (WindowManagerService.DEBUG_STARTING_WINDOW ||
+                            WindowManagerService.DEBUG_ANIM) Slog.v(WindowManagerService.TAG,
                             "Finish starting " + mToken
                             + ": first real window is shown, no animation");
                     // If this initial window is animating, stop it -- we
@@ -983,7 +977,6 @@
                         mAnimation = null;
                         // Make sure we clean up the animation.
                         mAnimating = true;
-                        mAnimState = ANIM_STATE_IDLE;
                     }
                     mService.mFinishedStarting.add(mAppToken);
                     mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
@@ -995,7 +988,7 @@
     }
 
     private boolean stepAnimation(long currentTime) {
-        if ((mAnimation == null) || !mLocalAnimating || (mAnimState != ANIM_STATE_RUNNING)) {
+        if ((mAnimation == null) || !mLocalAnimating) {
             return false;
         }
         mTransformation.clear();
@@ -1003,9 +996,6 @@
         if (WindowManagerService.DEBUG_ANIM) Slog.v(
             WindowManagerService.TAG, "Stepped animation in " + this +
             ": more=" + more + ", xform=" + mTransformation);
-        if (!more) {
-            mAnimState = ANIM_STATE_STOPPING;
-        }
         return more;
     }
 
@@ -1032,11 +1022,11 @@
                     mAnimation.setStartTime(currentTime);
                     mLocalAnimating = true;
                     mAnimating = true;
-                    mAnimState = ANIM_STATE_RUNNING;
                 }
-                if ((mAnimation != null) && mLocalAnimating && 
-                        (mAnimState != ANIM_STATE_STOPPING)) {
-                    return stepAnimation(currentTime);
+                if ((mAnimation != null) && mLocalAnimating) {
+                    if (stepAnimation(currentTime)) {
+                        return true;
+                    }
                 }
                 if (WindowManagerService.DEBUG_ANIM) Slog.v(
                     WindowManagerService.TAG, "Finished animation in " + this +
@@ -1137,7 +1127,6 @@
             mAppToken.updateReportedVisibilityLocked();
         }
 
-        mAnimState = ANIM_STATE_IDLE;
         return false;
     }
 
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
index 7b672da..8794452 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
@@ -120,10 +120,8 @@
         mProjectCallback = projectCallback;
     }
 
-    public BridgeTypedArray newTypeArray(int numEntries, boolean platformFile,
-            boolean platformStyleable, String styleableName) {
-        return new BridgeTypedArray(this, mContext, numEntries, platformFile,
-                platformStyleable, styleableName);
+    public BridgeTypedArray newTypeArray(int numEntries, boolean platformFile) {
+        return new BridgeTypedArray(this, mContext, numEntries, platformFile);
     }
 
     private Pair<String, ResourceValue> getResourceValue(int id, boolean[] platformResFlag_out) {
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index 8fdac02..cbc199a 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -16,7 +16,7 @@
 
 package android.content.res;
 
-import com.android.ide.common.rendering.api.DeclareStyleableResourceValue;
+import com.android.ide.common.rendering.api.AttrResourceValue;
 import com.android.ide.common.rendering.api.LayoutLog;
 import com.android.ide.common.rendering.api.RenderResources;
 import com.android.ide.common.rendering.api.ResourceValue;
@@ -51,28 +51,33 @@
     private final BridgeResources mBridgeResources;
     private final BridgeContext mContext;
     private final boolean mPlatformFile;
-    private final boolean mPlatformStyleable;
-    private final String mStyleableName;
 
     private ResourceValue[] mResourceData;
     private String[] mNames;
+    private boolean[] mIsFramework;
 
     public BridgeTypedArray(BridgeResources resources, BridgeContext context, int len,
-            boolean platformFile, boolean platformStyleable, String styleableName) {
+            boolean platformFile) {
         super(null, null, null, 0);
         mBridgeResources = resources;
         mContext = context;
         mPlatformFile = platformFile;
-        mPlatformStyleable = platformStyleable;
-        mStyleableName = styleableName;
         mResourceData = new ResourceValue[len];
         mNames = new String[len];
+        mIsFramework = new boolean[len];
     }
 
-    /** A bridge-specific method that sets a value in the type array */
-    public void bridgeSetValue(int index, String name, ResourceValue value) {
+    /**
+     * A bridge-specific method that sets a value in the type array
+     * @param index the index of the value in the TypedArray
+     * @param name the name of the attribute
+     * @param isFramework whether the attribute is in the android namespace.
+     * @param value the value of the attribute
+     */
+    public void bridgeSetValue(int index, String name, boolean isFramework, ResourceValue value) {
         mResourceData[index] = value;
         mNames[index] = name;
+        mIsFramework[index] = isFramework;
     }
 
     /**
@@ -213,8 +218,12 @@
             return defValue;
         }
 
+        if (s == null) {
+            return defValue;
+        }
+
         try {
-            return (s == null) ? defValue : XmlUtils.convertValueToInt(s, defValue);
+            return XmlUtils.convertValueToInt(s, defValue);
         } catch (NumberFormatException e) {
             // pass
         }
@@ -223,15 +232,14 @@
         // Check for possible constants and try to find them.
         // Get the map of attribute-constant -> IntegerValue
         Map<String, Integer> map = null;
-        if (mPlatformStyleable) {
+        if (mIsFramework[index]) {
             map = Bridge.getEnumValues(mNames[index]);
-        } else if (mStyleableName != null) {
+        } else {
             // get the styleable matching the resolved name
             RenderResources res = mContext.getRenderResources();
-            ResourceValue styleable = res.getProjectResource(ResourceType.DECLARE_STYLEABLE,
-                    mStyleableName);
-            if (styleable instanceof DeclareStyleableResourceValue) {
-                map = ((DeclareStyleableResourceValue) styleable).getAttributeValues(mNames[index]);
+            ResourceValue attr = res.getProjectResource(ResourceType.ATTR, mNames[index]);
+            if (attr instanceof AttrResourceValue) {
+                map = ((AttrResourceValue) attr).getAttributeValues();
             }
         }
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
index 529be97..f9f4b3a 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
@@ -70,13 +70,13 @@
 
     @Override
     public Result getProperty(Object objectView, String propertyName) {
-        // TODO Auto-generated method stub
+        // pass
         return super.getProperty(objectView, propertyName);
     }
 
     @Override
     public Result setProperty(Object objectView, String propertyName, String propertyValue) {
-        // TODO Auto-generated method stub
+        // pass
         return super.setProperty(objectView, propertyName, propertyValue);
     }
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 1555d6124..f9e48e2b 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -76,13 +76,11 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.IdentityHashMap;
+import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
-import java.util.TreeMap;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * Custom implementation of Context/Activity to handle non compiled resources.
@@ -247,15 +245,18 @@
 
     public boolean resolveThemeAttribute(int resid, TypedValue outValue, boolean resolveRefs) {
         Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(resid);
+        boolean isFrameworkRes = true;
         if (resourceInfo == null) {
             resourceInfo = mProjectCallback.resolveResourceId(resid);
+            isFrameworkRes = false;
         }
 
         if (resourceInfo == null) {
             return false;
         }
 
-        ResourceValue value = mRenderResources.findItemInTheme(resourceInfo.getSecond());
+        ResourceValue value = mRenderResources.findItemInTheme(resourceInfo.getSecond(),
+                isFrameworkRes);
         if (resolveRefs) {
             value = mRenderResources.resolveResValue(value);
         }
@@ -315,12 +316,7 @@
 
         if (isPlatformLayout == false && skipCallbackParser == false) {
             // check if the project callback can provide us with a custom parser.
-            ILayoutPullParser parser;
-            if (resource instanceof ResourceValue) {
-                parser = mProjectCallback.getParser((ResourceValue) resource);
-            } else {
-                parser = mProjectCallback.getParser(resource.getName());
-            }
+            ILayoutPullParser parser = getParser(resource);
 
             if (parser != null) {
                 BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(parser,
@@ -393,6 +389,17 @@
         return Pair.of(null, false);
     }
 
+    @SuppressWarnings("deprecation")
+    private ILayoutPullParser getParser(ResourceReference resource) {
+        ILayoutPullParser parser;
+        if (resource instanceof ResourceValue) {
+            parser = mProjectCallback.getParser((ResourceValue) resource);
+        } else {
+            parser = mProjectCallback.getParser(resource.getName());
+        }
+        return parser;
+    }
+
     // ------------ Context methods
 
     @Override
@@ -524,12 +531,10 @@
             return null;
         }
 
-        AtomicBoolean frameworkAttributes = new AtomicBoolean();
-        AtomicReference<String> attrName = new AtomicReference<String>();
-        TreeMap<Integer, String> styleNameMap = searchAttrs(attrs, frameworkAttributes, attrName);
+        List<Pair<String, Boolean>> attributeList = searchAttrs(attrs);
 
         BridgeTypedArray ta = ((BridgeResources) mSystemResources).newTypeArray(attrs.length,
-                isPlatformFile, frameworkAttributes.get(), attrName.get());
+                isPlatformFile);
 
         // look for a custom style.
         String customStyle = null;
@@ -555,14 +560,19 @@
 
         if (defStyleAttr != 0) {
             // get the name from the int.
-            String defStyleName = searchAttr(defStyleAttr);
+            Pair<String, Boolean> defStyleAttribute = searchAttr(defStyleAttr);
 
             if (defaultPropMap != null) {
+                String defStyleName = defStyleAttribute.getFirst();
+                if (defStyleAttribute.getSecond()) {
+                    defStyleName = "android:" + defStyleName;
+                }
                 defaultPropMap.put("style", defStyleName);
             }
 
             // look for the style in the current theme, and its parent:
-            ResourceValue item = mRenderResources.findItemInTheme(defStyleName);
+            ResourceValue item = mRenderResources.findItemInTheme(defStyleAttribute.getFirst(),
+                    defStyleAttribute.getSecond());
 
             if (item != null) {
                 // item is a reference to a style entry. Search for it.
@@ -575,19 +585,23 @@
             } else {
                 Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR,
                         String.format(
-                                "Failed to find style '%s' in current theme", defStyleName),
+                                "Failed to find style '%s' in current theme",
+                                defStyleAttribute.getFirst()),
                         null /*data*/);
             }
         } else if (defStyleRes != 0) {
+            boolean isFrameworkRes = true;
             Pair<ResourceType, String> value = Bridge.resolveResourceId(defStyleRes);
             if (value == null) {
                 value = mProjectCallback.resolveResourceId(defStyleRes);
+                isFrameworkRes = false;
             }
 
             if (value != null) {
                 if (value.getFirst() == ResourceType.STYLE) {
                     // look for the style in the current theme, and its parent:
-                    ResourceValue item = mRenderResources.findItemInTheme(value.getSecond());
+                    ResourceValue item = mRenderResources.findItemInTheme(value.getSecond(),
+                            isFrameworkRes);
                     if (item != null) {
                         if (item instanceof StyleResourceValue) {
                             if (defaultPropMap != null) {
@@ -619,26 +633,28 @@
             }
         }
 
-        String namespace = BridgeConstants.NS_RESOURCES;
-        boolean useFrameworkNS = frameworkAttributes.get();
-        if (useFrameworkNS == false) {
-            // need to use the application namespace
-            namespace = mProjectCallback.getNamespace();
-        }
+        String appNamespace = mProjectCallback.getNamespace();
 
-        if (styleNameMap != null) {
-            for (Entry<Integer, String> styleAttribute : styleNameMap.entrySet()) {
-                int index = styleAttribute.getKey().intValue();
+        if (attributeList != null) {
+            for (int index = 0 ; index < attributeList.size() ; index++) {
+                Pair<String, Boolean> attribute = attributeList.get(index);
 
-                String name = styleAttribute.getValue();
+                if (attribute == null) {
+                    continue;
+                }
+
+                String attrName = attribute.getFirst();
+                boolean frameworkAttr = attribute.getSecond().booleanValue();
                 String value = null;
                 if (set != null) {
-                    value = set.getAttributeValue(namespace, name);
+                    value = set.getAttributeValue(
+                            frameworkAttr ? BridgeConstants.NS_RESOURCES : appNamespace,
+                                    attrName);
 
                     // if this is an app attribute, and the first get fails, try with the
                     // new res-auto namespace as well
-                    if (useFrameworkNS == false && value == null) {
-                        value = set.getAttributeValue(BridgeConstants.NS_APP_RES_AUTO, name);
+                    if (frameworkAttr == false && value == null) {
+                        value = set.getAttributeValue(BridgeConstants.NS_APP_RES_AUTO, attrName);
                     }
                 }
 
@@ -649,18 +665,20 @@
 
                     // look for the value in the custom style first (and its parent if needed)
                     if (customStyleValues != null) {
-                        resValue = mRenderResources.findItemInStyle(customStyleValues, name);
+                        resValue = mRenderResources.findItemInStyle(customStyleValues,
+                                attrName, frameworkAttr);
                     }
 
                     // then look for the value in the default Style (and its parent if needed)
                     if (resValue == null && defStyleValues != null) {
-                        resValue = mRenderResources.findItemInStyle(defStyleValues, name);
+                        resValue = mRenderResources.findItemInStyle(defStyleValues,
+                                attrName, frameworkAttr);
                     }
 
                     // if the item is not present in the defStyle, we look in the main theme (and
                     // its parent themes)
                     if (resValue == null) {
-                        resValue = mRenderResources.findItemInTheme(name);
+                        resValue = mRenderResources.findItemInTheme(attrName, frameworkAttr);
                     }
 
                     // if we found a value, we make sure this doesn't reference another value.
@@ -668,18 +686,18 @@
                     if (resValue != null) {
                         // put the first default value, before the resolution.
                         if (defaultPropMap != null) {
-                            defaultPropMap.put(name, resValue.getValue());
+                            defaultPropMap.put(attrName, resValue.getValue());
                         }
 
                         resValue = mRenderResources.resolveResValue(resValue);
                     }
 
-                    ta.bridgeSetValue(index, name, resValue);
+                    ta.bridgeSetValue(index, attrName, frameworkAttr, resValue);
                 } else {
                     // there is a value in the XML, but we need to resolve it in case it's
                     // referencing another resource or a theme value.
-                    ta.bridgeSetValue(index, name,
-                            mRenderResources.resolveValue(null, name, value, isPlatformFile));
+                    ta.bridgeSetValue(index, attrName, frameworkAttr,
+                            mRenderResources.resolveValue(null, attrName, value, isPlatformFile));
                 }
             }
         }
@@ -705,23 +723,23 @@
     private BridgeTypedArray createStyleBasedTypedArray(StyleResourceValue style, int[] attrs)
             throws Resources.NotFoundException {
 
+        List<Pair<String, Boolean>> attributes = searchAttrs(attrs);
+
         BridgeTypedArray ta = ((BridgeResources) mSystemResources).newTypeArray(attrs.length,
-                false, true, null);
+                false);
 
         // for each attribute, get its name so that we can search it in the style
         for (int i = 0 ; i < attrs.length ; i++) {
-            Pair<ResourceType, String> resolvedResource = Bridge.resolveResourceId(attrs[i]);
-            if (resolvedResource != null) {
-                String attrName = resolvedResource.getSecond();
-                // look for the value in the given style
-                ResourceValue resValue = mRenderResources.findItemInStyle(style, attrName);
+            Pair<String, Boolean> attribute = attributes.get(i);
 
-                if (resValue != null) {
-                    // resolve it to make sure there are no references left.
-                    ta.bridgeSetValue(i, attrName, mRenderResources.resolveResValue(resValue));
+            // look for the value in the given style
+            ResourceValue resValue = mRenderResources.findItemInStyle(style, attribute.getFirst(),
+                    attribute.getSecond());
 
-                    resValue = mRenderResources.resolveResValue(resValue);
-                }
+            if (resValue != null) {
+                // resolve it to make sure there are no references left.
+                ta.bridgeSetValue(i, attribute.getFirst(), attribute.getSecond(),
+                        mRenderResources.resolveResValue(resValue));
             }
         }
 
@@ -732,91 +750,52 @@
 
 
     /**
-     * The input int[] attrs is one of com.android.internal.R.styleable fields where the name
-     * of the field is the style being referenced and the array contains one index per attribute.
+     * The input int[] attrs is a list of attributes. The returns a list of information about
+     * each attributes. The information is (name, isFramework)
      * <p/>
-     * searchAttrs() finds all the names of the attributes referenced so for example if
-     * attrs == com.android.internal.R.styleable.View, this returns the list of the "xyz" where
-     * there's a field com.android.internal.R.styleable.View_xyz and the field value is the index
-     * that is used to reference the attribute later in the TypedArray.
      *
      * @param attrs An attribute array reference given to obtainStyledAttributes.
-     * @param outFrameworkFlag out value indicating if the attr array is a framework value
-     * @param outAttrName out value for the resolved attr name.
-     * @return A sorted map Attribute-Value to Attribute-Name for all attributes declared by the
-     *         attribute array. Returns null if nothing is found.
+     * @return List of attribute information.
      */
-    private TreeMap<Integer,String> searchAttrs(int[] attrs, AtomicBoolean outFrameworkFlag,
-            AtomicReference<String> outAttrName) {
-        // get the name of the array from the framework resources
-        String arrayName = Bridge.resolveResourceId(attrs);
-        if (arrayName != null) {
-            // if we found it, get the name of each of the int in the array.
-            TreeMap<Integer,String> attributes = new TreeMap<Integer, String>();
-            for (int i = 0 ; i < attrs.length ; i++) {
-                Pair<ResourceType, String> info = Bridge.resolveResourceId(attrs[i]);
-                if (info != null) {
-                    attributes.put(i, info.getSecond());
-                } else {
-                    // FIXME Not sure what we should be doing here...
-                    attributes.put(i, null);
-                }
+    private List<Pair<String, Boolean>> searchAttrs(int[] attrs) {
+        List<Pair<String, Boolean>> results = new ArrayList<Pair<String, Boolean>>(attrs.length);
+
+        // for each attribute, get its name so that we can search it in the style
+        for (int i = 0 ; i < attrs.length ; i++) {
+            Pair<ResourceType, String> resolvedResource = Bridge.resolveResourceId(attrs[i]);
+            boolean isFramework = false;
+            if (resolvedResource != null) {
+                isFramework = true;
+            } else {
+                resolvedResource = mProjectCallback.resolveResourceId(attrs[i]);
             }
 
-            if (outFrameworkFlag != null) {
-                outFrameworkFlag.set(true);
+            if (resolvedResource != null) {
+                results.add(Pair.of(resolvedResource.getSecond(), isFramework));
+            } else {
+                results.add(null);
             }
-            if (outAttrName != null) {
-                outAttrName.set(arrayName);
-            }
-
-            return attributes;
         }
 
-        // if the name was not found in the framework resources, look in the project
-        // resources
-        arrayName = mProjectCallback.resolveResourceId(attrs);
-        if (arrayName != null) {
-            TreeMap<Integer,String> attributes = new TreeMap<Integer, String>();
-            for (int i = 0 ; i < attrs.length ; i++) {
-                Pair<ResourceType, String> info = mProjectCallback.resolveResourceId(attrs[i]);
-                if (info != null) {
-                    attributes.put(i, info.getSecond());
-                } else {
-                    // FIXME Not sure what we should be doing here...
-                    attributes.put(i, null);
-                }
-            }
-
-            if (outFrameworkFlag != null) {
-                outFrameworkFlag.set(false);
-            }
-            if (outAttrName != null) {
-                outAttrName.set(arrayName);
-            }
-
-            return attributes;
-        }
-
-        return null;
+        return results;
     }
 
     /**
      * Searches for the attribute referenced by its internal id.
      *
      * @param attr An attribute reference given to obtainStyledAttributes such as defStyle.
-     * @return The unique name of the attribute, if found, e.g. "buttonStyle". Returns null
+     * @return A (name, isFramework) pair describing the attribute if found. Returns null
      *         if nothing is found.
      */
-    public String searchAttr(int attr) {
+    public Pair<String, Boolean> searchAttr(int attr) {
         Pair<ResourceType, String> info = Bridge.resolveResourceId(attr);
         if (info != null) {
-            return info.getSecond();
+            return Pair.of(info.getSecond(), Boolean.TRUE);
         }
 
         info = mProjectCallback.resolveResourceId(attr);
         if (info != null) {
-            return info.getSecond();
+            return Pair.of(info.getSecond(), Boolean.FALSE);
         }
 
         return null;
@@ -876,149 +855,149 @@
 
     @Override
     public boolean bindService(Intent arg0, ServiceConnection arg1, int arg2) {
-        // TODO Auto-generated method stub
+        // pass
         return false;
     }
 
     @Override
     public int checkCallingOrSelfPermission(String arg0) {
-        // TODO Auto-generated method stub
+        // pass
         return 0;
     }
 
     @Override
     public int checkCallingOrSelfUriPermission(Uri arg0, int arg1) {
-        // TODO Auto-generated method stub
+        // pass
         return 0;
     }
 
     @Override
     public int checkCallingPermission(String arg0) {
-        // TODO Auto-generated method stub
+        // pass
         return 0;
     }
 
     @Override
     public int checkCallingUriPermission(Uri arg0, int arg1) {
-        // TODO Auto-generated method stub
+        // pass
         return 0;
     }
 
     @Override
     public int checkPermission(String arg0, int arg1, int arg2) {
-        // TODO Auto-generated method stub
+        // pass
         return 0;
     }
 
     @Override
     public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3) {
-        // TODO Auto-generated method stub
+        // pass
         return 0;
     }
 
     @Override
     public int checkUriPermission(Uri arg0, String arg1, String arg2, int arg3,
             int arg4, int arg5) {
-        // TODO Auto-generated method stub
+        // pass
         return 0;
     }
 
     @Override
     public void clearWallpaper() {
-        // TODO Auto-generated method stub
+        // pass
 
     }
 
     @Override
     public Context createPackageContext(String arg0, int arg1) {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public String[] databaseList() {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public boolean deleteDatabase(String arg0) {
-        // TODO Auto-generated method stub
+        // pass
         return false;
     }
 
     @Override
     public boolean deleteFile(String arg0) {
-        // TODO Auto-generated method stub
+        // pass
         return false;
     }
 
     @Override
     public void enforceCallingOrSelfPermission(String arg0, String arg1) {
-        // TODO Auto-generated method stub
+        // pass
 
     }
 
     @Override
     public void enforceCallingOrSelfUriPermission(Uri arg0, int arg1,
             String arg2) {
-        // TODO Auto-generated method stub
+        // pass
 
     }
 
     @Override
     public void enforceCallingPermission(String arg0, String arg1) {
-        // TODO Auto-generated method stub
+        // pass
 
     }
 
     @Override
     public void enforceCallingUriPermission(Uri arg0, int arg1, String arg2) {
-        // TODO Auto-generated method stub
+        // pass
 
     }
 
     @Override
     public void enforcePermission(String arg0, int arg1, int arg2, String arg3) {
-        // TODO Auto-generated method stub
+        // pass
 
     }
 
     @Override
     public void enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3,
             String arg4) {
-        // TODO Auto-generated method stub
+        // pass
 
     }
 
     @Override
     public void enforceUriPermission(Uri arg0, String arg1, String arg2,
             int arg3, int arg4, int arg5, String arg6) {
-        // TODO Auto-generated method stub
+        // pass
 
     }
 
     @Override
     public String[] fileList() {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public AssetManager getAssets() {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public File getCacheDir() {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public File getExternalCacheDir() {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
@@ -1032,49 +1011,49 @@
 
     @Override
     public File getDatabasePath(String arg0) {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public File getDir(String arg0, int arg1) {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public File getFileStreamPath(String arg0) {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public File getFilesDir() {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public File getExternalFilesDir(String type) {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public String getPackageCodePath() {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public PackageManager getPackageManager() {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public String getPackageName() {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
@@ -1085,25 +1064,25 @@
 
     @Override
     public String getPackageResourcePath() {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public File getSharedPrefsFile(String name) {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public SharedPreferences getSharedPreferences(String arg0, int arg1) {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public Drawable getWallpaper() {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
@@ -1119,81 +1098,81 @@
 
     @Override
     public void grantUriPermission(String arg0, Uri arg1, int arg2) {
-        // TODO Auto-generated method stub
+        // pass
 
     }
 
     @Override
     public FileInputStream openFileInput(String arg0) throws FileNotFoundException {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public FileOutputStream openFileOutput(String arg0, int arg1) throws FileNotFoundException {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2) {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1,
             CursorFactory arg2, DatabaseErrorHandler arg3) {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public Drawable peekWallpaper() {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1) {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1,
             String arg2, Handler arg3) {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public void removeStickyBroadcast(Intent arg0) {
-        // TODO Auto-generated method stub
+        // pass
 
     }
 
     @Override
     public void revokeUriPermission(Uri arg0, int arg1) {
-        // TODO Auto-generated method stub
+        // pass
 
     }
 
     @Override
     public void sendBroadcast(Intent arg0) {
-        // TODO Auto-generated method stub
+        // pass
 
     }
 
     @Override
     public void sendBroadcast(Intent arg0, String arg1) {
-        // TODO Auto-generated method stub
+        // pass
 
     }
 
     @Override
     public void sendOrderedBroadcast(Intent arg0, String arg1) {
-        // TODO Auto-generated method stub
+        // pass
 
     }
 
@@ -1201,13 +1180,13 @@
     public void sendOrderedBroadcast(Intent arg0, String arg1,
             BroadcastReceiver arg2, Handler arg3, int arg4, String arg5,
             Bundle arg6) {
-        // TODO Auto-generated method stub
+        // pass
 
     }
 
     @Override
     public void sendStickyBroadcast(Intent arg0) {
-        // TODO Auto-generated method stub
+        // pass
 
     }
 
@@ -1215,79 +1194,79 @@
     public void sendStickyOrderedBroadcast(Intent intent,
             BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData,
            Bundle initialExtras) {
-        // TODO Auto-generated method stub
+        // pass
     }
 
     @Override
     public void setTheme(int arg0) {
-        // TODO Auto-generated method stub
+        // pass
 
     }
 
     @Override
     public void setWallpaper(Bitmap arg0) throws IOException {
-        // TODO Auto-generated method stub
+        // pass
 
     }
 
     @Override
     public void setWallpaper(InputStream arg0) throws IOException {
-        // TODO Auto-generated method stub
+        // pass
 
     }
 
     @Override
     public void startActivity(Intent arg0) {
-        // TODO Auto-generated method stub
+        // pass
     }
 
     @Override
     public void startActivity(Intent arg0, Bundle arg1) {
-        // TODO Auto-generated method stub
+        // pass
     }
 
     @Override
     public void startIntentSender(IntentSender intent,
             Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
             throws IntentSender.SendIntentException {
-        // TODO Auto-generated method stub
+        // pass
     }
 
     @Override
     public void startIntentSender(IntentSender intent,
             Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags,
             Bundle options) throws IntentSender.SendIntentException {
-        // TODO Auto-generated method stub
+        // pass
     }
 
     @Override
     public boolean startInstrumentation(ComponentName arg0, String arg1,
             Bundle arg2) {
-        // TODO Auto-generated method stub
+        // pass
         return false;
     }
 
     @Override
     public ComponentName startService(Intent arg0) {
-        // TODO Auto-generated method stub
+        // pass
         return null;
     }
 
     @Override
     public boolean stopService(Intent arg0) {
-        // TODO Auto-generated method stub
+        // pass
         return false;
     }
 
     @Override
     public void unbindService(ServiceConnection arg0) {
-        // TODO Auto-generated method stub
+        // pass
 
     }
 
     @Override
     public void unregisterReceiver(BroadcastReceiver arg0) {
-        // TODO Auto-generated method stub
+        // pass
 
     }
 
@@ -1298,13 +1277,13 @@
 
     @Override
     public void startActivities(Intent[] arg0) {
-        // TODO Auto-generated method stub
+        // pass
 
     }
 
     @Override
     public void startActivities(Intent[] arg0, Bundle arg1) {
-        // TODO Auto-generated method stub
+        // pass
 
     }