Merge "Add a fixed viewport margin since website content width changes."
diff --git a/api/current.xml b/api/current.xml
index 27a17e6..89e91ca 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -6268,17 +6268,6 @@
  visibility="public"
 >
 </field>
-<field name="kraken_resource_pad57"
- type="int"
- transient="false"
- volatile="false"
- value="16843464"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="kraken_resource_pad6"
  type="int"
  transient="false"
@@ -10129,6 +10118,17 @@
  visibility="public"
 >
 </field>
+<field name="textSelectHandleWindowStyle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843464"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="textSize"
  type="int"
  transient="false"
@@ -15869,6 +15869,28 @@
  visibility="public"
 >
 </field>
+<field name="simple_list_item_activated_1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367075"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="simple_list_item_activated_2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17367076"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="simple_list_item_checked"
  type="int"
  transient="false"
@@ -22618,7 +22640,7 @@
 </implements>
 <implements name="android.view.KeyEvent.Callback">
 </implements>
-<implements name="android.view.LayoutInflater.Factory">
+<implements name="android.view.LayoutInflater.Factory2">
 </implements>
 <implements name="android.view.View.OnCreateContextMenuListener">
 </implements>
@@ -22751,6 +22773,23 @@
 <parameter name="ev" type="android.view.MotionEvent">
 </parameter>
 </method>
+<method name="dump"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<parameter name="writer" type="java.io.PrintWriter">
+</parameter>
+<parameter name="args" type="java.lang.String[]">
+</parameter>
+</method>
 <method name="findFragmentById"
  return="android.app.Fragment"
  abstract="false"
@@ -23456,6 +23495,25 @@
 <parameter name="attrs" type="android.util.AttributeSet">
 </parameter>
 </method>
+<method name="onCreateView"
+ return="android.view.View"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parent" type="android.view.View">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</method>
 <method name="onDestroy"
  return="void"
  abstract="false"
@@ -28720,6 +28778,25 @@
  visibility="public"
 >
 </constructor>
+<method name="dump"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="prefix" type="java.lang.String">
+</parameter>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<parameter name="writer" type="java.io.PrintWriter">
+</parameter>
+<parameter name="args" type="java.lang.String[]">
+</parameter>
+</method>
 <method name="equals"
  return="boolean"
  abstract="false"
@@ -28908,6 +28985,17 @@
  visibility="public"
 >
 </method>
+<method name="isInLayout"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isResumed"
  return="boolean"
  abstract="false"
@@ -29514,6 +29602,25 @@
  visibility="public"
 >
 </method>
+<method name="dump"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="prefix" type="java.lang.String">
+</parameter>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<parameter name="writer" type="java.io.PrintWriter">
+</parameter>
+<parameter name="args" type="java.lang.String[]">
+</parameter>
+</method>
 <method name="findFragmentById"
  return="android.app.Fragment"
  abstract="true"
@@ -106673,6 +106780,19 @@
 <parameter name="value" type="java.lang.String">
 </parameter>
 </method>
+<method name="setShowRunningNotification"
+ return="android.net.DownloadManager.Request"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="show" type="boolean">
+</parameter>
+</method>
 <method name="setTitle"
  return="android.net.DownloadManager.Request"
  abstract="false"
@@ -157148,6 +157268,17 @@
  visibility="public"
 >
 </field>
+<field name="AUTO_TIME_ZONE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;auto_time_zone&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="BLUETOOTH_DISCOVERABILITY"
  type="java.lang.String"
  transient="false"
@@ -178460,19 +178591,6 @@
 <parameter name="event" type="android.view.MotionEvent">
 </parameter>
 </method>
-<method name="setCursorController"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="cursorController" type="android.widget.TextView.CursorController">
-</parameter>
-</method>
 </class>
 <class name="BaseKeyListener"
  extends="android.text.method.MetaKeyKeyListener"
@@ -193168,6 +193286,17 @@
  visibility="public"
 >
 </method>
+<method name="getFactory2"
+ return="android.view.LayoutInflater.Factory2"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getFilter"
  return="android.view.LayoutInflater.Filter"
  abstract="false"
@@ -193260,6 +193389,25 @@
 <exception name="ClassNotFoundException" type="java.lang.ClassNotFoundException">
 </exception>
 </method>
+<method name="onCreateView"
+ return="android.view.View"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="parent" type="android.view.View">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<exception name="ClassNotFoundException" type="java.lang.ClassNotFoundException">
+</exception>
+</method>
 <method name="setFactory"
  return="void"
  abstract="false"
@@ -193273,6 +193421,19 @@
 <parameter name="factory" type="android.view.LayoutInflater.Factory">
 </parameter>
 </method>
+<method name="setFactory2"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="factory" type="android.view.LayoutInflater.Factory2">
+</parameter>
+</method>
 <method name="setFilter"
  return="void"
  abstract="false"
@@ -193312,6 +193473,35 @@
 </parameter>
 </method>
 </interface>
+<interface name="LayoutInflater.Factory2"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.view.LayoutInflater.Factory">
+</implements>
+<method name="onCreateView"
+ return="android.view.View"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parent" type="android.view.View">
+</parameter>
+<parameter name="name" type="java.lang.String">
+</parameter>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</method>
+</interface>
 <interface name="LayoutInflater.Filter"
  abstract="true"
  static="true"
@@ -239242,121 +239432,6 @@
 >
 </method>
 </class>
-<interface name="TextView.CursorController"
- abstract="true"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="draw"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="canvas" type="android.graphics.Canvas">
-</parameter>
-</method>
-<method name="getOffsetX"
- return="float"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getOffsetY"
- return="float"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="hide"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="isShowing"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onTouchEvent"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="event" type="android.view.MotionEvent">
-</parameter>
-</method>
-<method name="show"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="updatePosition"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="x" type="int">
-</parameter>
-<parameter name="y" type="int">
-</parameter>
-</method>
-<field name="FADE_OUT_DURATION"
- type="int"
- transient="false"
- volatile="false"
- value="400"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</interface>
 <interface name="TextView.OnEditorActionListener"
  abstract="true"
  static="true"
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 29db0ec..ee49d97 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -74,6 +74,8 @@
 import android.widget.AdapterView;
 import android.widget.FrameLayout;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
 
@@ -605,7 +607,7 @@
  * or finished.
  */
 public class Activity extends ContextThemeWrapper
-        implements LayoutInflater.Factory,
+        implements LayoutInflater.Factory2,
         Window.Callback, KeyEvent.Callback,
         OnCreateContextMenuListener, ComponentCallbacks {
     private static final String TAG = "Activity";
@@ -4030,15 +4032,30 @@
      * Standard implementation of
      * {@link android.view.LayoutInflater.Factory#onCreateView} used when
      * inflating with the LayoutInflater returned by {@link #getSystemService}.
+     * This implementation does nothing and is for
+     * pre-{@link android.os.Build.VERSION_CODES#HONEYCOMB} apps.  Newer apps
+     * should use {@link #onCreateView(View, String, Context, AttributeSet)}.
+     *
+     * @see android.view.LayoutInflater#createView
+     * @see android.view.Window#getLayoutInflater
+     */
+    public View onCreateView(String name, Context context, AttributeSet attrs) {
+        return null;
+    }
+
+    /**
+     * Standard implementation of
+     * {@link android.view.LayoutInflater.Factory2#onCreateView(View, String, Context, AttributeSet)}
+     * used when inflating with the LayoutInflater returned by {@link #getSystemService}.
      * This implementation handles <fragment> tags to embed fragments inside
      * of the activity.
      *
      * @see android.view.LayoutInflater#createView
      * @see android.view.Window#getLayoutInflater
      */
-    public View onCreateView(String name, Context context, AttributeSet attrs) {
+    public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
         if (!"fragment".equals(name)) {
-            return null;
+            return onCreateView(name, context, attrs);
         }
         
         String fname = attrs.getAttributeValue(null, "class");
@@ -4047,42 +4064,70 @@
         if (fname == null) {
             fname = a.getString(com.android.internal.R.styleable.Fragment_name);
         }
-        int id = a.getResourceId(com.android.internal.R.styleable.Fragment_id, 0);
+        int id = a.getResourceId(com.android.internal.R.styleable.Fragment_id, View.NO_ID);
         String tag = a.getString(com.android.internal.R.styleable.Fragment_tag);
         a.recycle();
         
-        if (id == 0) {
+        int containerId = parent != null ? parent.getId() : 0;
+        if (containerId == View.NO_ID && id == View.NO_ID && tag == null) {
             throw new IllegalArgumentException(attrs.getPositionDescription()
-                    + ": Must specify unique android:id for " + fname);
+                    + ": Must specify unique android:id, android:tag, or have a parent with an id for " + fname);
         }
-        
+
         // If we restored from a previous state, we may already have
         // instantiated this fragment from the state and should use
         // that instance instead of making a new one.
-        Fragment fragment = mFragments.findFragmentById(id);
+        Fragment fragment = id != View.NO_ID ? mFragments.findFragmentById(id) : null;
+        if (fragment == null && tag != null) {
+            fragment = mFragments.findFragmentByTag(tag);
+        }
+        if (fragment == null && containerId != View.NO_ID) {
+            fragment = mFragments.findFragmentById(containerId);
+        }
+
         if (FragmentManagerImpl.DEBUG) Log.v(TAG, "onCreateView: id=0x"
                 + Integer.toHexString(id) + " fname=" + fname
                 + " existing=" + fragment);
         if (fragment == null) {
             fragment = Fragment.instantiate(this, fname);
             fragment.mFromLayout = true;
-            fragment.mFragmentId = id;
+            fragment.mFragmentId = id != 0 ? id : containerId;
+            fragment.mContainerId = containerId;
             fragment.mTag = tag;
+            fragment.mInLayout = true;
             fragment.mImmediateActivity = this;
             fragment.mFragmentManager = mFragments;
+            fragment.onInflate(attrs, fragment.mSavedFragmentState);
+            mFragments.addFragment(fragment, true);
+
+        } else if (fragment.mInLayout) {
+            // A fragment already exists and it is not one we restored from
+            // previous state.
+            throw new IllegalArgumentException(attrs.getPositionDescription()
+                    + ": Duplicate id 0x" + Integer.toHexString(id)
+                    + ", tag " + tag + ", or parent id 0x" + Integer.toHexString(containerId)
+                    + " with another fragment for " + fname);
+        } else {
+            // This fragment was retained from a previous instance; get it
+            // going now.
+            fragment.mInLayout = true;
+            fragment.mImmediateActivity = this;
             // If this fragment is newly instantiated (either right now, or
             // from last saved state), then give it the attributes to
             // initialize itself.
             if (!fragment.mRetaining) {
                 fragment.onInflate(attrs, fragment.mSavedFragmentState);
             }
-            mFragments.addFragment(fragment, true);
+            mFragments.moveToState(fragment);
         }
+
         if (fragment.mView == null) {
             throw new IllegalStateException("Fragment " + fname
                     + " did not create a view.");
         }
-        fragment.mView.setId(id);
+        if (id != 0) {
+            fragment.mView.setId(id);
+        }
         if (fragment.mView.getTag() == null) {
             fragment.mView.setTag(tag);
         }
@@ -4090,6 +4135,19 @@
     }
 
     /**
+     * Print the Activity's state into the given stream.  This gets invoked if
+     * you run "adb shell dumpsys activity <youractivityname>".
+     *
+     * @param fd The raw file descriptor that the dump is being sent to.
+     * @param writer The PrintWriter to which you should dump your state.  This will be
+     * closed for you after you return.
+     * @param args additional arguments to the dump request.
+     */
+    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+        mFragments.dump("", fd, writer, args);
+    }
+
+    /**
      * Bit indicating that this activity is "immersive" and should not be
      * interrupted by notifications if possible.
      *
@@ -4177,7 +4235,7 @@
         
         mWindow = PolicyManager.makeNewWindow(this);
         mWindow.setCallback(this);
-        mWindow.getLayoutInflater().setFactory(this);
+        mWindow.getLayoutInflater().setFactory2(this);
         if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
             mWindow.setSoftInputMode(info.softInputMode);
         }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index c0e2987..3f74904 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -335,9 +335,9 @@
         }
     }
 
-    private static final class DumpServiceInfo {
+    private static final class DumpComponentInfo {
         FileDescriptor fd;
-        IBinder service;
+        IBinder token;
         String[] args;
         boolean dumped;
     }
@@ -370,7 +370,8 @@
         private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s";
         private static final String ONE_COUNT_COLUMN = "%17s %8d";
         private static final String TWO_COUNT_COLUMNS = "%17s %8d %17s %8d";
-        private static final String DB_INFO_FORMAT = "  %4d %6d %8d %14s  %s";
+        private static final String TWO_COUNT_COLUMNS_DB = "%20s %8d %20s %8d";
+        private static final String DB_INFO_FORMAT = "  %8s %8s %14s %14s  %s";
 
         // Formatting for checkin service - update version if row format changes
         private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 1;
@@ -591,9 +592,9 @@
         }
 
         public void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args) {
-            DumpServiceInfo data = new DumpServiceInfo();
+            DumpComponentInfo data = new DumpComponentInfo();
             data.fd = fd;
-            data.service = servicetoken;
+            data.token = servicetoken;
             data.args = args;
             data.dumped = false;
             queueOrSendMessage(H.DUMP_SERVICE, data);
@@ -663,6 +664,25 @@
         public void scheduleCrash(String msg) {
             queueOrSendMessage(H.SCHEDULE_CRASH, msg);
         }
+
+        public void dumpActivity(FileDescriptor fd, IBinder activitytoken, String[] args) {
+            DumpComponentInfo data = new DumpComponentInfo();
+            data.fd = fd;
+            data.token = activitytoken;
+            data.args = args;
+            data.dumped = false;
+            queueOrSendMessage(H.DUMP_ACTIVITY, data);
+            synchronized (data) {
+                while (!data.dumped) {
+                    try {
+                        data.wait();
+                    } catch (InterruptedException e) {
+                        // no need to do anything here, we will keep waiting until
+                        // dumped is set
+                    }
+                }
+            }
+        }
         
         @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -820,20 +840,23 @@
             // SQLite mem info
             pw.println(" ");
             pw.println(" SQL");
-            printRow(pw, TWO_COUNT_COLUMNS, "heap:", sqliteAllocated, "memoryUsed:",
+            printRow(pw, TWO_COUNT_COLUMNS_DB, "heap:", sqliteAllocated, "MEMORY_USED:",
                     stats.memoryUsed / 1024);
-            printRow(pw, TWO_COUNT_COLUMNS, "pageCacheOverflo:", stats.pageCacheOverflo / 1024,
-                    "largestMemAlloc:", stats.largestMemAlloc / 1024);
+            printRow(pw, TWO_COUNT_COLUMNS_DB, "PAGECACHE_OVERFLOW:",
+                    stats.pageCacheOverflo / 1024, "MALLOC_SIZE:", stats.largestMemAlloc / 1024);
             pw.println(" ");
             int N = stats.dbStats.size();
             if (N > 0) {
                 pw.println(" DATABASES");
-                printRow(pw, "  %4s %6s %8s %14s  %s", "pgsz", "dbsz", "lkaside", "cache",
-                    "Dbname");
+                printRow(pw, "  %8s %8s %14s %14s  %s", "pgsz", "dbsz", "Lookaside(b)", "cache",
+                        "Dbname");
                 for (int i = 0; i < N; i++) {
                     DbStats dbStats = stats.dbStats.get(i);
-                    printRow(pw, DB_INFO_FORMAT, dbStats.pageSize, dbStats.dbSize,
-                            dbStats.lookaside, dbStats.cache, dbStats.dbName);
+                    printRow(pw, DB_INFO_FORMAT,
+                            (dbStats.pageSize > 0) ? String.valueOf(dbStats.pageSize) : " ",
+                            (dbStats.dbSize > 0) ? String.valueOf(dbStats.dbSize) : " ",
+                            (dbStats.lookaside > 0) ? String.valueOf(dbStats.lookaside) : " ",
+                            dbStats.cache, dbStats.dbName);
                 }
             }
 
@@ -888,6 +911,7 @@
         public static final int DISPATCH_PACKAGE_BROADCAST = 133;
         public static final int SCHEDULE_CRASH          = 134;
         public static final int DUMP_HEAP               = 135;
+        public static final int DUMP_ACTIVITY           = 136;
         String codeToString(int code) {
             if (localLOGV) {
                 switch (code) {
@@ -927,6 +951,7 @@
                     case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
                     case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
                     case DUMP_HEAP: return "DUMP_HEAP";
+                    case DUMP_ACTIVITY: return "DUMP_ACTIVITY";
                 }
             }
             return "(unknown)";
@@ -1021,7 +1046,7 @@
                     scheduleGcIdler();
                     break;
                 case DUMP_SERVICE:
-                    handleDumpService((DumpServiceInfo)msg.obj);
+                    handleDumpService((DumpComponentInfo)msg.obj);
                     break;
                 case LOW_MEMORY:
                     handleLowMemory();
@@ -1055,6 +1080,9 @@
                 case DUMP_HEAP:
                     handleDumpHeap(msg.arg1 != 0, (DumpHeapData)msg.obj);
                     break;
+                case DUMP_ACTIVITY:
+                    handleDumpActivity((DumpComponentInfo)msg.obj);
+                    break;
             }
         }
 
@@ -2020,9 +2048,9 @@
         }
     }
 
-    private void handleDumpService(DumpServiceInfo info) {
+    private void handleDumpService(DumpComponentInfo info) {
         try {
-            Service s = mServices.get(info.service);
+            Service s = mServices.get(info.token);
             if (s != null) {
                 PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd));
                 s.dump(info.fd, pw, info.args);
@@ -2036,6 +2064,22 @@
         }
     }
 
+    private void handleDumpActivity(DumpComponentInfo info) {
+        try {
+            ActivityClientRecord r = mActivities.get(info.token);
+            if (r != null && r.activity != null) {
+                PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd));
+                r.activity.dump(info.fd, pw, info.args);
+                pw.close();
+            }
+        } finally {
+            synchronized (info) {
+                info.dumped = true;
+                info.notifyAll();
+            }
+        }
+    }
+
     private final void handleServiceArgs(ServiceArgsData data) {
         Service s = mServices.get(data.token);
         if (s != null) {
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index dc2145f..95689fc 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -414,6 +414,21 @@
             dumpHeap(managed, path, fd);
             return true;
         }
+
+        case DUMP_ACTIVITY_TRANSACTION: {
+            data.enforceInterface(IApplicationThread.descriptor);
+            ParcelFileDescriptor fd = data.readFileDescriptor();
+            final IBinder activity = data.readStrongBinder();
+            final String[] args = data.readStringArray();
+            if (fd != null) {
+                dumpActivity(fd.getFileDescriptor(), activity, args);
+                try {
+                    fd.close();
+                } catch (IOException e) {
+                }
+            }
+            return true;
+        }
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -857,5 +872,16 @@
                 IBinder.FLAG_ONEWAY);
         data.recycle();
     }
+
+    public void dumpActivity(FileDescriptor fd, IBinder token, String[] args)
+            throws RemoteException {
+        Parcel data = Parcel.obtain();
+        data.writeInterfaceToken(IApplicationThread.descriptor);
+        data.writeFileDescriptor(fd);
+        data.writeStrongBinder(token);
+        data.writeStringArray(args);
+        mRemote.transact(DUMP_ACTIVITY_TRANSACTION, data, null, 0);
+        data.recycle();
+    }
 }
 
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 1cbed79..12bf7e5 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -38,6 +38,8 @@
 import android.view.View.OnCreateContextMenuListener;
 import android.widget.AdapterView;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.HashMap;
 
 final class FragmentState implements Parcelable {
@@ -207,7 +209,7 @@
  *
  * <p>An activity's layout XML can include <code>&lt;fragment&gt;</code> tags
  * to embed fragment instances inside of the layout.  For example, here is
- * a simply layout that embeds one fragment:</p>
+ * a simple layout that embeds one fragment:</p>
  *
  * {@sample development/samples/ApiDemos/res/layout/fragment_layout.xml layout}
  *
@@ -251,6 +253,33 @@
  * details activity will finish of it finds itself running in a configuration
  * where the details can be shown inline.
  *
+ * <p>When a configuration change causes the activity hosting these fragments
+ * to restart, its new instance may use a different layout that doesn't
+ * include the same fragments as the previous layout.  In this case all of
+ * the previous fragments will still be instantiated and running in the new
+ * instance; however, any that are no longer associated with a &lt;fragment&gt;
+ * tag in the view hierarchy will not have their content view created and will
+ * return false from {@link #isInLayout}.
+ * 
+ * <p>The attributes of the &lt;fragment&gt; tag are used to control the
+ * LayoutParams provider when attaching the fragment's view to the parent
+ * container.  They can alse be parsed by the fragment in {@link #onInflate}
+ * as parameters.
+ * 
+ * <p>The fragment being instantiated must have some kind of unique identifier
+ * so that it can be re-associated with a previous instance if the parent
+ * activity needs to be destroyed and recreated.  This can be provided these
+ * ways:
+ * 
+ * <ul>
+ * <li>If nothing is explicitly supplied, the view ID of the container will
+ * be used.
+ * <li><code>android:tag</code> can be used in &lt;fragment&gt; to provide
+ * a specific tag name for the fragment.
+ * <li><code>android:id</code> can be used in &lt;fragment&gt; to provide
+ * a specific identifier for the fragment.
+ * </ul>
+ * 
  * <a name="BackStack"></a>
  * <h3>Back Stack</h3>
  *
@@ -316,6 +345,9 @@
     // Set to true if this fragment was instantiated from a layout file.
     boolean mFromLayout;
     
+    // Set to true when the view has actually been inflated in its layout.
+    boolean mInLayout;
+
     // Number of active back stack entries this fragment is in.
     int mBackStackNesting;
     
@@ -585,7 +617,7 @@
     /**
      * Return the FragmentManager for interacting with fragments associated
      * with this fragment's activity.  Note that this will be non-null slightly
-     * before {@link #getActivity()}, in the time from when the fragment is
+     * before {@link #getActivity()}, during the time from when the fragment is
      * placed in a {@link FragmentTransaction} until it is committed and
      * attached to its activity.
      */
@@ -601,6 +633,17 @@
     }
     
     /**
+     * Return true if the layout is included as part of an activity view
+     * hierarchy via the &lt;fragment&gt; tag.  This will always be true when
+     * fragments are created through the &lt;fragment&gt; tag, <em>except</em>
+     * in the case where an old fragment is restored from a previous state and
+     * it does not appear in the layout of the current state.
+     */
+    final public boolean isInLayout() {
+        return mInLayout;
+    }
+
+    /**
      * Return true if the fragment is in the resumed state.  This is true
      * for the duration of {@link #onResume()} and {@link #onPause()} as well.
      */
@@ -1075,6 +1118,76 @@
         return false;
     }
     
+    /**
+     * Print the Fragments's state into the given stream.
+     *
+     * @param prefix Text to print at the front of each line.
+     * @param fd The raw file descriptor that the dump is being sent to.
+     * @param writer The PrintWriter to which you should dump your state.  This will be
+     * closed for you after you return.
+     * @param args additional arguments to the dump request.
+     */
+    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+        writer.print(prefix); writer.print("mFragmentId="); writer.print(mFragmentId);
+                writer.print(" mContainerId="); writer.print(mContainerId);
+                writer.print(" mTag="); writer.println(mTag);
+        writer.print(prefix); writer.print("mState="); writer.print(mState);
+                writer.print(" mIndex="); writer.print(mIndex);
+                writer.print(" mWho="); writer.print(mWho);
+                writer.print(" mBackStackNesting="); writer.println(mBackStackNesting);
+        writer.print(prefix); writer.print("mAdded="); writer.print(mAdded);
+                writer.print(" mResumed="); writer.print(mResumed);
+                writer.print(" mFromLayout="); writer.print(mFromLayout);
+                writer.print(" mInLayout="); writer.println(mInLayout);
+        writer.print(prefix); writer.print("mHidden="); writer.print(mHidden);
+                writer.print(" mRetainInstance="); writer.print(mRetainInstance);
+                writer.print(" mRetaining="); writer.print(mRetaining);
+                writer.print(" mHasMenu="); writer.println(mHasMenu);
+        if (mFragmentManager != null) {
+            writer.print(prefix); writer.print("mFragmentManager=");
+                    writer.println(mFragmentManager);
+        }
+        if (mImmediateActivity != null) {
+            writer.print(prefix); writer.print("mImmediateActivity=");
+                    writer.println(mImmediateActivity);
+        }
+        if (mActivity != null) {
+            writer.print(prefix); writer.print("mActivity=");
+                    writer.println(mActivity);
+        }
+        if (mArguments != null) {
+            writer.print(prefix); writer.print("mArguments="); writer.println(mArguments);
+        }
+        if (mSavedFragmentState != null) {
+            writer.print(prefix); writer.print("mSavedFragmentState=");
+                    writer.println(mSavedFragmentState);
+        }
+        if (mSavedViewState != null) {
+            writer.print(prefix); writer.print("mSavedViewState=");
+                    writer.println(mSavedViewState);
+        }
+        if (mTarget != null) {
+            writer.print(prefix); writer.print("mTarget="); writer.print(mTarget);
+                    writer.print(" mTargetRequestCode=");
+                    writer.println(mTargetRequestCode);
+        }
+        if (mNextAnim != 0) {
+            writer.print(prefix); writer.print("mNextAnim="); writer.println(mNextAnim);
+        }
+        if (mContainer != null) {
+            writer.print(prefix); writer.print("mContainer="); writer.println(mContainer);
+        }
+        if (mView != null) {
+            writer.print(prefix); writer.print("mView="); writer.println(mView);
+        }
+        if (mLoaderManager != null) {
+            writer.print(prefix); writer.print("mLoaderManager="); writer.print(mLoaderManager);
+                    writer.print(" mStarted="); writer.print(mStarted);
+                    writer.print(" mCheckedForLoaderManager=");
+                    writer.println(mCheckedForLoaderManager);
+        }
+    }
+
     void performStop() {
         onStop();
         if (mStarted) {
diff --git a/core/java/android/app/FragmentBreadCrumbs.java b/core/java/android/app/FragmentBreadCrumbs.java
index 0d39d0b..22e0747 100644
--- a/core/java/android/app/FragmentBreadCrumbs.java
+++ b/core/java/android/app/FragmentBreadCrumbs.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.app.FragmentManager.BackStackEntry;
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
@@ -139,14 +140,14 @@
         FragmentManager fm = mActivity.getFragmentManager();
         int numEntries = fm.countBackStackEntries();
         int numViews = mContainer.getChildCount();
-        for (int i=mTopEntry != null ? -1 : 0; i<numEntries; i++) {
-            FragmentManager.BackStackEntry bse = i == -1 ? mTopEntry : fm.getBackStackEntry(i);
-            int viewI = mTopEntry != null ? i+1 : i;
+        for (int i = mTopEntry != null ? -1 : 0; i < numEntries; i++) {
+            BackStackEntry bse = i == -1 ? mTopEntry : fm.getBackStackEntry(i);
+            int viewI = mTopEntry != null ? i + 1 : i;
             if (viewI < numViews) {
                 View v = mContainer.getChildAt(viewI);
                 Object tag = v.getTag();
                 if (tag != bse) {
-                    for (int j=viewI; j<numViews; j++) {
+                    for (int j = viewI; j < numViews; j++) {
                         mContainer.removeViewAt(viewI);
                     }
                     numViews = viewI;
@@ -163,13 +164,24 @@
                     text.setCompoundDrawables(null, null, null, null);
                 }
                 mContainer.addView(item);
+                item.setOnClickListener(mOnClickListener);
             }
         }
-        int viewI = mTopEntry != null ? numEntries+1 : numEntries;
+        int viewI = mTopEntry != null ? numEntries + 1 : numEntries;
         numViews = mContainer.getChildCount();
         while (numViews > viewI) {
             mContainer.removeViewAt(numViews-1);
             numViews--;
         }
     }
+
+    private OnClickListener mOnClickListener = new OnClickListener() {
+        public void onClick(View v) {
+            if (v.getTag() instanceof BackStackEntry) {
+                BackStackEntry bse = (BackStackEntry) v.getTag();
+                mActivity.getFragmentManager().popBackStack(bse.getId(),
+                        bse == mTopEntry? FragmentManager.POP_BACK_STACK_INCLUSIVE : 0);
+            }
+        }
+    };
 }
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 9f958246..da7ba6f 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -32,6 +32,8 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 
 /**
@@ -190,6 +192,16 @@
      * the given reference.
      */
     public Fragment getFragment(Bundle bundle, String key);
+
+    /**
+     * Print the FragmentManager's state into the given stream.
+     *
+     * @param prefix Text to print at the front of each line.
+     * @param fd The raw file descriptor that the dump is being sent to.
+     * @param writer A PrintWriter to which the dump is to be set.
+     * @param args additional arguments to the dump request.
+     */
+    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args);
 }
 
 final class FragmentManagerState implements Parcelable {
@@ -270,18 +282,23 @@
             execPendingActions();
         }
     };
+
+    @Override
     public FragmentTransaction openTransaction() {
         return new BackStackRecord(this);
     }
 
+    @Override
     public boolean popBackStack() {
         return popBackStackState(mActivity.mHandler, null, -1, 0);
     }
 
+    @Override
     public boolean popBackStack(String name, int flags) {
         return popBackStackState(mActivity.mHandler, name, -1, flags);
     }
 
+    @Override
     public boolean popBackStack(int id, int flags) {
         if (id < 0) {
             throw new IllegalArgumentException("Bad id: " + id);
@@ -289,14 +306,17 @@
         return popBackStackState(mActivity.mHandler, null, id, flags);
     }
 
+    @Override
     public int countBackStackEntries() {
         return mBackStack != null ? mBackStack.size() : 0;
     }
 
+    @Override
     public BackStackEntry getBackStackEntry(int index) {
         return mBackStack.get(index);
     }
 
+    @Override
     public void addOnBackStackChangedListener(OnBackStackChangedListener listener) {
         if (mBackStackChangeListeners == null) {
             mBackStackChangeListeners = new ArrayList<OnBackStackChangedListener>();
@@ -304,12 +324,14 @@
         mBackStackChangeListeners.add(listener);
     }
 
+    @Override
     public void removeOnBackStackChangedListener(OnBackStackChangedListener listener) {
         if (mBackStackChangeListeners != null) {
             mBackStackChangeListeners.remove(listener);
         }
     }
 
+    @Override
     public void putFragment(Bundle bundle, String key, Fragment fragment) {
         if (fragment.mIndex < 0) {
             throw new IllegalStateException("Fragment " + fragment
@@ -318,6 +340,7 @@
         bundle.putInt(key, fragment.mIndex);
     }
 
+    @Override
     public Fragment getFragment(Bundle bundle, String key) {
         int index = bundle.getInt(key, -1);
         if (index == -1) {
@@ -335,6 +358,51 @@
         return f;
     }
 
+    @Override
+    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+        if (mActive == null || mActive.size() <= 0) {
+            return;
+        }
+
+        writer.print(prefix); writer.println("Active Fragments:");
+
+        String innerPrefix = prefix + "    ";
+
+        int N = mActive.size();
+        for (int i=0; i<N; i++) {
+            Fragment f = mActive.get(i);
+            if (f != null) {
+                writer.print(prefix); writer.print("  #"); writer.print(i);
+                        writer.print(": "); writer.println(f.toString());
+                f.dump(innerPrefix, fd, writer, args);
+            }
+        }
+
+        if (mAdded != null) {
+            N = mAdded.size();
+            if (N > 0) {
+                writer.print(prefix); writer.println("Added Fragments:");
+                for (int i=0; i<N; i++) {
+                    Fragment f = mAdded.get(i);
+                    writer.print(prefix); writer.print("  #"); writer.print(i);
+                            writer.print(": "); writer.println(f.toString());
+                }
+            }
+        }
+
+        if (mBackStack != null) {
+            N = mBackStack.size();
+            if (N > 0) {
+                writer.print(prefix); writer.println("Back Stack:");
+                for (int i=0; i<N; i++) {
+                    BackStackRecord bs = mBackStack.get(i);
+                    writer.print(prefix); writer.print("  #"); writer.print(i);
+                            writer.print(": "); writer.println(bs.toString());
+                }
+            }
+        }
+    }
+
     Animator loadAnimator(Fragment fragment, int transit, boolean enter,
             int transitionStyle) {
         Animator animObj = fragment.onCreateAnimator(transit, enter,
@@ -436,7 +504,7 @@
                             if (f.mContainerId != 0) {
                                 container = (ViewGroup)mActivity.findViewById(f.mContainerId);
                                 if (container == null) {
-                                    throw new IllegalArgumentException("New view found for id 0x"
+                                    throw new IllegalArgumentException("No view found for id 0x"
                                             + Integer.toHexString(f.mContainerId)
                                             + " for fragment " + f);
                                 }
@@ -519,7 +587,7 @@
                         if (f.mView != null) {
                             // Need to save the current view state if not
                             // done already.
-                            if (!mActivity.isFinishing() && f.mSavedFragmentState == null) {
+                            if (!mActivity.isFinishing() && f.mSavedViewState == null) {
                                 saveFragmentViewState(f);
                             }
                         }
@@ -581,6 +649,10 @@
         f.mState = newState;
     }
     
+    void moveToState(Fragment f) {
+        moveToState(f, mCurState, 0, 0);
+    }
+
     void moveToState(int newState, boolean always) {
         moveToState(newState, 0, 0, always);
     }
@@ -655,7 +727,7 @@
             mNeedMenuInvalidate = true;
         }
         if (moveToStateNow) {
-            moveToState(fragment, mCurState, 0, 0);
+            moveToState(fragment);
         }
     }
     
@@ -1010,37 +1082,42 @@
                 FragmentState fs = new FragmentState(f);
                 active[i] = fs;
                 
-                if (mStateBundle == null) {
-                    mStateBundle = new Bundle();
-                }
-                f.onSaveInstanceState(mStateBundle);
-                if (!mStateBundle.isEmpty()) {
-                    fs.mSavedFragmentState = mStateBundle;
-                    mStateBundle = null;
-                }
-                
-                if (f.mView != null) {
-                    saveFragmentViewState(f);
-                    if (f.mSavedViewState != null) {
+                if (f.mState > Fragment.INITIALIZING && fs.mSavedFragmentState == null) {
+                    if (mStateBundle == null) {
+                        mStateBundle = new Bundle();
+                    }
+                    f.onSaveInstanceState(mStateBundle);
+                    if (!mStateBundle.isEmpty()) {
+                        fs.mSavedFragmentState = mStateBundle;
+                        mStateBundle = null;
+                    }
+
+                    if (f.mView != null) {
+                        saveFragmentViewState(f);
+                        if (f.mSavedViewState != null) {
+                            if (fs.mSavedFragmentState == null) {
+                                fs.mSavedFragmentState = new Bundle();
+                            }
+                            fs.mSavedFragmentState.putSparseParcelableArray(
+                                    FragmentManagerImpl.VIEW_STATE_TAG, f.mSavedViewState);
+                        }
+                    }
+
+                    if (f.mTarget != null) {
                         if (fs.mSavedFragmentState == null) {
                             fs.mSavedFragmentState = new Bundle();
                         }
-                        fs.mSavedFragmentState.putSparseParcelableArray(
-                                FragmentManagerImpl.VIEW_STATE_TAG, f.mSavedViewState);
+                        putFragment(fs.mSavedFragmentState,
+                                FragmentManagerImpl.TARGET_STATE_TAG, f.mTarget);
+                        if (f.mTargetRequestCode != 0) {
+                            fs.mSavedFragmentState.putInt(
+                                    FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG,
+                                    f.mTargetRequestCode);
+                        }
                     }
-                }
 
-                if (f.mTarget != null) {
-                    if (fs.mSavedFragmentState == null) {
-                        fs.mSavedFragmentState = new Bundle();
-                    }
-                    putFragment(fs.mSavedFragmentState,
-                            FragmentManagerImpl.TARGET_STATE_TAG, f.mTarget);
-                    if (f.mTargetRequestCode != 0) {
-                        fs.mSavedFragmentState.putInt(
-                                FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG,
-                                f.mTargetRequestCode);
-                    }
+                } else {
+                    fs.mSavedFragmentState = f.mSavedFragmentState;
                 }
                 
                 if (DEBUG) Log.v(TAG, "Saved state of " + f + ": "
@@ -1057,13 +1134,15 @@
         BackStackState[] backStack = null;
         
         // Build list of currently added fragments.
-        N = mAdded.size();
-        if (N > 0) {
-            added = new int[N];
-            for (int i=0; i<N; i++) {
-                added[i] = mAdded.get(i).mIndex;
-                if (DEBUG) Log.v(TAG, "saveAllState: adding fragment #" + i
-                        + ": " + mAdded.get(i));
+        if (mAdded != null) {
+            N = mAdded.size();
+            if (N > 0) {
+                added = new int[N];
+                for (int i=0; i<N; i++) {
+                    added[i] = mAdded.get(i).mIndex;
+                    if (DEBUG) Log.v(TAG, "saveAllState: adding fragment #" + i
+                            + ": " + mAdded.get(i));
+                }
             }
         }
         
@@ -1104,6 +1183,7 @@
                 fs.mInstance = f;
                 f.mSavedViewState = null;
                 f.mBackStackNesting = 0;
+                f.mInLayout = false;
                 f.mAdded = false;
                 if (fs.mSavedFragmentState != null) {
                     f.mSavedViewState = fs.mSavedFragmentState.getSparseParcelableArray(
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 039bcb9..1f8a7c58 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -105,7 +105,9 @@
     static final int EXTERNAL_STORAGE_UNAVAILABLE = 1;
     void dispatchPackageBroadcast(int cmd, String[] packages) throws RemoteException;
     void scheduleCrash(String msg) throws RemoteException;
-    
+    void dumpActivity(FileDescriptor fd, IBinder servicetoken, String[] args)
+            throws RemoteException;
+
     String descriptor = "android.app.IApplicationThread";
 
     int SCHEDULE_PAUSE_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;
@@ -143,4 +145,5 @@
     int DISPATCH_PACKAGE_BROADCAST_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+33;
     int SCHEDULE_CRASH_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+34;
     int DUMP_HEAP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+35;
+    int DUMP_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+36;
 }
diff --git a/core/java/android/net/DownloadManager.java b/core/java/android/net/DownloadManager.java
index 1081609..fc5ebb3 100644
--- a/core/java/android/net/DownloadManager.java
+++ b/core/java/android/net/DownloadManager.java
@@ -365,7 +365,6 @@
          *
          * @param show whether the download manager should show a notification for this download.
          * @return this object
-         * @hide
          */
         public Request setShowRunningNotification(boolean show) {
             mShowNotification = show;
diff --git a/core/java/android/net/LinkCapabilities.aidl b/core/java/android/net/LinkCapabilities.aidl
index 5f47baf..df72599 100644
--- a/core/java/android/net/LinkCapabilities.aidl
+++ b/core/java/android/net/LinkCapabilities.aidl
@@ -1,7 +1,6 @@
 /*
 **
-** Copyright (C) 2009 Qualcomm Innovation Center, Inc.  All Rights Reserved.
-** Copyright (C) 2009 The Android Open Source Project
+** 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.
diff --git a/core/java/android/net/LinkCapabilities.java b/core/java/android/net/LinkCapabilities.java
index d10a759..eb9166f 100644
--- a/core/java/android/net/LinkCapabilities.java
+++ b/core/java/android/net/LinkCapabilities.java
@@ -146,7 +146,7 @@
         // code these to match
 
         /** Default Role */
-        public static final String DEFAULT = "0";
+        public static final String DEFAULT = "default";
         /** Bulk down load */
         public static final String BULK_DOWNLOAD = "bulk.download";
         /** Bulk upload */
diff --git a/core/java/android/net/LinkProperties.aidl b/core/java/android/net/LinkProperties.aidl
index 73c7988..9cd06d5 100644
--- a/core/java/android/net/LinkProperties.aidl
+++ b/core/java/android/net/LinkProperties.aidl
@@ -1,7 +1,6 @@
 /*
 **
-** Copyright (C) 2009 Qualcomm Innovation Center, Inc.  All Rights Reserved.
-** Copyright (C) 2009 The Android Open Source Project
+** 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.
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 24aebfc..f411eac 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * 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.
diff --git a/core/java/android/net/LinkSocket.java b/core/java/android/net/LinkSocket.java
index d416ed0..5aa6451 100644
--- a/core/java/android/net/LinkSocket.java
+++ b/core/java/android/net/LinkSocket.java
@@ -197,6 +197,17 @@
 
     /**
      * Connect a duplicate socket socket to the same remote host address and port
+     * as the original with a timeout parameter.
+     * @param timeout the timeout value in milliseconds or 0 for infinite timeout
+     * @throws IOException if the socket is already connected or an error occurs
+     *                     while connecting
+     */
+    public void connect(int timeout) throws IOException {
+        if (DBG) log("connect(timeout) EX");
+    }
+
+    /**
+     * Connect a duplicate socket socket to the same remote host address and port
      * as the original.
      * @throws IOException if the socket is already connected or an error occurs
      *                     while connecting
@@ -237,9 +248,9 @@
      */
     @Override
     @Deprecated
-    public void bind(SocketAddress localAddr) throws IOException {
+    public void bind(SocketAddress localAddr) throws UnsupportedOperationException {
         if (DBG) log("bind(localAddr) EX throws IOException");
-        throw new IOException("bind is deprecated for LinkSocket");
+        throw new UnsupportedOperationException("bind is deprecated for LinkSocket");
     }
 
     /**
diff --git a/core/java/android/net/LinkSocketNotifier.java b/core/java/android/net/LinkSocketNotifier.java
index 183c767..28e2834 100644
--- a/core/java/android/net/LinkSocketNotifier.java
+++ b/core/java/android/net/LinkSocketNotifier.java
@@ -84,5 +84,5 @@
      * Get notified of every capability change
      * check for LinkSockets on that Link that are interested in that Capability - call them
      */
-    public void onCapabilityChanged(LinkSocket socket, LinkCapabilities changedCapabilities);
+    public void onCapabilitiesChanged(LinkSocket socket, LinkCapabilities changedCapabilities);
 }
diff --git a/core/java/android/net/ProxyProperties.java b/core/java/android/net/ProxyProperties.java
index fb59fed..140b71f 100644
--- a/core/java/android/net/ProxyProperties.java
+++ b/core/java/android/net/ProxyProperties.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 The Android Open Source Project
+ * 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.
diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java
index e89f7c2..be5b685 100644
--- a/core/java/android/os/MessageQueue.java
+++ b/core/java/android/os/MessageQueue.java
@@ -33,6 +33,7 @@
 public class MessageQueue {
     Message mMessages;
     private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
+    private IdleHandler[] mPendingIdleHandlers;
     private boolean mQuiting = false;
     boolean mQuitAllowed = true;
 
@@ -105,91 +106,75 @@
     }
 
     final Message next() {
-        boolean tryIdle = true;
-        // when we start out, we'll just touch the input pipes and then go from there
-        int timeToNextEventMillis = 0;
+        int pendingIdleHandlerCount = -1; // -1 only during first iteration
+        int nextPollTimeoutMillis = 0;
 
-        while (true) {
-            long now;
-            Object[] idlers = null;
+        for (;;) {
+            if (nextPollTimeoutMillis != 0) {
+                Binder.flushPendingCommands();
+            }
+            nativePollOnce(nextPollTimeoutMillis);
 
-            boolean dispatched = nativePollOnce(timeToNextEventMillis);
-
-            // Try to retrieve the next message, returning if found.
             synchronized (this) {
-                now = SystemClock.uptimeMillis();
-                Message msg = pullNextLocked(now);
+                // Try to retrieve the next message.  Return if found.
+                final long now = SystemClock.uptimeMillis();
+                final Message msg = mMessages;
                 if (msg != null) {
-                    msg.markInUse();
-                    return msg;
-                }
-                
-                if (tryIdle && mIdleHandlers.size() > 0) {
-                    idlers = mIdleHandlers.toArray();
-                }
-            }
-    
-            // There was no message so we are going to wait...  but first,
-            // if there are any idle handlers let them know.
-            boolean didIdle = false;
-            if (idlers != null) {
-                for (Object idler : idlers) {
-                    boolean keep = false;
-                    try {
-                        didIdle = true;
-                        keep = ((IdleHandler)idler).queueIdle();
-                    } catch (Throwable t) {
-                        Log.wtf("MessageQueue", "IdleHandler threw exception", t);
-                    }
-
-                    if (!keep) {
-                        synchronized (this) {
-                            mIdleHandlers.remove(idler);
-                        }
-                    }
-                }
-            }
-            
-            // While calling an idle handler, a new message could have been
-            // delivered...  so go back and look again for a pending message.
-            if (didIdle) {
-                tryIdle = false;
-                continue;
-            }
-
-            synchronized (this) {
-                // No messages, nobody to tell about it...  time to wait!
-                if (mMessages != null) {
-                    long longTimeToNextEventMillis = mMessages.when - now;
-                    
-                    if (longTimeToNextEventMillis > 0) {
-                        Binder.flushPendingCommands();
-                        timeToNextEventMillis = (int) Math.min(longTimeToNextEventMillis,
-                                Integer.MAX_VALUE);
+                    final long when = msg.when;
+                    if (now >= when) {
+                        mMessages = msg.next;
+                        if (Config.LOGV) Log.v("MessageQueue", "Returning message: " + msg);
+                        msg.markInUse();
+                        return msg;
                     } else {
-                        timeToNextEventMillis = 0;
+                        nextPollTimeoutMillis = (int) Math.min(when - now, Integer.MAX_VALUE);
                     }
                 } else {
-                    Binder.flushPendingCommands();
-                    timeToNextEventMillis = -1;
+                    nextPollTimeoutMillis = -1;
+                }
+
+                // If first time, then get the number of idlers to run.
+                if (pendingIdleHandlerCount < 0) {
+                    pendingIdleHandlerCount = mIdleHandlers.size();
+                }
+                if (pendingIdleHandlerCount == 0) {
+                    // No idle handlers to run.  Loop and wait some more.
+                    continue;
+                }
+
+                if (mPendingIdleHandlers == null) {
+                    mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
+                }
+                mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
+            }
+
+            // Run the idle handlers.
+            // We only ever reach this code block during the first iteration.
+            for (int i = 0; i < pendingIdleHandlerCount; i++) {
+                final IdleHandler idler = mPendingIdleHandlers[i];
+                mPendingIdleHandlers[i] = null; // release the reference to the handler
+
+                boolean keep = false;
+                try {
+                    keep = idler.queueIdle();
+                } catch (Throwable t) {
+                    Log.wtf("MessageQueue", "IdleHandler threw exception", t);
+                }
+
+                if (!keep) {
+                    synchronized (this) {
+                        mIdleHandlers.remove(idler);
+                    }
                 }
             }
-            // loop to the while(true) and do the appropriate nativeWait(when)
-        }
-    }
 
-    final Message pullNextLocked(long now) {
-        Message msg = mMessages;
-        if (msg != null) {
-            if (now >= msg.when) {
-                mMessages = msg.next;
-                if (Config.LOGV) Log.v(
-                    "MessageQueue", "Returning message: " + msg);
-                return msg;
-            }
-        }
+            // Reset the idle handler count to 0 so we do not run them again.
+            pendingIdleHandlerCount = 0;
 
-        return null;
+            // While calling an idle handler, a new message could have been delivered
+            // so go back and look again for a pending message without waiting.
+            nextPollTimeoutMillis = 0;
+        }
     }
 
     final boolean enqueueMessage(Message msg, long when) {
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 5fea6fe..e56e257 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -307,8 +307,10 @@
      * Requires the {@link android.Manifest.permission#REBOOT} permission.
      *
      * @param context      the Context to use
-     * @param packageFile  the update package to install.  Currently
-     * must be on the /cache or /data partitions.
+     * @param packageFile  the update package to install.  Must be on
+     * a partition mountable by recovery.  (The set of partitions
+     * known to recovery may vary from device to device.  Generally,
+     * /cache and /data are safe.)
      *
      * @throws IOException  if writing the recovery command file
      * fails, or if the reboot itself fails.
@@ -316,15 +318,6 @@
     public static void installPackage(Context context, File packageFile)
         throws IOException {
         String filename = packageFile.getCanonicalPath();
-
-        if (filename.startsWith("/cache/")) {
-            filename = "CACHE:" + filename.substring(7);
-        } else if (filename.startsWith("/data/")) {
-            filename = "DATA:" + filename.substring(6);
-        } else {
-            throw new IllegalArgumentException(
-                "Must start with /cache or /data: " + filename);
-        }
         Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");
         String arg = "--update_package=" + filename;
         bootCommand(context, arg);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 4d87b79..51dc6ae 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1494,6 +1494,12 @@
         public static final String AUTO_TIME = "auto_time";
 
         /**
+         * Value to specify if the user prefers the time zone
+         * to be automatically fetched from the network (NITZ). 1=yes, 0=no
+         */
+        public static final String AUTO_TIME_ZONE = "auto_time_zone";
+
+        /**
          * Display times as 12 or 24 hours
          *   12
          *   24
@@ -1775,6 +1781,7 @@
             TEXT_AUTO_PUNCTUATE,
             TEXT_SHOW_PASSWORD,
             AUTO_TIME,
+            AUTO_TIME_ZONE,
             TIME_12_24,
             DATE_FORMAT,
             ACCELEROMETER_ROTATION,
diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java
index 0408673..733b535 100644
--- a/core/java/android/text/method/ArrowKeyMovementMethod.java
+++ b/core/java/android/text/method/ArrowKeyMovementMethod.java
@@ -314,6 +314,8 @@
      * {@link MotionEvent#ACTION_CANCEL} event), the controller is reset to null.
      *
      * @param cursorController A cursor controller implementation
+     *
+     * @hide
      */
     public void setCursorController(CursorController cursorController) {
         mCursorController = cursorController;
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 458274f..d24af52 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -67,6 +67,7 @@
     // these are optional, set by the caller
     private boolean mFactorySet;
     private Factory mFactory;
+    private Factory2 mFactory2;
     private Filter mFilter;
 
     private final Object[] mConstructorArgs = new Object[2];
@@ -122,12 +123,33 @@
         public View onCreateView(String name, Context context, AttributeSet attrs);
     }
 
-    private static class FactoryMerger implements Factory {
+    public interface Factory2 extends Factory {
+        /**
+         * Version of {@link #onCreateView(String, Context, AttributeSet)}
+         * that also supplies the parent that the view created view will be
+         * placed in.
+         *
+         * @param parent The parent that the created view will be placed
+         * in; <em>note that this may be null</em>.
+         * @param name Tag name to be inflated.
+         * @param context The context the view is being created in.
+         * @param attrs Inflation attributes as specified in XML file.
+         *
+         * @return View Newly created view. Return null for the default
+         *         behavior.
+         */
+        public View onCreateView(View parent, String name, Context context, AttributeSet attrs);
+    }
+
+    private static class FactoryMerger implements Factory2 {
         private final Factory mF1, mF2;
+        private final Factory2 mF12, mF22;
         
-        FactoryMerger(Factory f1, Factory f2) {
+        FactoryMerger(Factory f1, Factory2 f12, Factory f2, Factory2 f22) {
             mF1 = f1;
             mF2 = f2;
+            mF12 = f12;
+            mF22 = f22;
         }
         
         public View onCreateView(String name, Context context, AttributeSet attrs) {
@@ -135,6 +157,14 @@
             if (v != null) return v;
             return mF2.onCreateView(name, context, attrs);
         }
+
+        public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
+            View v = mF12 != null ? mF12.onCreateView(parent, name, context, attrs)
+                    : mF1.onCreateView(name, context, attrs);
+            if (v != null) return v;
+            return mF22 != null ? mF22.onCreateView(parent, name, context, attrs)
+                    : mF2.onCreateView(name, context, attrs);
+        }
     }
     
     /**
@@ -162,6 +192,7 @@
     protected LayoutInflater(LayoutInflater original, Context newContext) {
         mContext = newContext;
         mFactory = original.mFactory;
+        mFactory2 = original.mFactory2;
         mFilter = original.mFilter;
     }
     
@@ -200,7 +231,7 @@
     }
 
     /**
-     * Return the current factory (or null). This is called on each element
+     * Return the current {@link Factory} (or null). This is called on each element
      * name. If the factory returns a View, add that to the hierarchy. If it
      * returns null, proceed to call onCreateView(name).
      */
@@ -209,6 +240,17 @@
     }
 
     /**
+     * Return the current {@link Factory2}.  Returns null if no factory is set
+     * or the set factory does not implement the {@link Factory2} interface.
+     * This is called on each element
+     * name. If the factory returns a View, add that to the hierarchy. If it
+     * returns null, proceed to call onCreateView(name).
+     */
+    public final Factory2 getFactory2() {
+        return mFactory2;
+    }
+
+    /**
      * Attach a custom Factory interface for creating views while using
      * this LayoutInflater.  This must not be null, and can only be set once;
      * after setting, you can not change the factory.  This is
@@ -234,7 +276,26 @@
         if (mFactory == null) {
             mFactory = factory;
         } else {
-            mFactory = new FactoryMerger(factory, mFactory);
+            mFactory = new FactoryMerger(factory, null, mFactory, mFactory2);
+        }
+    }
+
+    /**
+     * Like {@link #setFactory}, but allows you to set a {@link Factory2}
+     * interface.
+     */
+    public void setFactory2(Factory2 factory) {
+        if (mFactorySet) {
+            throw new IllegalStateException("A factory has already been set on this LayoutInflater");
+        }
+        if (factory == null) {
+            throw new NullPointerException("Given factory can not be null");
+        }
+        mFactorySet = true;
+        if (mFactory == null) {
+            mFactory = mFactory2 = factory;
+        } else {
+            mFactory = new FactoryMerger(factory, factory, mFactory, mFactory2);
         }
     }
 
@@ -384,7 +445,7 @@
                     rInflate(parser, root, attrs, false);
                 } else {
                     // Temp is the root view that was found in the xml
-                    View temp = createViewFromTag(name, attrs);
+                    View temp = createViewFromTag(root, name, attrs);
 
                     ViewGroup.LayoutParams params = null;
 
@@ -557,10 +618,27 @@
         return createView(name, "android.view.", attrs);
     }
 
+    /**
+     * Version of {@link #onCreateView(String, AttributeSet)} that also
+     * takes the future parent of the view being constructure.  The default
+     * implementation simply calls {@link #onCreateView(String, AttributeSet)}.
+     *
+     * @param parent The future parent of the returned view.  <em>Note that
+     * this may be null.</em>
+     * @param name The fully qualified class name of the View to be create.
+     * @param attrs An AttributeSet of attributes to apply to the View.
+     *
+     * @return View The View created.
+     */
+    protected View onCreateView(View parent, String name, AttributeSet attrs)
+            throws ClassNotFoundException {
+        return onCreateView(name, attrs);
+    }
+
     /*
      * default visibility so the BridgeInflater can override it.
      */
-    View createViewFromTag(String name, AttributeSet attrs) {
+    View createViewFromTag(View parent, String name, AttributeSet attrs) {
         if (name.equals("view")) {
             name = attrs.getAttributeValue(null, "class");
         }
@@ -568,12 +646,14 @@
         if (DEBUG) System.out.println("******** Creating view: " + name);
 
         try {
-            View view = (mFactory == null) ? null : mFactory.onCreateView(name,
-                    mContext, attrs);
+            View view;
+            if (mFactory2 != null) view = mFactory2.onCreateView(parent, name, mContext, attrs);
+            else if (mFactory != null) view = mFactory.onCreateView(name, mContext, attrs);
+            else view = null;
 
             if (view == null) {
                 if (-1 == name.indexOf('.')) {
-                    view = onCreateView(name, attrs);
+                    view = onCreateView(parent, name, attrs);
                 } else {
                     view = createView(name, null, attrs);
                 }
@@ -628,7 +708,7 @@
             } else if (TAG_MERGE.equals(name)) {
                 throw new InflateException("<merge /> must be the root element");
             } else {
-                final View view = createViewFromTag(name, attrs);
+                final View view = createViewFromTag(parent, name, attrs);
                 final ViewGroup viewGroup = (ViewGroup) parent;
                 final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
                 rInflate(parser, view, attrs, true);
@@ -689,7 +769,7 @@
                         // Inflate all children.
                         rInflate(childParser, parent, childAttrs, false);
                     } else {
-                        final View view = createViewFromTag(childName, childAttrs);
+                        final View view = createViewFromTag(parent, childName, childAttrs);
                         final ViewGroup group = (ViewGroup) parent;
 
                         // We try to load the layout params set in the <include /> tag. If
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 97d58d2..3d5aff7 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1613,12 +1613,6 @@
     private static final int AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
 
     /**
-     * Indicates that this view has a visible/touchable overlay.
-     * @hide
-     */
-    static final int HAS_OVERLAY = 0x10000000;
-
-    /**
      * Indicates that pivotX or pivotY were explicitly set and we should not assume the center
      * for transform operations
      *
@@ -3040,57 +3034,6 @@
         resetPressedState();
     }
 
-    /**
-     * Enable or disable drawing overlays after a full drawing pass. This enables a view to
-     * draw on a topmost overlay layer after normal drawing completes and get right of first
-     * refusal for touch events in the window.
-     * 
-     * <em>Warning:</em> Views that use this feature should take care to disable/enable overlay
-     * appropriately when they are attached/detached from their window. All overlays should be
-     * disabled when detached.
-     * 
-     * @param enabled true if overlay drawing should be enabled for this view, false otherwise
-     * 
-     * @see #onDrawOverlay(Canvas)
-     * 
-     * @hide
-     */
-    protected void setOverlayEnabled(boolean enabled) {
-        final boolean oldValue = (mPrivateFlags & HAS_OVERLAY) == HAS_OVERLAY;
-        mPrivateFlags = (mPrivateFlags & ~HAS_OVERLAY) | (enabled ? HAS_OVERLAY : 0);
-        if (enabled != oldValue) {
-            final ViewParent parent = getParent();
-            if (parent != null) {
-                try {
-                    parent.childOverlayStateChanged(this);
-                } catch (AbstractMethodError e) {
-                    Log.e(VIEW_LOG_TAG, "Could not propagate hasOverlay state", e);
-                }
-            }
-        }
-    }
-
-    /**
-     * @return true if this View has an overlay enabled.
-     * 
-     * @see #setOverlayEnabled(boolean)
-     * @see #onDrawOverlay(Canvas)
-     * 
-     * @hide
-     */
-    public boolean isOverlayEnabled() {
-        return (mPrivateFlags & HAS_OVERLAY) == HAS_OVERLAY;
-    }
-
-    /**
-     * Override this method to draw on an overlay layer above all other views in the window
-     * after the standard drawing pass is complete. This allows a view to draw outside its
-     * normal boundaries.
-     * @hide
-     */
-    public void onDrawOverlay(Canvas canvas) {
-    }
-
     private void resetPressedState() {
         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
             return;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 3db4857..2b92e872 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -245,11 +245,6 @@
     protected static final int FLAG_DISALLOW_INTERCEPT = 0x80000;
 
     /**
-     * When set, at least one child of this ViewGroup will return true from hasOverlay.
-     */
-    private static final int FLAG_CHILD_HAS_OVERLAY = 0x100000;
-
-    /**
      * When set, this ViewGroup will split MotionEvents to multiple child Views when appropriate.
      */
     private static final int FLAG_SPLIT_MOTION_EVENTS = 0x200000;
@@ -910,33 +905,6 @@
                 final View[] children = mChildren;
                 final int count = mChildrenCount;
 
-                // Check for children with overlays first. They don't rely on hit rects to determine
-                // if they can accept a new touch event.
-                if ((mGroupFlags & FLAG_CHILD_HAS_OVERLAY) == FLAG_CHILD_HAS_OVERLAY) {
-                    for (int i = count - 1; i >= 0; i--) {
-                        final View child = children[i];
-                        // Don't let children respond to events as an overlay during an animation.
-                        if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
-                                && child.getAnimation() == null
-                                && child.isOverlayEnabled()) {
-                            // offset the event to the view's coordinate system
-                            final float xc = scrolledXFloat - child.mLeft;
-                            final float yc = scrolledYFloat - child.mTop;
-                            ev.setLocation(xc, yc);
-                            child.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
-                            if (child.dispatchTouchEvent(ev))  {
-                                // Event handled, we have a target now.
-                                mMotionTarget = child;
-                                return true;
-                            }
-                            // The event didn't get handled, try the next view.
-                            // Don't reset the event's location, it's not
-                            // necessary here.
-                        }
-                    }
-                }
-
-                // Now check views normally.
                 for (int i = count - 1; i >= 0; i--) {
                     final View child = children[i];
                     if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
@@ -2774,8 +2742,6 @@
         if (clearChildFocus != null) {
             clearChildFocus(clearChildFocus);
         }
-
-        mGroupFlags &= ~FLAG_CHILD_HAS_OVERLAY;
     }
 
     /**
@@ -3024,8 +2990,7 @@
                 final int left = mLeft;
                 final int top = mTop;
 
-                if ((mGroupFlags & FLAG_CHILD_HAS_OVERLAY) == FLAG_CHILD_HAS_OVERLAY ||
-                        dirty.intersect(0, 0, mRight - left, mBottom - top) ||
+                if (dirty.intersect(0, 0, mRight - left, mBottom - top) ||
                         (mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION) {
                     mPrivateFlags &= ~DRAWING_CACHE_VALID;
 
@@ -4013,69 +3978,6 @@
     }
 
     /**
-     * Called when a child's overlay state changes between enabled/disabled.
-     * @param child Child view whose state has changed or null
-     * @hide
-     */
-    public void childOverlayStateChanged(View child) {
-        boolean childHasOverlay = false;
-        if (child != null) {
-            childHasOverlay = child.isOverlayEnabled();
-        } else {
-            final int childCount = getChildCount();
-            for (int i = 0; i < childCount; i++) {
-                if (childHasOverlay |= getChildAt(i).isOverlayEnabled()) {
-                    break;
-                }
-            }
-        }
-        
-        final boolean hasChildWithOverlay = childHasOverlay ||
-                (mGroupFlags & FLAG_CHILD_HAS_OVERLAY) == FLAG_CHILD_HAS_OVERLAY;
-
-        final boolean oldValue = isOverlayEnabled();
-        mGroupFlags = (mGroupFlags & ~FLAG_CHILD_HAS_OVERLAY) |
-                (hasChildWithOverlay ? FLAG_CHILD_HAS_OVERLAY : 0);
-        if (isOverlayEnabled() != oldValue) {
-            final ViewParent parent = getParent();
-            if (parent != null) {
-                try {
-                    parent.childOverlayStateChanged(this);
-                } catch (AbstractMethodError e) {
-                    Log.e("ViewGroup", "Could not propagate hasOverlay state", e);
-                }
-            }
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public boolean isOverlayEnabled() {
-        return super.isOverlayEnabled() ||
-                ((mGroupFlags & FLAG_CHILD_HAS_OVERLAY) == FLAG_CHILD_HAS_OVERLAY);
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    public void onDrawOverlay(Canvas canvas) {
-        if ((mGroupFlags & FLAG_CHILD_HAS_OVERLAY) == FLAG_CHILD_HAS_OVERLAY) {
-            final int childCount = getChildCount();
-            for (int i = 0; i < childCount; i++) {
-                final View child = getChildAt(i);
-                if (child.isOverlayEnabled()) {
-                    canvas.translate(child.mLeft - child.mScrollX, child.mTop - child.mScrollY);
-                    child.onDrawOverlay(canvas);
-                    canvas.translate(-(child.mLeft - child.mScrollX),
-                            -(child.mTop - child.mScrollY));
-                }
-            }
-        }
-    }
-
-    /**
      * LayoutParams are used by views to tell their parents how they want to be
      * laid out. See
      * {@link android.R.styleable#ViewGroup_Layout ViewGroup Layout Attributes}
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index d2907da..d7d4c3f 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -222,11 +222,4 @@
      */
     public boolean requestChildRectangleOnScreen(View child, Rect rectangle,
             boolean immediate);
-
-    /**
-     * Called when a child view's overlay state changes between enabled/disabled.
-     * @param child Child view whose state changed or null.
-     * @hide
-     */
-    public void childOverlayStateChanged(View child);
 }
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index cb9f84d..e71b5b6 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -206,8 +206,6 @@
     AudioManager mAudioManager;
 
     private final int mDensity;
-    
-    private boolean mHasOverlay;
 
     public static IWindowSession getWindowSession(Looper mainLooper) {
         synchronized (mStaticInit) {
@@ -1359,9 +1357,6 @@
                         canvas.setScreenDensity(scalingRequired
                                 ? DisplayMetrics.DENSITY_DEVICE : 0);
                         mView.draw(canvas);
-                        if (mHasOverlay) {
-                            mView.onDrawOverlay(canvas);
-                        }
                     } finally {
                         mAttachInfo.mIgnoreDirtyState = false;
                     }
@@ -2744,19 +2739,6 @@
         return scrollToRectOrFocus(rectangle, immediate);
     }
 
-    /**
-     * @hide
-     */
-    public void childOverlayStateChanged(View child) {
-        final boolean oldState = mHasOverlay;
-        mHasOverlay = child.isOverlayEnabled();
-        // Invalidate the whole thing when we change overlay states just in case
-        // something left chunks of data drawn someplace it shouldn't have.
-        if (mHasOverlay != oldState) {
-            child.invalidate();
-        }
-    }
-
     class TakenSurfaceHolder extends BaseSurfaceHolder {
         @Override
         public boolean onAllowLockCanvas() {
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 4a3e2a9..71f4f03 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -176,6 +176,7 @@
                 attrs, com.android.internal.R.styleable.PopupWindow, defStyleAttr, defStyleRes);
 
         mBackground = a.getDrawable(R.styleable.PopupWindow_popupBackground);
+        mAnimationStyle = a.getResourceId(R.styleable.PopupWindow_windowAnimationStyle, -1);
 
         // If this is a StateListDrawable, try to find and store the drawable to be
         // used when the drop-down is placed above its anchor view, and the one to be
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 3e5ddfc..d49b4d7f 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -96,7 +96,6 @@
 import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewConfiguration;
 import android.view.ViewDebug;
 import android.view.ViewGroup.LayoutParams;
 import android.view.ViewRoot;
@@ -199,6 +198,9 @@
     private static final int PRIORITY = 100;
 
     private int mCurrentAlpha = 255;    
+
+    private final int[] mTempCoords = new int[2];
+
     private ColorStateList mTextColor;
     private int mCurTextColor;
     private ColorStateList mHintTextColor;
@@ -3779,8 +3781,6 @@
             showError();
             mShowErrorAfterAttach = false;
         }
-        
-        updateOverlay();
     }
 
     @Override
@@ -3798,8 +3798,6 @@
         if (mError != null) {
             hideError();
         }
-        
-        setOverlayEnabled(false);
     }
 
     @Override
@@ -4169,19 +4167,6 @@
         canvas.restore();
     }
 
-    /**
-     * @hide
-     */
-    @Override
-    public void onDrawOverlay(Canvas canvas) {
-        if (mInsertionPointCursorController != null) {
-            mInsertionPointCursorController.draw(canvas);
-        }
-        if (mSelectionModifierCursorController != null) {
-            mSelectionModifierCursorController.draw(canvas);
-        }
-    }
-
     @Override
     public void getFocusedRect(Rect r) {
         if (mLayout == null) {
@@ -6768,31 +6753,17 @@
     public boolean onTouchEvent(MotionEvent event) {
         final int action = event.getActionMasked();
         if (action == MotionEvent.ACTION_DOWN) {
-            // Check to see if we're testing for our anchor overlay.
-            boolean handled = false;
-            final float x = event.getX();
-            final float y = event.getY();
-            if (x < 0 || x >= mRight - mLeft || y < 0 || y >= mBottom - mTop) {
-                if (mInsertionPointCursorController != null) {
-                    handled |= mInsertionPointCursorController.onTouchEvent(event);
-                }
-                if (mSelectionModifierCursorController != null) {
-                    handled |= mSelectionModifierCursorController.onTouchEvent(event);
-                }
-
-                if (!handled) {
-                    return false;
-                }
+            if (mInsertionPointCursorController != null) {
+                mInsertionPointCursorController.onTouchEvent(event);
+            }
+            if (mSelectionModifierCursorController != null) {
+                mSelectionModifierCursorController.onTouchEvent(event);
             }
 
             // Reset this state; it will be re-set if super.onTouchEvent
             // causes focus to move to the view.
             mTouchFocusSelected = false;
             mScrolled = false;
-
-            if (handled) {
-                return true;
-            }
         }
 
         final boolean superResult = super.onTouchEvent(event);
@@ -6808,7 +6779,6 @@
         }
 
         if ((mMovement != null || onCheckIsTextEditor()) && mText instanceof Spannable && mLayout != null) {
-
             if (mInsertionPointCursorController != null) {
                 mInsertionPointCursorController.onTouchEvent(event);
             }
@@ -6822,11 +6792,22 @@
             int oldSelStart = getSelectionStart();
             int oldSelEnd = getSelectionEnd();
 
+            final int oldScrollX = mScrollX;
+            final int oldScrollY = mScrollY;
+            
             if (mMovement != null) {
                 handled |= mMovement.onTouchEvent(this, (Spannable) mText, event);
             }
 
             if (isTextEditable()) {
+                if (mScrollX != oldScrollX || mScrollY != oldScrollY) {
+                    // Hide insertion anchor while scrolling. Leave selection.
+                    hideInsertionPointCursorController();
+                    if (mSelectionModifierCursorController != null &&
+                            mSelectionModifierCursorController.isShowing()) {
+                        mSelectionModifierCursorController.updatePosition();
+                    }
+                }
                 if (action == MotionEvent.ACTION_UP && isFocused() && !mScrolled) {
                     InputMethodManager imm = (InputMethodManager)
                           getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
@@ -7705,22 +7686,13 @@
         }
     }
 
-    private void updateOverlay() {
-        boolean enableOverlay = false;
-        if (mSelectionModifierCursorController != null) {
-            enableOverlay |= mSelectionModifierCursorController.isShowing();
-        }
-        if (mInsertionPointCursorController != null) {
-            enableOverlay |= mInsertionPointCursorController.isShowing();
-        }
-        setOverlayEnabled(enableOverlay);
-    }
-
     /**
      * A CursorController instance can be used to control a cursor in the text.
      *
      * It can be passed to an {@link ArrowKeyMovementMethod} which can intercepts events
      * and send them to this object instead of the cursor.
+     *
+     * @hide
      */
     public interface CursorController {
         /* Cursor fade-out animation duration, in milliseconds. */
@@ -7748,6 +7720,8 @@
          */
         public void updatePosition(int x, int y);
 
+        public void updatePosition();
+
         /**
          * The controller and the cursor's positions can be link by a fixed offset,
          * computed when the controller is touched, and then maintained as it moves
@@ -7766,154 +7740,192 @@
          * @param event The touch event
          */
         public boolean onTouchEvent(MotionEvent event);
-
-        /**
-         * Draws a visual representation of the controller on the canvas.
-         *
-         * Called at the end of {@link #draw(Canvas)}, in the content coordinates system.
-         * @param canvas The Canvas used by this TextView.
-         */
-        public void draw(Canvas canvas);
     }
 
-    private class Handle {
-        Drawable mDrawable;
-        // Vertical extension of the touch region
-        int mTopExtension, mBottomExtension;
-        // Position of the virtual finger position on screen
-        int mHotSpotVerticalPosition;
+    private class HandleView extends View {
+        private boolean mPositionOnTop = false;
+        private Drawable mDrawable;
+        private PopupWindow mContainer;
+        private int mPositionX;
+        private int mPositionY;
+        private CursorController mController;
+        private boolean mIsDragging;
 
-        Handle(Drawable drawable) {
-            mDrawable = drawable;
+        public HandleView(CursorController controller, Drawable handle) {
+            super(TextView.this.mContext);
+            mController = controller;
+            mDrawable = handle;
+            mContainer = new PopupWindow(TextView.this.mContext, null,
+                    com.android.internal.R.attr.textSelectHandleWindowStyle);
+        }
+
+        @Override
+        public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            setMeasuredDimension(mDrawable.getIntrinsicWidth(),
+                    mDrawable.getIntrinsicHeight());
+        }
+
+        public void show() {
+            if (!isPositionInBounds()) {
+                hide();
+                return;
+            }
+            mContainer.setContentView(this);
+            final int[] coords = mTempCoords;
+            TextView.this.getLocationOnScreen(coords);
+            coords[0] += mPositionX;
+            coords[1] += mPositionY;
+            mContainer.showAtLocation(TextView.this, 0, coords[0], coords[1]);
+        }
+
+        public void hide() {
+            mIsDragging = false;
+            mContainer.dismiss();
+        }
+
+        public boolean isShowing() {
+            return mContainer.isShowing();
+        }
+
+        private boolean isPositionInBounds() {
+            final int extendedPaddingTop = getExtendedPaddingTop();
+            final int extendedPaddingBottom = getExtendedPaddingBottom();
+            final int compoundPaddingLeft = getCompoundPaddingLeft();
+            final int compoundPaddingRight = getCompoundPaddingRight();
+
+            final TextView hostView = TextView.this;
+            final int right = hostView.mRight;
+            final int left = hostView.mLeft;
+            final int bottom = hostView.mBottom;
+            final int top = hostView.mTop;
+
+            final int clipLeft = left + compoundPaddingLeft;
+            final int clipTop = top + extendedPaddingTop;
+            final int clipRight = right - compoundPaddingRight;
+            final int clipBottom = bottom - extendedPaddingBottom;
+
+            final int handleWidth = mDrawable.getIntrinsicWidth();
+            return mPositionX >= clipLeft - handleWidth * 0.75f &&
+                    mPositionX <= clipRight + handleWidth * 0.25f &&
+                    mPositionY >= clipTop && mPositionY <= clipBottom;
+        }
+
+        private void moveTo(int x, int y) {
+            mPositionX = x - TextView.this.mScrollX;
+            mPositionY = y - TextView.this.mScrollY;
+            if (isPositionInBounds()) {
+                if (mContainer.isShowing()){
+                    final int[] coords = mTempCoords;
+                    TextView.this.getLocationOnScreen(coords);
+                    coords[0] += mPositionX;
+                    coords[1] += mPositionY;
+                    mContainer.update(coords[0], coords[1], mRight - mLeft, mBottom - mTop);
+                } else {
+                    show();
+                }
+            } else {
+                hide();
+            }
+        }
+
+        @Override
+        public void onDraw(Canvas c) {
+            mDrawable.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
+            if (mPositionOnTop) {
+                c.save();
+                c.rotate(180, (mRight - mLeft) / 2, (mBottom - mTop) / 2);
+                mDrawable.draw(c);
+                c.restore();
+            } else {
+                mDrawable.draw(c);
+            }
+        }
+
+        @Override
+        public boolean onTouchEvent(MotionEvent ev) {
+            switch (ev.getActionMasked()) {
+            case MotionEvent.ACTION_DOWN:
+                mIsDragging = true;
+                break;
+
+            case MotionEvent.ACTION_MOVE:
+                final float rawX = ev.getRawX();
+                final float rawY = ev.getRawY();
+                final int[] coords = mTempCoords;
+                TextView.this.getLocationOnScreen(coords);
+                final int x = (int) (rawX - coords[0] + 0.5f);
+                final int y = (int) (rawY - coords[1] + 0.5f);
+                mController.updatePosition(x, y);
+                break;
+
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_CANCEL:
+                mIsDragging = false;
+            }
+            return true;
+        }
+
+        public boolean isDragging() {
+            return mIsDragging;
         }
 
         void positionAtCursor(final int offset, boolean bottom) {
-            final int drawableWidth = mDrawable.getIntrinsicWidth();
-            final int drawableHeight = mDrawable.getIntrinsicHeight();
+            final int width = mDrawable.getIntrinsicWidth();
+            final int height = mDrawable.getIntrinsicHeight();
             final int line = mLayout.getLineForOffset(offset);
             final int lineTop = mLayout.getLineTop(line);
             final int lineBottom = mLayout.getLineBottom(line);
 
-            mHotSpotVerticalPosition = lineTop;
-
             final Rect bounds = sCursorControllerTempRect;
-            bounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - drawableWidth / 2.0)
-                + mScrollX;
-            bounds.top = (bottom ? lineBottom : lineTop) + mScrollY;
+            bounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - width / 2.0)
+                + TextView.this.mScrollX;
+            bounds.top = (bottom ? lineBottom : lineTop) + TextView.this.mScrollY;
 
-            mTopExtension = bottom ? 0 : drawableHeight / 2;
-            mBottomExtension = 0; //drawableHeight / 4;
-
-            // Extend touch region up when editing the last line of text (or a single line) so that
-            // it is easier to grab.
-            if (line == mLayout.getLineCount() - 1) {
-                mTopExtension = (lineBottom - lineTop) - drawableHeight / 2;
-            }
-
-            bounds.right = bounds.left + drawableWidth;
-            bounds.bottom = bounds.top + drawableHeight;
+            bounds.right = bounds.left + width;
+            bounds.bottom = bounds.top + height;
 
             convertFromViewportToContentCoordinates(bounds);
-            invalidate();
-            mDrawable.setBounds(bounds);
-            invalidate();
-        }
-
-        boolean hasFingerOn(float x, float y) {
-            // Simulate a 'fat finger' to ease grabbing of the controller.
-            // Expands according to controller image size instead of using dip distance.
-            // Assumes controller imager has a sensible size, proportionnal to screen density.
-            final int drawableWidth = mDrawable.getIntrinsicWidth();
-            final Rect fingerRect = sCursorControllerTempRect;
-            fingerRect.set((int) (x - drawableWidth / 2.0),
-                           (int) (y - mBottomExtension),
-                           (int) (x + drawableWidth / 2.0),
-                           (int) (y + mTopExtension));
-            fingerRect.offset(mScrollX, mScrollY);
-            return Rect.intersects(mDrawable.getBounds(), fingerRect);
-        }
-
-        void invalidate() {
-            final Rect bounds = mDrawable.getBounds();
-            TextView.this.invalidate(bounds.left, bounds.top,
-                    bounds.right, bounds.bottom);
-        }
-
-        void postInvalidate() {
-            final Rect bounds = mDrawable.getBounds();
-            TextView.this.postInvalidate(bounds.left, bounds.top,
-                    bounds.right, bounds.bottom);
-        }
-
-        void postInvalidateDelayed(long delay) {
-            final Rect bounds = mDrawable.getBounds();
-            TextView.this.postInvalidateDelayed(delay, bounds.left, bounds.top,
-                                                       bounds.right, bounds.bottom);
+            moveTo(bounds.left, bounds.top);
         }
     }
 
     class InsertionPointCursorController implements CursorController {
-        private static final int DELAY_BEFORE_FADE_OUT = 2100;
+        private static final int DELAY_BEFORE_FADE_OUT = 4100;
 
-        // Whether or not the cursor control is currently visible
-        private boolean mIsVisible = false;
-        // Starting time of the fade timer
-        private long mFadeOutTimerStart;
         // The cursor controller image
-        private final Handle mHandle;
-        // Used to detect a tap (vs drag) on the controller
-        private long mOnDownTimerStart;
+        private final HandleView mHandle;
         // Offset between finger hot point on cursor controller and actual cursor
         private float mOffsetX, mOffsetY;
 
+        private final Runnable mHider = new Runnable() {
+            public void run() {
+                hide();
+            }
+        };
+
         InsertionPointCursorController() {
             Resources res = mContext.getResources();
-            mHandle = new Handle(res.getDrawable(mTextSelectHandleRes));
+            mHandle = new HandleView(this, res.getDrawable(mTextSelectHandleRes));
         }
 
         public void show() {
-            updateDrawablePosition();
-            // Has to be done after updateDrawablePosition, so that previous position invalidate
-            // in only done if necessary.
-            mIsVisible = true;
-            updateOverlay();
+            updatePosition();
+            mHandle.show();
+            hideDelayed(DELAY_BEFORE_FADE_OUT);
         }
 
         public void hide() {
-            if (mIsVisible) {
-                long time = System.currentTimeMillis();
-                // Start fading out, only if not already in progress
-                if (time - mFadeOutTimerStart < DELAY_BEFORE_FADE_OUT) {
-                    mFadeOutTimerStart = time - DELAY_BEFORE_FADE_OUT;
-                    mHandle.postInvalidate();
-                }
-            }
+            mHandle.hide();
+            TextView.this.removeCallbacks(mHider);
+        }
+
+        private void hideDelayed(int msec) {
+            TextView.this.removeCallbacks(mHider);
+            TextView.this.postDelayed(mHider, msec);
         }
 
         public boolean isShowing() {
-            return mIsVisible;
-        }
-
-        public void draw(Canvas canvas) {
-            if (mIsVisible) {
-                int time = (int) (System.currentTimeMillis() - mFadeOutTimerStart);
-                if (time <= DELAY_BEFORE_FADE_OUT) {
-                    mHandle.postInvalidateDelayed(DELAY_BEFORE_FADE_OUT - time);
-                } else {
-                    time -= DELAY_BEFORE_FADE_OUT;
-                    if (time <= FADE_OUT_DURATION) {
-                        final int alpha = (int)
-                                         ((255.0 * (FADE_OUT_DURATION - time)) / FADE_OUT_DURATION);
-                        mHandle.mDrawable.setAlpha(alpha);
-                        mHandle.postInvalidateDelayed(30);
-                    } else {
-                        mHandle.mDrawable.setAlpha(0);
-                        mIsVisible = false;
-                        updateOverlay();
-                    }
-                }
-                mHandle.mDrawable.draw(canvas);
-            }
+            return mHandle.isShowing();
         }
 
         public void updatePosition(int x, int y) {
@@ -7922,81 +7934,22 @@
 
             if (offset != previousOffset) {
                 Selection.setSelection((Spannable) mText, offset);
-                updateDrawablePosition();
+                updatePosition();
             }
+            hideDelayed(DELAY_BEFORE_FADE_OUT);
         }
 
-        private void updateDrawablePosition() {
-            if (mIsVisible) {
-                // Clear previous cursor controller before bounds are updated
-                mHandle.postInvalidate();
-            }
-
+        public void updatePosition() {
             final int offset = getSelectionStart();
 
             if (offset < 0) {
                 // Should never happen, safety check.
                 Log.w(LOG_TAG, "Update cursor controller position called with no cursor");
-                mIsVisible = false;
-                updateOverlay();
+                hide();
                 return;
             }
 
             mHandle.positionAtCursor(offset, true);
-
-            mFadeOutTimerStart = System.currentTimeMillis();
-            mHandle.mDrawable.setAlpha(255);
-        }
-
-        public boolean onTouchEvent(MotionEvent event) {
-            if (isFocused() && isTextEditable() && mIsVisible) {
-                switch (event.getActionMasked()) {
-                    case MotionEvent.ACTION_DOWN : {
-                        final float x = event.getX();
-                        final float y = event.getY();
-
-                        if (mHandle.hasFingerOn(x, y)) {
-                            show();
-
-                            if (mMovement instanceof ArrowKeyMovementMethod) {
-                                ((ArrowKeyMovementMethod)mMovement).setCursorController(this);
-                            }
-
-                            if (mParent != null) {
-                                // Prevent possible scrollView parent from scrolling, so that
-                                // we can use auto-scrolling.
-                                mParent.requestDisallowInterceptTouchEvent(true);
-                            }
-
-                            final Rect bounds = mHandle.mDrawable.getBounds();
-                            mOffsetX = (bounds.left + bounds.right) / 2.0f - x;
-                            mOffsetY = mHandle.mHotSpotVerticalPosition - y;
-
-                            mOffsetX += viewportToContentHorizontalOffset();
-                            mOffsetY += viewportToContentVerticalOffset();
-
-                            mOnDownTimerStart = event.getEventTime();
-                            return true;
-                        }
-                        return false;
-                    }
-
-                    case MotionEvent.ACTION_UP : {
-                        int time = (int) (event.getEventTime() - mOnDownTimerStart);
-
-                        if (time <= ViewConfiguration.getTapTimeout()) {
-                            // A tap on the controller (not a drag) will move the cursor
-                            int offset = getOffset((int) event.getX(), (int) event.getY());
-                            Selection.setSelection((Spannable) mText, offset);
-
-                            // Modified by cancelLongPress and prevents the cursor from changing
-                            mScrolled = false;
-                        }
-                        break;
-                    }
-                }
-            }
-            return false;
         }
 
         public float getOffsetX() {
@@ -8006,88 +7959,59 @@
         public float getOffsetY() {
             return mOffsetY;
         }
+
+        public boolean onTouchEvent(MotionEvent ev) {
+            return false;
+        }
     }
 
     class SelectionModifierCursorController implements CursorController {
-        // Whether or not the selection controls are currently visible
-        private boolean mIsVisible = false;
-        // Whether that start or the end of selection controller is dragged
-        private boolean mStartIsDragged = false;
-        // Starting time of the fade timer
-        private long mFadeOutTimerStart;
         // The cursor controller images
-        private final Handle mStartHandle, mEndHandle;
+        private HandleView mStartHandle, mEndHandle;
         // Offset between finger hot point on active cursor controller and actual cursor
         private float mOffsetX, mOffsetY;
         // The offsets of that last touch down event. Remembered to start selection there.
         private int mMinTouchOffset, mMaxTouchOffset;
+        // Whether selection anchors are active
+        private boolean mIsShowing;
 
         SelectionModifierCursorController() {
             Resources res = mContext.getResources();
-            mStartHandle = new Handle(res.getDrawable(mTextSelectHandleLeftRes));
-            mEndHandle = new Handle(res.getDrawable(mTextSelectHandleRightRes));
+            mStartHandle = new HandleView(this, res.getDrawable(mTextSelectHandleLeftRes));
+            mEndHandle = new HandleView(this, res.getDrawable(mTextSelectHandleRightRes));
         }
 
         public void show() {
-            updateDrawablesPositions();
-            // Has to be done after updateDrawablePositions, so that previous position invalidate
-            // in only done if necessary.
-            mIsVisible = true;
-            updateOverlay();
-            mFadeOutTimerStart = -1;
+            mIsShowing = true;
+            updatePosition();
+            mStartHandle.show();
+            mEndHandle.show();
             hideInsertionPointCursorController();
         }
 
         public void hide() {
-            if (mIsVisible && (mFadeOutTimerStart < 0)) {
-                mFadeOutTimerStart = System.currentTimeMillis();
-                mStartHandle.postInvalidate();
-                mEndHandle.postInvalidate();
-            }
+            mStartHandle.hide();
+            mEndHandle.hide();
+            mIsShowing = false;
         }
 
         public boolean isShowing() {
-            return mIsVisible;
+            return mIsShowing;
         }
 
         public void cancelFadeOutAnimation() {
-            mIsVisible = false;
-            updateOverlay();
-            mStartHandle.postInvalidate();
-            mEndHandle.postInvalidate();
-        }
-
-        public void draw(Canvas canvas) {
-            if (mIsVisible) {
-                if (mFadeOutTimerStart >= 0) {
-                    int time = (int) (System.currentTimeMillis() - mFadeOutTimerStart);
-                    if (time <= FADE_OUT_DURATION) {
-                        final int alpha = 255 * (FADE_OUT_DURATION - time) / FADE_OUT_DURATION;
-                        mStartHandle.mDrawable.setAlpha(alpha);
-                        mEndHandle.mDrawable.setAlpha(alpha);
-                        mStartHandle.postInvalidateDelayed(30);
-                        mEndHandle.postInvalidateDelayed(30);
-                    } else {
-                        mStartHandle.mDrawable.setAlpha(0);
-                        mEndHandle.mDrawable.setAlpha(0);
-                        mIsVisible = false;
-                        updateOverlay();
-                    }
-                }
-                mStartHandle.mDrawable.draw(canvas);
-                mEndHandle.mDrawable.draw(canvas);
-            }
+            hide();
         }
 
         public void updatePosition(int x, int y) {
             int selectionStart = getSelectionStart();
             int selectionEnd = getSelectionEnd();
 
-            final int previousOffset = mStartIsDragged ? selectionStart : selectionEnd;
+            final int previousOffset = mStartHandle.isDragging() ? selectionStart : selectionEnd;
             int offset = getHysteresisOffset(x, y, previousOffset);
 
             // Handle the case where start and end are swapped, making sure start <= end
-            if (mStartIsDragged) {
+            if (mStartHandle.isDragging()) {
                 if (offset <= selectionEnd) {
                     if (selectionStart == offset) {
                         return; // no change, no need to redraw;
@@ -8096,7 +8020,9 @@
                 } else {
                     selectionStart = selectionEnd;
                     selectionEnd = offset;
-                    mStartIsDragged = false;
+                    HandleView temp = mStartHandle;
+                    mStartHandle = mEndHandle;
+                    mEndHandle = temp;
                 }
             } else {
                 if (offset >= selectionStart) {
@@ -8107,43 +8033,35 @@
                 } else {
                     selectionEnd = selectionStart;
                     selectionStart = offset;
-                    mStartIsDragged = true;
+                    HandleView temp = mStartHandle;
+                    mStartHandle = mEndHandle;
+                    mEndHandle = temp;
                 }
             }
 
             Selection.setSelection((Spannable) mText, selectionStart, selectionEnd);
-            updateDrawablesPositions();
+            updatePosition();
         }
 
-        private void updateDrawablesPositions() {
-            if (mIsVisible) {
-                // Clear previous cursor controller before bounds are updated
-                mStartHandle.postInvalidate();
-                mEndHandle.postInvalidate();
-            }
-
+        public void updatePosition() {
             final int selectionStart = getSelectionStart();
             final int selectionEnd = getSelectionEnd();
 
             if ((selectionStart < 0) || (selectionEnd < 0)) {
                 // Should never happen, safety check.
                 Log.w(LOG_TAG, "Update selection controller position called with no cursor");
-                mIsVisible = false;
-                updateOverlay();
+                hide();
                 return;
             }
 
-            boolean oneLineSelection =
-                mLayout.getLineForOffset(selectionStart) == mLayout.getLineForOffset(selectionEnd);
+            boolean oneLineSelection = mLayout.getLineForOffset(selectionStart) ==
+                    mLayout.getLineForOffset(selectionEnd);
             mStartHandle.positionAtCursor(selectionStart, oneLineSelection);
             mEndHandle.positionAtCursor(selectionEnd, true);
-
-            mStartHandle.mDrawable.setAlpha(255);
-            mEndHandle.mDrawable.setAlpha(255);
         }
 
         public boolean onTouchEvent(MotionEvent event) {
-            if (isTextEditable()) {
+            if (isFocused() && isTextEditable()) {
                 switch (event.getActionMasked()) {
                     case MotionEvent.ACTION_DOWN:
                         final int x = (int) event.getX();
@@ -8152,34 +8070,6 @@
                         // Remember finger down position, to be able to start selection from there
                         mMinTouchOffset = mMaxTouchOffset = mLastTouchOffset = getOffset(x, y);
 
-                        if (mIsVisible) {
-                            if (mMovement instanceof ArrowKeyMovementMethod) {
-                                boolean isOnStart = mStartHandle.hasFingerOn(x, y);
-                                boolean isOnEnd = mEndHandle.hasFingerOn(x, y);
-                                if (isOnStart || isOnEnd) {
-                                    if (mParent != null) {
-                                        // Prevent possible scrollView parent from scrolling, so
-                                        // that we can use auto-scrolling.
-                                        mParent.requestDisallowInterceptTouchEvent(true);
-                                    }
-
-                                    // In case both controllers are under finger (very small
-                                    // selection region), arbitrarily pick end controller.
-                                    mStartIsDragged = !isOnEnd;
-                                    final Handle draggedHandle =
-                                        mStartIsDragged ? mStartHandle : mEndHandle;
-                                    final Rect bounds = draggedHandle.mDrawable.getBounds();
-                                    mOffsetX = (bounds.left + bounds.right) / 2.0f - x;
-                                    mOffsetY = draggedHandle.mHotSpotVerticalPosition - y;
-
-                                    mOffsetX += viewportToContentHorizontalOffset();
-                                    mOffsetY += viewportToContentVerticalOffset();
-
-                                    ((ArrowKeyMovementMethod)mMovement).setCursorController(this);
-                                    return true;
-                                }
-                            }
-                        }
                         break;
 
                     case MotionEvent.ACTION_POINTER_DOWN:
@@ -8230,7 +8120,7 @@
          * @return true iff this controller is currently used to move the selection start.
          */
         public boolean isSelectionStartDragged() {
-            return mIsVisible && mStartIsDragged;
+            return mStartHandle.isDragging();
         }
     }
 
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index 344669c..ee44747 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -226,10 +226,8 @@
 
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
-static SkShader* RadialGradient_create1(JNIEnv* env, jobject,
-                                        float x, float y, float radius,
-                                        jintArray colorArray, jfloatArray posArray, int tileMode)
-{
+static SkShader* RadialGradient_create1(JNIEnv* env, jobject, float x, float y, float radius,
+        jintArray colorArray, jfloatArray posArray, int tileMode) {
     SkPoint center;
     center.set(SkFloatToScalar(x), SkFloatToScalar(y));
 
@@ -259,10 +257,8 @@
     return shader;
 }
 
-static SkShader* RadialGradient_create2(JNIEnv* env, jobject,
-                                        float x, float y, float radius,
-                                        int color0, int color1, int tileMode)
-{
+static SkShader* RadialGradient_create2(JNIEnv* env, jobject, float x, float y, float radius,
+        int color0, int color1, int tileMode) {
     SkPoint center;
     center.set(SkFloatToScalar(x), SkFloatToScalar(y));
 
@@ -276,11 +272,65 @@
     return s;
 }
 
+static SkiaShader* RadialGradient_postCreate1(JNIEnv* env, jobject o, SkShader* shader,
+        float x, float y, float radius, jintArray colorArray, jfloatArray posArray, int tileMode) {
+#ifdef USE_OPENGL_RENDERER
+    size_t count = env->GetArrayLength(colorArray);
+    const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
+
+    jfloat* storedPositions = new jfloat[count];
+    uint32_t* storedColors = new uint32_t[count];
+    for (size_t i = 0; i < count; i++) {
+        storedColors[i] = static_cast<uint32_t>(colorValues[i]);
+    }
+
+    if (posArray) {
+        AutoJavaFloatArray autoPos(env, posArray, count);
+        const float* posValues = autoPos.ptr();
+        for (size_t i = 0; i < count; i++) {
+            storedPositions[i] = posValues[i];
+        }
+    } else {
+        storedPositions[0] = 0.0f;
+        storedPositions[1] = 1.0f;
+    }
+
+    SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors,
+            storedPositions, count, shader, (SkShader::TileMode) tileMode, NULL,
+            (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
+
+    env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
+    return skiaShader;
+#else
+    return NULL;
+#endif
+}
+
+static SkiaShader* RadialGradient_postCreate2(JNIEnv* env, jobject o, SkShader* shader,
+        float x, float y, float radius, int color0, int color1, int tileMode) {
+#ifdef USE_OPENGL_RENDERER
+    float* storedPositions = new float[2];
+    storedPositions[0] = 0.0f;
+    storedPositions[1] = 1.0f;
+
+    uint32_t* storedColors = new uint32_t[2];
+    storedColors[0] = static_cast<uint32_t>(color0);
+    storedColors[1] = static_cast<uint32_t>(color1);
+
+    SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors,
+            storedPositions, 2, shader, (SkShader::TileMode) tileMode, NULL,
+            (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
+
+    return skiaShader;
+#else
+    return NULL;
+#endif
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 static SkShader* SweepGradient_create1(JNIEnv* env, jobject, float x, float y,
-                                    jintArray jcolors, jfloatArray jpositions)
-{
+        jintArray jcolors, jfloatArray jpositions) {
     size_t      count = env->GetArrayLength(jcolors);
     const jint* colors = env->GetIntArrayElements(jcolors, NULL);
     
@@ -307,8 +357,7 @@
 }
 
 static SkShader* SweepGradient_create2(JNIEnv* env, jobject, float x, float y,
-                                        int color0, int color1)
-{
+        int color0, int color1) {
     SkColor colors[2];
     colors[0] = color0;
     colors[1] = color1;
@@ -437,22 +486,24 @@
 };
 
 static JNINativeMethod gRadialGradientMethods[] = {
-    {"nativeCreate1",   "(FFF[I[FI)I",  (void*)RadialGradient_create1   },
-    {"nativeCreate2",   "(FFFIII)I",    (void*)RadialGradient_create2   }
+    { "nativeCreate1",     "(FFF[I[FI)I",  (void*)RadialGradient_create1     },
+    { "nativeCreate2",     "(FFFIII)I",    (void*)RadialGradient_create2     },
+    { "nativePostCreate1", "(IFFF[I[FI)I", (void*)RadialGradient_postCreate1 },
+    { "nativePostCreate2", "(IFFFIII)I",   (void*)RadialGradient_postCreate2 }
 };
 
 static JNINativeMethod gSweepGradientMethods[] = {
-    {"nativeCreate1",      "(FF[I[F)I",  (void*)SweepGradient_create1     },
-    {"nativeCreate2",      "(FFII)I",    (void*)SweepGradient_create2     },
+    { "nativeCreate1",     "(FF[I[F)I",  (void*)SweepGradient_create1     },
+    { "nativeCreate2",     "(FFII)I",    (void*)SweepGradient_create2     },
     { "nativePostCreate1", "(IFF[I[F)I", (void*)SweepGradient_postCreate1 },
     { "nativePostCreate2", "(IFFII)I",   (void*)SweepGradient_postCreate2 }
 };
 
 static JNINativeMethod gComposeShaderMethods[] = {
-    {"nativeCreate1",      "(III)I",   (void*)ComposeShader_create1     },
-    {"nativeCreate2",      "(III)I",   (void*)ComposeShader_create2     },
-    {"nativePostCreate1",  "(IIII)I",  (void*)ComposeShader_postCreate1 },
-    {"nativePostCreate2",  "(IIII)I",  (void*)ComposeShader_postCreate2 }
+    { "nativeCreate1",      "(III)I",   (void*)ComposeShader_create1     },
+    { "nativeCreate2",      "(III)I",   (void*)ComposeShader_create2     },
+    { "nativePostCreate1",  "(IIII)I",  (void*)ComposeShader_postCreate1 },
+    { "nativePostCreate2",  "(IIII)I",  (void*)ComposeShader_postCreate2 }
 };
 
 #include <android_runtime/AndroidRuntime.h>
diff --git a/core/res/res/layout/simple_list_item_2.xml b/core/res/res/layout/simple_list_item_2.xml
index 5eab54e..c87922c 100644
--- a/core/res/res/layout/simple_list_item_2.xml
+++ b/core/res/res/layout/simple_list_item_2.xml
@@ -15,8 +15,6 @@
 -->
 
 <TwoLineListItem xmlns:android="http://schemas.android.com/apk/res/android" 
-	android:paddingTop="2dip"
-	android:paddingBottom="2dip"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:minHeight="?android:attr/listPreferredItemHeight"
diff --git a/core/res/res/layout/simple_list_item_activated_1.xml b/core/res/res/layout/simple_list_item_activated_1.xml
new file mode 100644
index 0000000..8416df2
--- /dev/null
+++ b/core/res/res/layout/simple_list_item_activated_1.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/text1"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:textAppearance="?android:attr/textAppearanceLarge"
+    android:gravity="center_vertical"
+    android:background="?android:attr/activatedBackgroundIndicator"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+/>
diff --git a/core/res/res/layout/simple_list_item_activated_2.xml b/core/res/res/layout/simple_list_item_activated_2.xml
new file mode 100644
index 0000000..2ffbf02
--- /dev/null
+++ b/core/res/res/layout/simple_list_item_activated_2.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<TwoLineListItem xmlns:android="http://schemas.android.com/apk/res/android"
+    android:paddingTop="2dip"
+    android:paddingBottom="2dip"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="?android:attr/activatedBackgroundIndicator"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:mode="twoLine"
+>
+
+    <TextView android:id="@android:id/text1"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="6dip"
+        android:layout_marginTop="6dip"
+        android:textAppearance="?android:attr/textAppearanceLarge"
+    />
+
+    <TextView android:id="@android:id/text2"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_below="@android:id/text1"
+        android:layout_alignLeft="@android:id/text1"
+        android:textAppearance="?android:attr/textAppearanceSmall"
+    />
+
+</TwoLineListItem>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 779a33f..19b76ab 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -466,6 +466,9 @@
         <attr name="quickContactBadgeStyleSmallWindowMedium" format="reference" />
         <!-- Default quickcontact badge style with large quickcontact window. -->
         <attr name="quickContactBadgeStyleSmallWindowLarge" format="reference" />
+        <!-- Reference to a style that will be used for the window containing a text
+             selection anchor. -->
+        <attr name="textSelectHandleWindowStyle" format="reference" />
         <!-- Default ListPopupWindow style. -->
         <attr name="listPopupWindowStyle" format="reference" />
         <!-- Default PopupMenu style. -->
@@ -2355,6 +2358,7 @@
     </declare-styleable>
     <declare-styleable name="PopupWindow">
         <attr name="popupBackground" format="reference|color" />
+        <attr name="windowAnimationStyle" />
     </declare-styleable>
     <declare-styleable name="ViewAnimator">
         <!-- Identifier for the animation to use when a view is shown. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 6f53677..cdeb899 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1255,6 +1255,7 @@
   <public type="attr" name="textSelectHandleLeft" id="0x010102c5" />
   <public type="attr" name="textSelectHandleRight" id="0x010102c6" />
   <public type="attr" name="textSelectHandle" id="0x010102c7" />
+  <public type="attr" name="textSelectHandleWindowStyle" id="0x010102c8" />
 
   <public-padding type="attr" name="kraken_resource_pad" end="0x01010300" />
 
@@ -1376,6 +1377,16 @@
   <!-- A simple ListView item layout which can contain text and support (single or multiple) item selection. -->
   <public type="layout" name="simple_selectable_list_item" />
 
+  <!-- A version of {@link #simple_list_item_1} that is able to change its
+       background state to indicate when it is activated (that is checked by
+       a ListView). -->
+  <public type="layout" name="simple_list_item_activated_1" />
+
+  <!-- A version of {@link #simple_list_item_2} that is able to change its
+       background state to indicate when it is activated (that is checked by
+       a ListView). -->
+  <public type="layout" name="simple_list_item_activated_2" />
+
   <public type="style" name="Theme.WithActionBar" />
   <public type="style" name="Widget.Spinner.DropDown" />
   <public type="style" name="Widget.ActionButton" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index e8343f1..c37bb66 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -881,6 +881,17 @@
         <item name="android:background">@android:drawable/bottom_bar</item>
     </style>
 
+    <!-- Style for the small popup windows that contain text selection anchors. -->
+    <style name="Widget.TextSelectHandle">
+        <item name="android:windowAnimationStyle">@android:style/Animation.TextSelectHandle</item>
+    </style>
+
+    <!-- Style for animating text selection handles. -->
+    <style name="Animation.TextSelectHandle">
+        <item name="windowEnterAnimation">@android:anim/fade_in</item>
+        <item name="windowExitAnimation">@android:anim/fade_out</item>
+    </style>
+
     <style name="Widget.ActionBar">
         <item name="android:background">@android:drawable/action_bar_background</item>
         <item name="android:displayOptions">useLogo</item>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index fd39179..9425fc4 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -156,6 +156,7 @@
         <item name="textSelectHandleLeft">@android:drawable/text_select_handle_middle</item>
         <item name="textSelectHandleRight">@android:drawable/text_select_handle_middle</item>
         <item name="textSelectHandle">@android:drawable/text_select_handle_middle</item>
+        <item name="textSelectHandleWindowStyle">@android:style/Widget.TextSelectHandle</item>
 
         <!-- Widget styles -->
         <item name="absListViewStyle">@android:style/Widget.AbsListView</item>
diff --git a/core/tests/hosttests/src/android/content/pm/PackageManagerHostTestUtils.java b/core/tests/hosttests/src/android/content/pm/PackageManagerHostTestUtils.java
index 0f7351a..c698e99 100644
--- a/core/tests/hosttests/src/android/content/pm/PackageManagerHostTestUtils.java
+++ b/core/tests/hosttests/src/android/content/pm/PackageManagerHostTestUtils.java
@@ -601,7 +601,7 @@
             mTestRunErrorMessage = errorMessage;
         }
 
-        public void testRunStarted(int testCount) {
+        public void testRunStarted(String runName, int testCount) {
             // ignore
         }
 
diff --git a/graphics/java/android/graphics/RadialGradient.java b/graphics/java/android/graphics/RadialGradient.java
index b4e902d..897762c 100644
--- a/graphics/java/android/graphics/RadialGradient.java
+++ b/graphics/java/android/graphics/RadialGradient.java
@@ -40,6 +40,8 @@
             throw new IllegalArgumentException("color and position arrays must be of equal length");
         }
         native_instance = nativeCreate1(x, y, radius, colors, positions, tile.nativeInt);
+        native_shader = nativePostCreate1(native_instance, x, y, radius, colors, positions,
+                tile.nativeInt);
     }
 
 	/**	Create a shader that draws a radial gradient given the center and radius.
@@ -56,11 +58,18 @@
             throw new IllegalArgumentException("radius must be > 0");
         }
         native_instance = nativeCreate2(x, y, radius, color0, color1, tile.nativeInt);
+        native_shader = nativePostCreate2(native_instance, x, y, radius, color0, color1,
+                tile.nativeInt);
     }
 
 	private static native int nativeCreate1(float x, float y, float radius,
-                                            int colors[], float positions[], int tileMode);
+            int colors[], float positions[], int tileMode);
 	private static native int nativeCreate2(float x, float y, float radius,
-                                            int color0, int color1, int tileMode);
+            int color0, int color1, int tileMode);
+
+    private static native int nativePostCreate1(int native_shader, float x, float y, float radius,
+            int colors[], float positions[], int tileMode);
+    private static native int nativePostCreate2(int native_shader, float x, float y, float radius,
+            int color0, int color1, int tileMode);
 }
 
diff --git a/graphics/java/android/renderscript/BaseObj.java b/graphics/java/android/renderscript/BaseObj.java
index 3198e3f..715e3fb 100644
--- a/graphics/java/android/renderscript/BaseObj.java
+++ b/graphics/java/android/renderscript/BaseObj.java
@@ -32,6 +32,9 @@
     }
 
     public int getID() {
+        if (mDestroyed) {
+            throw new IllegalStateException("using a destroyed object.");
+        }
         return mID;
     }
 
diff --git a/include/media/stagefright/foundation/ADebug.h b/include/media/stagefright/foundation/ADebug.h
index 0f986a0..69021d8c 100644
--- a/include/media/stagefright/foundation/ADebug.h
+++ b/include/media/stagefright/foundation/ADebug.h
@@ -22,45 +22,18 @@
 
 #include <media/stagefright/foundation/ABase.h>
 #include <media/stagefright/foundation/AString.h>
+#include <utils/Log.h>
 
 namespace android {
 
-enum LogType {
-    VERBOSE,
-    INFO,
-    WARNING,
-    ERROR,
-    FATAL,
-};
-
-struct Logger {
-    Logger(LogType type);
-    virtual ~Logger();
-
-    template<class T> Logger &operator<<(const T &x) {
-        mMessage.append(x);
-
-        return *this;
-    }
-
-private:
-    android::AString mMessage;
-    LogType mLogType;
-
-    DISALLOW_EVIL_CONSTRUCTORS(Logger);
-};
-
-const char *LeafName(const char *s);
-
-#undef LOG
-#define LOG(type)    Logger(type) << LeafName(__FILE__) << ":" << __LINE__ << " "
+#define LITERAL_TO_STRING_INTERNAL(x)    #x
+#define LITERAL_TO_STRING(x) LITERAL_TO_STRING_INTERNAL(x)
 
 #define CHECK(condition)                                \
-    do {                                                \
-        if (!(condition)) {                             \
-            LOG(FATAL) << "CHECK(" #condition ") failed.";    \
-        }                                               \
-    } while (false)
+    LOG_ALWAYS_FATAL_IF(                                \
+            !(condition),                               \
+            __FILE__ ":" LITERAL_TO_STRING(__LINE__)    \
+            " CHECK(" #condition ") failed.")
 
 #define MAKE_COMPARATOR(suffix,op)                          \
     template<class A, class B>                              \
@@ -85,8 +58,10 @@
     do {                                                                \
         AString ___res = Compare_##suffix(x, y);                        \
         if (!___res.empty()) {                                          \
-            LOG(FATAL) << "CHECK_" #suffix "(" #x "," #y ") failed: "   \
-                       << ___res;                                       \
+            LOG_ALWAYS_FATAL(                                           \
+                    __FILE__ ":" LITERAL_TO_STRING(__LINE__)            \
+                    " CHECK_" #suffix "( " #x "," #y ") failed: %s",    \
+                    ___res.c_str());                                    \
         }                                                               \
     } while (false)
 
@@ -97,7 +72,7 @@
 #define CHECK_GE(x,y)   CHECK_OP(x,y,GE,>=)
 #define CHECK_GT(x,y)   CHECK_OP(x,y,GT,>)
 
-#define TRESPASS()      LOG(FATAL) << "Should not be here."
+#define TRESPASS()      LOG_ALWAYS_FATAL("Should not be here.")
 
 }  // namespace android
 
diff --git a/include/utils/Looper.h b/include/utils/Looper.h
index 7d90866..3f00b78 100644
--- a/include/utils/Looper.h
+++ b/include/utils/Looper.h
@@ -205,6 +205,7 @@
 
     int pollInner(int timeoutMillis);
 
+    static void initTLSKey();
     static void threadDestructor(void *st);
 };
 
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index 264ad3d..c698b5a 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -144,6 +144,12 @@
     return data[kTranslateY];
 }
 
+void Matrix4::multiply(float v) {
+    for (int i = 0; i < 16; i++) {
+        data[i] *= v;
+    }
+}
+
 void Matrix4::loadTranslate(float x, float y, float z) {
     loadIdentity();
     data[kTranslateX] = x;
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index c247a67..0608efe 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -83,6 +83,8 @@
         load(u);
     }
 
+    void multiply(float v);
+
     void translate(float x, float y, float z) {
         Matrix4 u;
         u.loadTranslate(x, y, z);
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index bcc1edf..3e9412c 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -40,9 +40,12 @@
         "uniform vec2 gradientStart;\n"
         "uniform mat4 screenSpace;\n",
         // Circular
-        "",
+        "uniform vec2 gradientStart;\n"
+        "uniform mat4 gradientMatrix;\n"
+        "uniform mat4 screenSpace;\n",
         // Sweep
         "uniform vec2 gradientStart;\n"
+        "uniform mat4 gradientMatrix;\n"
         "uniform mat4 screenSpace;\n"
 };
 const char* gVS_Header_Uniforms_HasBitmap =
@@ -56,7 +59,7 @@
         // Linear
         "varying float index;\n",
         // Circular
-        "",
+        "varying vec2 circular;\n",
         // Sweep
         "varying vec2 sweep;\n"
 };
@@ -69,10 +72,11 @@
         "    vec4 location = screenSpace * position;\n"
         "    index = dot(location.xy - gradientStart, gradient) * gradientLength;\n",
         // Circular
-        "",
+        "    vec4 location = screenSpace * position;\n"
+        "    circular = (gradientMatrix * vec4(location.xy - gradientStart, 0.0, 0.0)).xy;\n",
         // Sweep
         "    vec4 location = screenSpace * position;\n"
-        "    sweep = location.xy - gradientStart;\n"
+        "    sweep = (gradientMatrix * vec4(location.xy - gradientStart, 0.0, 0.0)).xy;\n"
 };
 const char* gVS_Main_OutBitmapTexCoords =
         "    vec4 bitmapCoords = textureTransform * position;\n"
@@ -98,6 +102,7 @@
         // Linear
         "uniform sampler2D gradientSampler;\n",
         // Circular
+        "uniform float gradientRadius;\n"
         "uniform sampler2D gradientSampler;\n",
         // Sweep
         "uniform sampler2D gradientSampler;\n"
@@ -129,7 +134,8 @@
         // Linear
         "    vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n",
         // Circular
-        "",
+        "    float index = length(circular) * gradientRadius;\n"
+        "    vec4 gradientColor = texture2D(gradientSampler, vec2(index, 0.5));\n",
         // Sweep
         "    float index = atan(sweep.y, sweep.x) * 0.15915494309; // inv(2 * PI)\n"
         "    vec4 gradientColor = texture2D(gradientSampler, vec2(index - floor(index), 0.5));\n"
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index c5d9767..9e1f6c2 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -209,6 +209,30 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+// Circular gradient shader
+///////////////////////////////////////////////////////////////////////////////
+
+SkiaCircularGradientShader::SkiaCircularGradientShader(float x, float y, float radius,
+        uint32_t* colors, float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
+        SkMatrix* matrix, bool blend):
+        SkiaSweepGradientShader(kCircularGradient, x, y, colors, positions, count, key,
+                tileMode, matrix, blend),
+        mRadius(radius) {
+}
+
+void SkiaCircularGradientShader::describe(ProgramDescription& description,
+        const Extensions& extensions) {
+    description.hasGradient = true;
+    description.gradientType = ProgramDescription::kGradientCircular;
+}
+
+void SkiaCircularGradientShader::setupProgram(Program* program, const mat4& modelView,
+        const Snapshot& snapshot, GLuint* textureUnit) {
+    SkiaSweepGradientShader::setupProgram(program, modelView, snapshot, textureUnit);
+    glUniform1f(program->getUniform("gradientRadius"), 1.0f / mRadius);
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // Sweep gradient shader
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -219,6 +243,13 @@
         mX(x), mY(y), mColors(colors), mPositions(positions), mCount(count) {
 }
 
+SkiaSweepGradientShader::SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors,
+        float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
+        SkMatrix* matrix, bool blend):
+        SkiaShader(type, key, tileMode, tileMode, matrix, blend),
+        mX(x), mY(y), mColors(colors), mPositions(positions), mCount(count) {
+}
+
 SkiaSweepGradientShader::~SkiaSweepGradientShader() {
     delete[] mColors;
     delete[] mPositions;
@@ -243,10 +274,15 @@
     float left = mX;
     float top = mY;
 
+    mat4 shaderMatrix;
     if (mMatrix) {
-        mat4 shaderMatrix(*mMatrix);
+        shaderMatrix.load(*mMatrix);
         shaderMatrix.mapPoint(left, top);
     }
+
+    mat4 copy(shaderMatrix);
+    shaderMatrix.loadInverse(copy);
+
     snapshot.transform->mapPoint(left, top);
 
     mat4 screenSpace(*snapshot.transform);
@@ -255,6 +291,7 @@
     // Uniforms
     bindTexture(texture->id, gTileModes[mTileX], gTileModes[mTileY], textureSlot);
     glUniform1i(program->getUniform("gradientSampler"), textureSlot);
+    glUniformMatrix4fv(program->getUniform("gradientMatrix"), 1, GL_FALSE, &shaderMatrix.data[0]);
     glUniform2f(program->getUniform("gradientStart"), left, top);
     glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
 }
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index b67bfee..0023c46 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -152,12 +152,15 @@
             SkShader* key, SkMatrix* matrix, bool blend);
     ~SkiaSweepGradientShader();
 
-    void describe(ProgramDescription& description, const Extensions& extensions);
-    void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
+    virtual void describe(ProgramDescription& description, const Extensions& extensions);
+    virtual void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
             GLuint* textureUnit);
     void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot);
 
-private:
+protected:
+    SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors, float* positions,
+            int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);
+
     float mX, mY;
     uint32_t* mColors;
     float* mPositions;
@@ -165,6 +168,21 @@
 }; // struct SkiaSweepGradientShader
 
 /**
+ * A shader that draws a circular gradient.
+ */
+struct SkiaCircularGradientShader: public SkiaSweepGradientShader {
+    SkiaCircularGradientShader(float x, float y, float radius, uint32_t* colors, float* positions,
+            int count, SkShader* key,SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);
+
+    void describe(ProgramDescription& description, const Extensions& extensions);
+    void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
+            GLuint* textureUnit);
+
+private:
+    float mRadius;
+}; // struct SkiaCircularGradientShader
+
+/**
  * A shader that draws two shaders, composited with an xfermode.
  */
 struct SkiaComposeShader: public SkiaShader {
diff --git a/libs/rs/java/tests/src/com/android/rs/test/primitives.rs b/libs/rs/java/tests/src/com/android/rs/test/primitives.rs
index b6148eff..39bd2c4 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/primitives.rs
+++ b/libs/rs/java/tests/src/com/android/rs/test/primitives.rs
@@ -3,7 +3,9 @@
 #pragma rs export_func(rs_primitives_test)
 
 // Testing primitive types
-static float floatTest = 1.0;
+#pragma rs export_var(floatTest)
+#pragma rs export_var(doubleTest)
+static float floatTest = 1.99f;
 static double doubleTest = 2.05;
 static char charTest = -8;
 static short shortTest = -16;
@@ -16,7 +18,7 @@
     bool failed = false;
     start();
 
-    _RS_ASSERT(floatTest == 1.0);
+    _RS_ASSERT(floatTest == 1.99f);
     _RS_ASSERT(doubleTest == 2.05);
     _RS_ASSERT(charTest == -8);
     _RS_ASSERT(shortTest == -16);
diff --git a/libs/utils/Looper.cpp b/libs/utils/Looper.cpp
index b46279e..d2dd6eb 100644
--- a/libs/utils/Looper.cpp
+++ b/libs/utils/Looper.cpp
@@ -24,16 +24,15 @@
 
 namespace android {
 
-static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
-static bool gHaveTLS = false;
-static pthread_key_t gTLS = 0;
-
 // Hint for number of file descriptors to be associated with the epoll instance.
 static const int EPOLL_SIZE_HINT = 8;
 
 // Maximum number of file descriptors for which to retrieve poll events each iteration.
 static const int EPOLL_MAX_EVENTS = 16;
 
+static pthread_once_t gTLSOnce = PTHREAD_ONCE_INIT;
+static pthread_key_t gTLSKey = 0;
+
 Looper::Looper(bool allowNonCallbacks) :
         mAllowNonCallbacks(allowNonCallbacks),
         mResponseIndex(0) {
@@ -56,6 +55,7 @@
             errno);
 
     struct epoll_event eventItem;
+    memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
     eventItem.events = EPOLLIN;
     eventItem.data.fd = mWakeReadPipeFd;
     result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
@@ -69,6 +69,11 @@
     close(mEpollFd);
 }
 
+void Looper::initTLSKey() {
+    int result = pthread_key_create(& gTLSKey, threadDestructor);
+    LOG_ALWAYS_FATAL_IF(result != 0, "Could not allocate TLS key.");
+}
+
 void Looper::threadDestructor(void *st) {
     Looper* const self = static_cast<Looper*>(st);
     if (self != NULL) {
@@ -83,7 +88,7 @@
         looper->incStrong((void*)threadDestructor);
     }
 
-    pthread_setspecific(gTLS, looper.get());
+    pthread_setspecific(gTLSKey, looper.get());
 
     if (old != NULL) {
         old->decStrong((void*)threadDestructor);
@@ -91,17 +96,10 @@
 }
 
 sp<Looper> Looper::getForThread() {
-    if (!gHaveTLS) {
-        pthread_mutex_lock(&gTLSMutex);
-        if (pthread_key_create(&gTLS, threadDestructor) != 0) {
-            pthread_mutex_unlock(&gTLSMutex);
-            return NULL;
-        }
-        gHaveTLS = true;
-        pthread_mutex_unlock(&gTLSMutex);
-    }
+    int result = pthread_once(& gTLSOnce, initTLSKey);
+    LOG_ALWAYS_FATAL_IF(result != 0, "pthread_once failed");
 
-    return (Looper*)pthread_getspecific(gTLS);
+    return (Looper*)pthread_getspecific(gTLSKey);
 }
 
 sp<Looper> Looper::prepare(int opts) {
@@ -331,6 +329,7 @@
         request.data = data;
 
         struct epoll_event eventItem;
+        memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
         eventItem.events = epollEvents;
         eventItem.data.fd = fd;
 
diff --git a/media/java/android/media/Visualizer.java b/media/java/android/media/Visualizer.java
index 453fc04..33222ff 100755
--- a/media/java/android/media/Visualizer.java
+++ b/media/java/android/media/Visualizer.java
@@ -218,13 +218,16 @@
     public int setEnabled(boolean enabled)
     throws IllegalStateException {
         synchronized (mStateLock) {
-            if ((enabled && mState != STATE_INITIALIZED) ||
-                    (!enabled && mState != STATE_ENABLED)) {
+            if (mState == STATE_UNINITIALIZED) {
                 throw(new IllegalStateException("setEnabled() called in wrong state: "+mState));
             }
-            int status = native_setEnabled(enabled);
-            if (status == SUCCESS) {
-                mState = enabled ? STATE_ENABLED : STATE_INITIALIZED;
+            int status = SUCCESS;
+            if ((enabled && (mState == STATE_INITIALIZED)) ||
+                    (!enabled && (mState == STATE_ENABLED))) {
+                status = native_setEnabled(enabled);
+                if (status == SUCCESS) {
+                    mState = enabled ? STATE_ENABLED : STATE_INITIALIZED;
+                }
             }
             return status;
         }
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
index 8ab57c93..03a6bbb 100644
--- a/media/libeffects/visualizer/EffectVisualizer.cpp
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -239,6 +239,24 @@
     }
 
     // all code below assumes stereo 16 bit PCM output and input
+
+    // derive capture scaling factor from peak value in current buffer
+    // this gives more interesting captures for display.
+    int32_t shift = 32;
+    for (size_t i = 0; i < inBuffer->frameCount; i++) {
+        int32_t smp = inBuffer->s16[i];
+        if (smp < 0) smp = -smp;
+        int32_t clz = __builtin_clz(smp);
+        if (shift > clz) shift = clz;
+    }
+    // never scale by less than 8 to avoid returning unaltered PCM signal.
+    // add one to combine the division by 2 needed after summing left and right channels below
+    if (20 > shift) {
+        shift = (31 - 8 + 1) - shift;
+    } else {
+        shift = (3 + 1);
+    }
+
     uint32_t captIdx;
     uint32_t inIdx;
     uint8_t *buf = pContext->mCaptureBuf[pContext->mCurrentBuf];
@@ -246,7 +264,7 @@
          inIdx < inBuffer->frameCount && captIdx < pContext->mCaptureSize;
          inIdx++, captIdx++) {
         int32_t smp = inBuffer->s16[2 * inIdx] + inBuffer->s16[2 * inIdx + 1];
-        smp = (smp + (1 << 8)) >> 9;
+        smp = (smp + (1 << (shift - 1))) >> shift;
         buf[captIdx] = ((uint8_t)smp)^0x80;
     }
     pContext->mCaptureIdx = captIdx;
@@ -369,7 +387,7 @@
 
 
     case VISU_CMD_CAPTURE:
-        if (pReplyData == NULL || *replySize != (int)pContext->mCaptureSize) {
+        if (pReplyData == NULL || *replySize != pContext->mCaptureSize) {
             LOGV("VISU_CMD_CAPTURE() error *replySize %d pContext->mCaptureSize %d",
                     *replySize, pContext->mCaptureSize);
             return -EINVAL;
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 9171aab..3a0fc41 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -132,7 +132,7 @@
 }
 
 void PageCache::copy(size_t from, void *data, size_t size) {
-    LOG(VERBOSE) << "copy from " << from << " size " << size;
+    LOGV("copy from %d size %d", from, size);
 
     CHECK_LE(from + size, mTotalSize);
 
@@ -228,7 +228,7 @@
 }
 
 void NuCachedSource2::fetchInternal() {
-    LOG(VERBOSE) << "fetchInternal";
+    LOGV("fetchInternal");
 
     CHECK_EQ(mFinalStatus, (status_t)OK);
 
@@ -240,11 +240,11 @@
     Mutex::Autolock autoLock(mLock);
 
     if (n < 0) {
-        LOG(ERROR) << "source returned error " << n;
+        LOGE("source returned error %ld", n);
         mFinalStatus = n;
         mCache->releasePage(page);
     } else if (n == 0) {
-        LOG(INFO) << "ERROR_END_OF_STREAM";
+        LOGI("ERROR_END_OF_STREAM");
         mFinalStatus = ERROR_END_OF_STREAM;
         mCache->releasePage(page);
     } else {
@@ -254,10 +254,10 @@
 }
 
 void NuCachedSource2::onFetch() {
-    LOG(VERBOSE) << "onFetch";
+    LOGV("onFetch");
 
     if (mFinalStatus != OK) {
-        LOG(VERBOSE) << "EOS reached, done prefetching for now";
+        LOGV("EOS reached, done prefetching for now");
         mFetching = false;
     }
 
@@ -268,7 +268,7 @@
 
     if (mFetching || keepAlive) {
         if (keepAlive) {
-            LOG(INFO) << "Keep alive";
+            LOGI("Keep alive");
         }
 
         fetchInternal();
@@ -276,7 +276,7 @@
         mLastFetchTimeUs = ALooper::GetNowUs();
 
         if (mFetching && mCache->totalSize() >= kHighWaterThreshold) {
-            LOG(INFO) << "Cache full, done prefetching for now";
+            LOGI("Cache full, done prefetching for now");
             mFetching = false;
         }
     } else {
@@ -289,7 +289,7 @@
 }
 
 void NuCachedSource2::onRead(const sp<AMessage> &msg) {
-    LOG(VERBOSE) << "onRead";
+    LOGV("onRead");
 
     int64_t offset;
     CHECK(msg->findInt64("offset", &offset));
@@ -339,14 +339,14 @@
     size_t actualBytes = mCache->releaseFromStart(maxBytes);
     mCacheOffset += actualBytes;
 
-    LOG(INFO) << "restarting prefetcher, totalSize = " << mCache->totalSize();
+    LOGI("restarting prefetcher, totalSize = %d", mCache->totalSize());
     mFetching = true;
 }
 
 ssize_t NuCachedSource2::readAt(off_t offset, void *data, size_t size) {
     Mutex::Autolock autoSerializer(mSerializer);
 
-    LOG(VERBOSE) << "readAt offset " << offset << " size " << size;
+    LOGV("readAt offset %ld, size %d", offset, size);
 
     Mutex::Autolock autoLock(mLock);
 
@@ -406,7 +406,7 @@
 }
 
 ssize_t NuCachedSource2::readInternal(off_t offset, void *data, size_t size) {
-    LOG(VERBOSE) << "readInternal offset " << offset << " size " << size;
+    LOGV("readInternal offset %ld size %d", offset, size);
 
     Mutex::Autolock autoLock(mLock);
 
@@ -442,7 +442,7 @@
         return size;
     }
 
-    LOG(VERBOSE) << "deferring read";
+    LOGV("deferring read");
 
     return -EAGAIN;
 }
@@ -455,7 +455,7 @@
         return OK;
     }
 
-    LOG(INFO) << "new range: offset= " << offset;
+    LOGI("new range: offset= %ld", offset);
 
     mCacheOffset = offset;
 
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 4e79575..1b2be41 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1821,7 +1821,7 @@
 
         case OMX_EventError:
         {
-            LOGE("ERROR(0x%08lx, %ld)", data1, data2);
+            CODEC_LOGE("ERROR(0x%08lx, %ld)", data1, data2);
 
             setState(ERROR);
             break;
diff --git a/media/libstagefright/ThreadedSource.cpp b/media/libstagefright/ThreadedSource.cpp
index 5add2a5..38c6e2d 100644
--- a/media/libstagefright/ThreadedSource.cpp
+++ b/media/libstagefright/ThreadedSource.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "ThreadedSource"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
 #include "include/ThreadedSource.h"
 
 #include <media/stagefright/foundation/ADebug.h>
diff --git a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
index 7483d60..3c0b736 100644
--- a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
+++ b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
@@ -232,6 +232,53 @@
     }
 }
 
+MediaBuffer *AVCDecoder::drainOutputBuffer() {
+    int32_t index;
+    int32_t Release;
+    AVCFrameIO Output;
+    Output.YCbCr[0] = Output.YCbCr[1] = Output.YCbCr[2] = NULL;
+    AVCDec_Status status = PVAVCDecGetOutput(mHandle, &index, &Release, &Output);
+
+    if (status != AVCDEC_SUCCESS) {
+        LOGV("PVAVCDecGetOutput returned error %d", status);
+        return NULL;
+    }
+
+    CHECK(index >= 0);
+    CHECK(index < (int32_t)mFrames.size());
+
+    MediaBuffer *mbuf = mFrames.editItemAt(index);
+
+    bool skipFrame = false;
+
+    if (mTargetTimeUs >= 0) {
+        int64_t timeUs;
+        CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
+        CHECK(timeUs <= mTargetTimeUs);
+
+        if (timeUs < mTargetTimeUs) {
+            // We're still waiting for the frame with the matching
+            // timestamp and we won't return the current one.
+            skipFrame = true;
+
+            LOGV("skipping frame at %lld us", timeUs);
+        } else {
+            LOGV("found target frame at %lld us", timeUs);
+
+            mTargetTimeUs = -1;
+        }
+    }
+
+    if (!skipFrame) {
+        mbuf->set_range(0, mbuf->size());
+        mbuf->add_ref();
+
+        return mbuf;
+    }
+
+    return new MediaBuffer(0);
+}
+
 status_t AVCDecoder::read(
         MediaBuffer **out, const ReadOptions *options) {
     *out = NULL;
@@ -279,7 +326,8 @@
                 seekOptions.clearSeekTo();
 
                 if (err != OK) {
-                    return err;
+                    *out = drainOutputBuffer();
+                    return (*out == NULL)  ? err : (status_t)OK;
                 }
 
                 if (mInputBuffer->range_length() > 0) {
@@ -415,51 +463,12 @@
                         fragSize);
 
                 if (res == AVCDEC_PICTURE_OUTPUT_READY) {
-                    int32_t index;
-                    int32_t Release;
-                    AVCFrameIO Output;
-                    Output.YCbCr[0] = Output.YCbCr[1] = Output.YCbCr[2] = NULL;
-
-                    AVCDec_Status status =
-                        PVAVCDecGetOutput(mHandle, &index, &Release, &Output);
-
-                    if (status != AVCDEC_SUCCESS) {
-                        LOGV("PVAVCDecGetOutput returned error %d", status);
+                    MediaBuffer *mbuf = drainOutputBuffer();
+                    if (mbuf == NULL) {
                         break;
                     }
 
-                    CHECK(index >= 0);
-                    CHECK(index < (int32_t)mFrames.size());
-
-                    MediaBuffer *mbuf = mFrames.editItemAt(index);
-
-                    bool skipFrame = false;
-
-                    if (mTargetTimeUs >= 0) {
-                        int64_t timeUs;
-                        CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
-                        CHECK(timeUs <= mTargetTimeUs);
-
-                        if (timeUs < mTargetTimeUs) {
-                            // We're still waiting for the frame with the matching
-                            // timestamp and we won't return the current one.
-                            skipFrame = true;
-
-                            LOGV("skipping frame at %lld us", timeUs);
-                        } else {
-                            LOGV("found target frame at %lld us", timeUs);
-
-                            mTargetTimeUs = -1;
-                        }
-                    }
-
-                    if (!skipFrame) {
-                        *out = mbuf;
-                        (*out)->set_range(0, (*out)->size());
-                        (*out)->add_ref();
-                    } else {
-                        *out = new MediaBuffer(0);
-                    }
+                    *out = mbuf;
 
                     // Do _not_ release input buffer yet.
 
@@ -496,6 +505,7 @@
 
             case AVC_NALTYPE_AUD:
             case AVC_NALTYPE_FILL:
+            case AVC_NALTYPE_EOSEQ:
             {
                 *out = new MediaBuffer(0);
 
diff --git a/media/libstagefright/foundation/ADebug.cpp b/media/libstagefright/foundation/ADebug.cpp
deleted file mode 100644
index 16f8b22..0000000
--- a/media/libstagefright/foundation/ADebug.cpp
+++ /dev/null
@@ -1,76 +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.
- */
-
-#include "ADebug.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifdef ANDROID
-#include <cutils/log.h>
-#endif
-
-namespace android {
-
-Logger::Logger(LogType type)
-    : mLogType(type) {
-    switch (mLogType) {
-        case VERBOSE:
-            mMessage = "V ";
-            break;
-        case INFO:
-            mMessage = "I ";
-            break;
-        case WARNING:
-            mMessage = "W ";
-            break;
-        case ERROR:
-            mMessage = "E ";
-            break;
-        case FATAL:
-            mMessage = "F ";
-            break;
-
-        default:
-            break;
-    }
-}
-
-Logger::~Logger() {
-    if (mLogType == VERBOSE) {
-        return;
-    }
-
-    mMessage.append("\n");
-
-#if defined(ANDROID) && 1
-    LOG_PRI(ANDROID_LOG_INFO, "ADebug", "%s", mMessage.c_str());
-#else
-    fprintf(stderr, mMessage.c_str());
-    fflush(stderr);
-#endif
-
-    if (mLogType == FATAL) {
-        abort();
-    }
-}
-
-const char *LeafName(const char *s) {
-    const char *lastSlash = strrchr(s, '/');
-    return lastSlash != NULL ? lastSlash + 1 : s;
-}
-
-}  // namespace android
diff --git a/media/libstagefright/foundation/ALooperRoster.cpp b/media/libstagefright/foundation/ALooperRoster.cpp
index 65f7593..7683113 100644
--- a/media/libstagefright/foundation/ALooperRoster.cpp
+++ b/media/libstagefright/foundation/ALooperRoster.cpp
@@ -74,7 +74,7 @@
     ssize_t index = mHandlers.indexOfKey(msg->target());
 
     if (index < 0) {
-        LOG(WARNING) << "failed to post message. Target handler not registered.";
+        LOGW("failed to post message. Target handler not registered.");
         return;
     }
 
@@ -83,8 +83,8 @@
     sp<ALooper> looper = info.mLooper.promote();
 
     if (looper == NULL) {
-        LOG(WARNING) << "failed to post message. "
-                        "Target handler still registered, but object gone.";
+        LOGW("failed to post message. "
+             "Target handler still registered, but object gone.");
 
         mHandlers.removeItemsAt(index);
         return;
@@ -102,8 +102,7 @@
         ssize_t index = mHandlers.indexOfKey(msg->target());
 
         if (index < 0) {
-            LOG(WARNING) << "failed to deliver message. "
-                         << "Target handler not registered.";
+            LOGW("failed to deliver message. Target handler not registered.");
             return;
         }
 
@@ -111,8 +110,8 @@
         handler = info.mHandler.promote();
 
         if (handler == NULL) {
-            LOG(WARNING) << "failed to deliver message. "
-                            "Target handler registered, but object gone.";
+            LOGW("failed to deliver message. "
+                 "Target handler registered, but object gone.");
 
             mHandlers.removeItemsAt(index);
             return;
diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk
index f6a8a52..ffa7db0 100644
--- a/media/libstagefright/foundation/Android.mk
+++ b/media/libstagefright/foundation/Android.mk
@@ -5,7 +5,6 @@
     AAtomizer.cpp               \
     ABitReader.cpp              \
     ABuffer.cpp                 \
-    ADebug.cpp                  \
     AHandler.cpp                \
     ALooper.cpp                 \
     ALooperRoster.cpp           \
diff --git a/media/libstagefright/foundation/hexdump.cpp b/media/libstagefright/foundation/hexdump.cpp
index 093b587..9f6bf9e 100644
--- a/media/libstagefright/foundation/hexdump.cpp
+++ b/media/libstagefright/foundation/hexdump.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "hexdump"
+#include <utils/Log.h>
+
 #include "hexdump.h"
 
 #include "ADebug.h"
@@ -63,7 +67,7 @@
             }
         }
 
-        LOG(INFO) << line;
+        LOGI("%s", line.c_str());
 
         offset += 16;
     }
diff --git a/media/libstagefright/include/AVCDecoder.h b/media/libstagefright/include/AVCDecoder.h
index 898c90a..eb3b142 100644
--- a/media/libstagefright/include/AVCDecoder.h
+++ b/media/libstagefright/include/AVCDecoder.h
@@ -82,6 +82,8 @@
 
     void releaseFrames();
 
+    MediaBuffer *drainOutputBuffer();
+
     AVCDecoder(const AVCDecoder &);
     AVCDecoder &operator=(const AVCDecoder &);
 };
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index 72de8d7..9952783 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ATSParser"
+#include <utils/Log.h>
+
 #include "ATSParser.h"
 
 #include "AnotherPacketSource.h"
@@ -31,6 +35,10 @@
 
 namespace android {
 
+// I want the expression "y" evaluated even if verbose logging is off.
+#define MY_LOGV(x, y) \
+    do { unsigned tmp = y; LOGV(x, tmp); } while (0)
+
 static const size_t kTSPacketSize = 188;
 
 struct ATSParser::Program : public RefBase {
@@ -115,36 +123,33 @@
 
 void ATSParser::Program::parseProgramMap(ABitReader *br) {
     unsigned table_id = br->getBits(8);
-    LOG(VERBOSE) << "  table_id = " << table_id;
+    LOGV("  table_id = %u", table_id);
     CHECK_EQ(table_id, 0x02u);
 
-    unsigned section_syntax_indictor = br->getBits(1);
-    LOG(VERBOSE) << "  section_syntax_indictor = " << section_syntax_indictor;
-    CHECK_EQ(section_syntax_indictor, 1u);
+    unsigned section_syntax_indicator = br->getBits(1);
+    LOGV("  section_syntax_indicator = %u", section_syntax_indicator);
+    CHECK_EQ(section_syntax_indicator, 1u);
 
     CHECK_EQ(br->getBits(1), 0u);
-    LOG(VERBOSE) << "  reserved = " << br->getBits(2);
+    MY_LOGV("  reserved = %u", br->getBits(2));
 
     unsigned section_length = br->getBits(12);
-    LOG(VERBOSE) << "  section_length = " << section_length;
+    LOGV("  section_length = %u", section_length);
     CHECK((section_length & 0xc00) == 0);
     CHECK_LE(section_length, 1021u);
 
-    LOG(VERBOSE) << "  program_number = " << br->getBits(16);
-    LOG(VERBOSE) << "  reserved = " << br->getBits(2);
-    LOG(VERBOSE) << "  version_number = " << br->getBits(5);
-    LOG(VERBOSE) << "  current_next_indicator = " << br->getBits(1);
-    LOG(VERBOSE) << "  section_number = " << br->getBits(8);
-    LOG(VERBOSE) << "  last_section_number = " << br->getBits(8);
-    LOG(VERBOSE) << "  reserved = " << br->getBits(3);
-
-    LOG(VERBOSE) << "  PCR_PID = "
-              << StringPrintf("0x%04x", br->getBits(13));
-
-    LOG(VERBOSE) << "  reserved = " << br->getBits(4);
+    MY_LOGV("  program_number = %u", br->getBits(16));
+    MY_LOGV("  reserved = %u", br->getBits(2));
+    MY_LOGV("  version_number = %u", br->getBits(5));
+    MY_LOGV("  current_next_indicator = %u", br->getBits(1));
+    MY_LOGV("  section_number = %u", br->getBits(8));
+    MY_LOGV("  last_section_number = %u", br->getBits(8));
+    MY_LOGV("  reserved = %u", br->getBits(3));
+    MY_LOGV("  PCR_PID = 0x%04x", br->getBits(13));
+    MY_LOGV("  reserved = %u", br->getBits(4));
 
     unsigned program_info_length = br->getBits(12);
-    LOG(VERBOSE) << "  program_info_length = " << program_info_length;
+    LOGV("  program_info_length = %u", program_info_length);
     CHECK((program_info_length & 0xc00) == 0);
 
     br->skipBits(program_info_length * 8);  // skip descriptors
@@ -158,19 +163,17 @@
         CHECK_GE(infoBytesRemaining, 5u);
 
         unsigned streamType = br->getBits(8);
-        LOG(VERBOSE) << "    stream_type = "
-                  << StringPrintf("0x%02x", streamType);
+        LOGV("    stream_type = 0x%02x", streamType);
 
-        LOG(VERBOSE) << "    reserved = " << br->getBits(3);
+        MY_LOGV("    reserved = %u", br->getBits(3));
 
         unsigned elementaryPID = br->getBits(13);
-        LOG(VERBOSE) << "    elementary_PID = "
-                  << StringPrintf("0x%04x", elementaryPID);
+        LOGV("    elementary_PID = 0x%04x", elementaryPID);
 
-        LOG(VERBOSE) << "    reserved = " << br->getBits(4);
+        MY_LOGV("    reserved = %u", br->getBits(4));
 
         unsigned ES_info_length = br->getBits(12);
-        LOG(VERBOSE) << "    ES_info_length = " << ES_info_length;
+        LOGV("    ES_info_length = %u", ES_info_length);
         CHECK((ES_info_length & 0xc00) == 0);
 
         CHECK_GE(infoBytesRemaining - 5, ES_info_length);
@@ -180,10 +183,10 @@
 #else
         unsigned info_bytes_remaining = ES_info_length;
         while (info_bytes_remaining >= 2) {
-            LOG(VERBOSE) << "      tag = " << StringPrintf("0x%02x", br->getBits(8));
+            MY_LOGV("      tag = 0x%02x", br->getBits(8));
 
             unsigned descLength = br->getBits(8);
-            LOG(VERBOSE) << "      len = " << descLength;
+            LOGV("      len = %u", descLength);
 
             CHECK_GE(info_bytes_remaining, 2 + descLength);
 
@@ -209,7 +212,7 @@
 
     CHECK_EQ(infoBytesRemaining, 0u);
 
-    LOG(VERBOSE) << "  CRC = " << StringPrintf("0x%08x", br->getBits(32));
+    MY_LOGV("  CRC = 0x%08x", br->getBits(32));
 }
 
 sp<MediaSource> ATSParser::Program::getSource(SourceType type) {
@@ -255,7 +258,7 @@
     }
 
     size_t payloadSizeBits = br->numBitsLeft();
-    CHECK_EQ(payloadSizeBits % 8, 0u);
+    CHECK((payloadSizeBits % 8) == 0);
 
     CHECK_LE(mBuffer->size() + payloadSizeBits / 8, mBuffer->capacity());
 
@@ -266,16 +269,15 @@
 void ATSParser::Stream::parsePES(ABitReader *br) {
     unsigned packet_startcode_prefix = br->getBits(24);
 
-    LOG(VERBOSE) << "packet_startcode_prefix = "
-              << StringPrintf("0x%08x", packet_startcode_prefix);
+    LOGV("packet_startcode_prefix = 0x%08x", packet_startcode_prefix);
 
     CHECK_EQ(packet_startcode_prefix, 0x000001u);
 
     unsigned stream_id = br->getBits(8);
-    LOG(VERBOSE) << "stream_id = " << StringPrintf("0x%02x", stream_id);
+    LOGV("stream_id = 0x%02x", stream_id);
 
     unsigned PES_packet_length = br->getBits(16);
-    LOG(VERBOSE) << "PES_packet_length = " << PES_packet_length;
+    LOGV("PES_packet_length = %u", PES_packet_length);
 
     if (stream_id != 0xbc  // program_stream_map
             && stream_id != 0xbe  // padding_stream
@@ -287,33 +289,32 @@
             && stream_id != 0xf8) {  // H.222.1 type E
         CHECK_EQ(br->getBits(2), 2u);
 
-        LOG(VERBOSE) << "PES_scrambling_control = " << br->getBits(2);
-        LOG(VERBOSE) << "PES_priority = " << br->getBits(1);
-        LOG(VERBOSE) << "data_alignment_indicator = " << br->getBits(1);
-        LOG(VERBOSE) << "copyright = " << br->getBits(1);
-        LOG(VERBOSE) << "original_or_copy = " << br->getBits(1);
+        MY_LOGV("PES_scrambling_control = %u", br->getBits(2));
+        MY_LOGV("PES_priority = %u", br->getBits(1));
+        MY_LOGV("data_alignment_indicator = %u", br->getBits(1));
+        MY_LOGV("copyright = %u", br->getBits(1));
+        MY_LOGV("original_or_copy = %u", br->getBits(1));
 
         unsigned PTS_DTS_flags = br->getBits(2);
-        LOG(VERBOSE) << "PTS_DTS_flags = " << PTS_DTS_flags;
+        LOGV("PTS_DTS_flags = %u", PTS_DTS_flags);
 
         unsigned ESCR_flag = br->getBits(1);
-        LOG(VERBOSE) << "ESCR_flag = " << ESCR_flag;
+        LOGV("ESCR_flag = %u", ESCR_flag);
 
         unsigned ES_rate_flag = br->getBits(1);
-        LOG(VERBOSE) << "ES_rate_flag = " << ES_rate_flag;
+        LOGV("ES_rate_flag = %u", ES_rate_flag);
 
         unsigned DSM_trick_mode_flag = br->getBits(1);
-        LOG(VERBOSE) << "DSM_trick_mode_flag = " << DSM_trick_mode_flag;
+        LOGV("DSM_trick_mode_flag = %u", DSM_trick_mode_flag);
 
         unsigned additional_copy_info_flag = br->getBits(1);
-        LOG(VERBOSE) << "additional_copy_info_flag = "
-                  << additional_copy_info_flag;
+        LOGV("additional_copy_info_flag = %u", additional_copy_info_flag);
 
-        LOG(VERBOSE) << "PES_CRC_flag = " << br->getBits(1);
-        LOG(VERBOSE) << "PES_extension_flag = " << br->getBits(1);
+        MY_LOGV("PES_CRC_flag = %u", br->getBits(1));
+        MY_LOGV("PES_extension_flag = %u", br->getBits(1));
 
         unsigned PES_header_data_length = br->getBits(8);
-        LOG(VERBOSE) << "PES_header_data_length = " << PES_header_data_length;
+        LOGV("PES_header_data_length = %u", PES_header_data_length);
 
         unsigned optional_bytes_remaining = PES_header_data_length;
 
@@ -331,8 +332,8 @@
             PTS |= br->getBits(15);
             CHECK_EQ(br->getBits(1), 1u);
 
-            LOG(VERBOSE) << "PTS = " << PTS;
-            // LOG(INFO) << "PTS = " << PTS / 90000.0f << " secs";
+            LOGV("PTS = %llu", PTS);
+            // LOGI("PTS = %.2f secs", PTS / 90000.0f);
 
             optional_bytes_remaining -= 5;
 
@@ -348,7 +349,7 @@
                 DTS |= br->getBits(15);
                 CHECK_EQ(br->getBits(1), 1u);
 
-                LOG(VERBOSE) << "DTS = " << DTS;
+                LOGV("DTS = %llu", DTS);
 
                 optional_bytes_remaining -= 5;
             }
@@ -366,8 +367,8 @@
             ESCR |= br->getBits(15);
             CHECK_EQ(br->getBits(1), 1u);
 
-            LOG(VERBOSE) << "ESCR = " << ESCR;
-            LOG(VERBOSE) << "ESCR_extension = " << br->getBits(9);
+            LOGV("ESCR = %llu", ESCR);
+            MY_LOGV("ESCR_extension = %u", br->getBits(9));
 
             CHECK_EQ(br->getBits(1), 1u);
 
@@ -378,7 +379,7 @@
             CHECK_GE(optional_bytes_remaining, 3u);
 
             CHECK_EQ(br->getBits(1), 1u);
-            LOG(VERBOSE) << "ES_rate = " << br->getBits(22);
+            MY_LOGV("ES_rate = %u", br->getBits(22));
             CHECK_EQ(br->getBits(1), 1u);
 
             optional_bytes_remaining -= 3;
@@ -405,8 +406,7 @@
             size_t payloadSizeBits = br->numBitsLeft();
             CHECK((payloadSizeBits % 8) == 0);
 
-            LOG(VERBOSE) << "There's " << (payloadSizeBits / 8)
-                         << " bytes of payload.";
+            LOGV("There's %d bytes of payload.", payloadSizeBits / 8);
         }
     } else if (stream_id == 0xbe) {  // padding_stream
         CHECK_NE(PES_packet_length, 0u);
@@ -422,9 +422,7 @@
         return;
     }
 
-    LOG(VERBOSE) << "flushing stream "
-                 << StringPrintf("0x%04x", mElementaryPID)
-                 << " size = " << mBuffer->size();
+    LOGV("flushing stream 0x%04x size = %d", mElementaryPID, mBuffer->size());
 
     ABitReader br(mBuffer->data(), mBuffer->size());
     parsePES(&br);
@@ -493,7 +491,7 @@
     CHECK(picParamSet != NULL);
 
     buffer->setRange(stopOffset, size - stopOffset);
-    LOG(INFO) << "buffer has " << buffer->size() << " bytes left.";
+    LOGI("buffer has %d bytes left.", buffer->size());
 
     size_t csdSize =
         1 + 3 + 1 + 1
@@ -617,15 +615,15 @@
     CHECK_EQ(br.getBits(2), 0u);
     br.getBits(1);  // protection_absent
     unsigned profile = br.getBits(2);
-    LOG(INFO) << "profile = " << profile;
+    LOGI("profile = %u", profile);
     CHECK_NE(profile, 3u);
     unsigned sampling_freq_index = br.getBits(4);
     br.getBits(1);  // private_bit
     unsigned channel_configuration = br.getBits(3);
     CHECK_NE(channel_configuration, 0u);
 
-    LOG(INFO) << "sampling_freq_index = " << sampling_freq_index;
-    LOG(INFO) << "channel_configuration = " << channel_configuration;
+    LOGI("sampling_freq_index = %u", sampling_freq_index);
+    LOGI("channel_configuration = %u", channel_configuration);
 
     CHECK_LE(sampling_freq_index, 11u);
     static const int32_t kSamplingFreq[] = {
@@ -671,8 +669,7 @@
 void ATSParser::Stream::onPayloadData(
         unsigned PTS_DTS_flags, uint64_t PTS, uint64_t DTS,
         const uint8_t *data, size_t size) {
-    LOG(VERBOSE) << "onPayloadData mStreamType="
-                 << StringPrintf("0x%02x", mStreamType);
+    LOGV("onPayloadData mStreamType=0x%02x", mStreamType);
 
     sp<ABuffer> buffer;
 
@@ -710,8 +707,8 @@
             sp<ABuffer> csd =
                 FindMPEG2ADTSConfig(buffer, &sampleRate, &channelCount);
 
-            LOG(INFO) << "sampleRate = " << sampleRate;
-            LOG(INFO) << "channelCount = " << channelCount;
+            LOGI("sampleRate = %d", sampleRate);
+            LOGI("channelCount = %d", channelCount);
 
             meta->setInt32(kKeySampleRate, sampleRate);
             meta->setInt32(kKeyChannelCount, channelCount);
@@ -719,7 +716,7 @@
             meta->setData(kKeyESDS, 0, csd->data(), csd->size());
         }
 
-        LOG(INFO) << "created source!";
+        LOGI("created source!");
         mSource = new AnotherPacketSource(meta);
 
         // fall through
@@ -777,12 +774,7 @@
 
             CHECK_LE(scan, buffer->size());
 
-            LOG(VERBOSE)
-                << "found aac raw data block at ["
-                << StringPrintf("0x%08x", offset)
-                << " ; "
-                << StringPrintf("0x%08x", scan)
-                << ")";
+            LOGV("found aac raw data block at [0x%08x ; 0x%08x)", offset, scan);
 
             memmove(&buffer->data()[dstOffset], &buffer->data()[offset],
                     scan - offset);
@@ -825,50 +817,48 @@
 
 void ATSParser::parseProgramAssociationTable(ABitReader *br) {
     unsigned table_id = br->getBits(8);
-    LOG(VERBOSE) << "  table_id = " << table_id;
+    LOGV("  table_id = %u", table_id);
     CHECK_EQ(table_id, 0x00u);
 
     unsigned section_syntax_indictor = br->getBits(1);
-    LOG(VERBOSE) << "  section_syntax_indictor = " << section_syntax_indictor;
+    LOGV("  section_syntax_indictor = %u", section_syntax_indictor);
     CHECK_EQ(section_syntax_indictor, 1u);
 
     CHECK_EQ(br->getBits(1), 0u);
-    LOG(VERBOSE) << "  reserved = " << br->getBits(2);
+    MY_LOGV("  reserved = %u", br->getBits(2));
 
     unsigned section_length = br->getBits(12);
-    LOG(VERBOSE) << "  section_length = " << section_length;
+    LOGV("  section_length = %u", section_length);
     CHECK((section_length & 0xc00) == 0);
 
-    LOG(VERBOSE) << "  transport_stream_id = " << br->getBits(16);
-    LOG(VERBOSE) << "  reserved = " << br->getBits(2);
-    LOG(VERBOSE) << "  version_number = " << br->getBits(5);
-    LOG(VERBOSE) << "  current_next_indicator = " << br->getBits(1);
-    LOG(VERBOSE) << "  section_number = " << br->getBits(8);
-    LOG(VERBOSE) << "  last_section_number = " << br->getBits(8);
+    MY_LOGV("  transport_stream_id = %u", br->getBits(16));
+    MY_LOGV("  reserved = %u", br->getBits(2));
+    MY_LOGV("  version_number = %u", br->getBits(5));
+    MY_LOGV("  current_next_indicator = %u", br->getBits(1));
+    MY_LOGV("  section_number = %u", br->getBits(8));
+    MY_LOGV("  last_section_number = %u", br->getBits(8));
 
     size_t numProgramBytes = (section_length - 5 /* header */ - 4 /* crc */);
     CHECK_EQ((numProgramBytes % 4), 0u);
 
     for (size_t i = 0; i < numProgramBytes / 4; ++i) {
         unsigned program_number = br->getBits(16);
-        LOG(VERBOSE) << "    program_number = " << program_number;
+        LOGV("    program_number = %u", program_number);
 
-        LOG(VERBOSE) << "    reserved = " << br->getBits(3);
+        MY_LOGV("    reserved = %u", br->getBits(3));
 
         if (program_number == 0) {
-            LOG(VERBOSE) << "    network_PID = "
-                      << StringPrintf("0x%04x", br->getBits(13));
+            MY_LOGV("    network_PID = 0x%04x", br->getBits(13));
         } else {
             unsigned programMapPID = br->getBits(13);
 
-            LOG(VERBOSE) << "    program_map_PID = "
-                      << StringPrintf("0x%04x", programMapPID);
+            LOGV("    program_map_PID = 0x%04x", programMapPID);
 
             mPrograms.push(new Program(programMapPID));
         }
     }
 
-    LOG(VERBOSE) << "  CRC = " << StringPrintf("0x%08x", br->getBits(32));
+    MY_LOGV("  CRC = 0x%08x", br->getBits(32));
 }
 
 void ATSParser::parsePID(
@@ -893,8 +883,7 @@
     }
 
     if (!handled) {
-        LOG(WARNING) << "PID " << StringPrintf("0x%04x", PID)
-                     << " not handled.";
+        LOGV("PID 0x%04x not handled.", PID);
     }
 }
 
@@ -906,28 +895,27 @@
 }
 
 void ATSParser::parseTS(ABitReader *br) {
-    LOG(VERBOSE) << "---";
+    LOGV("---");
 
     unsigned sync_byte = br->getBits(8);
     CHECK_EQ(sync_byte, 0x47u);
 
-    LOG(VERBOSE) << "transport_error_indicator = " << br->getBits(1);
+    MY_LOGV("transport_error_indicator = %u", br->getBits(1));
 
     unsigned payload_unit_start_indicator = br->getBits(1);
-    LOG(VERBOSE) << "payload_unit_start_indicator = "
-                 << payload_unit_start_indicator;
+    LOGV("payload_unit_start_indicator = %u", payload_unit_start_indicator);
 
-    LOG(VERBOSE) << "transport_priority = " << br->getBits(1);
+    MY_LOGV("transport_priority = %u", br->getBits(1));
 
     unsigned PID = br->getBits(13);
-    LOG(VERBOSE) << "PID = " << StringPrintf("0x%04x", PID);
+    LOGV("PID = 0x%04x", PID);
 
-    LOG(VERBOSE) << "transport_scrambling_control = " << br->getBits(2);
+    MY_LOGV("transport_scrambling_control = %u", br->getBits(2));
 
     unsigned adaptation_field_control = br->getBits(2);
-    LOG(VERBOSE) << "adaptation_field_control = " << adaptation_field_control;
+    LOGV("adaptation_field_control = %u", adaptation_field_control);
 
-    LOG(VERBOSE) << "continuity_counter = " << br->getBits(4);
+    MY_LOGV("continuity_counter = %u", br->getBits(4));
 
     if (adaptation_field_control == 2 || adaptation_field_control == 3) {
         parseAdaptationField(br);
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index fcf506d..4f28855 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -286,7 +286,7 @@
         return OK;
     }
 
-    sp<MemoryDealer> dealer = new MemoryDealer(8 * 1024 * 1024, "OMXHarness");
+    sp<MemoryDealer> dealer = new MemoryDealer(16 * 1024 * 1024, "OMXHarness");
     IOMX::node_id node;
 
     status_t err =
diff --git a/media/libstagefright/rtsp/AAMRAssembler.cpp b/media/libstagefright/rtsp/AAMRAssembler.cpp
index 154ba31..b1f6e9a 100644
--- a/media/libstagefright/rtsp/AAMRAssembler.cpp
+++ b/media/libstagefright/rtsp/AAMRAssembler.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AAMRAssembler"
+#include <utils/Log.h>
+
 #include "AAMRAssembler.h"
 
 #include "ARTPSource.h"
@@ -119,9 +123,7 @@
         mNextExpectedSeqNoValid = true;
         mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
     } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
-#if VERBOSE
-        LOG(VERBOSE) << "Not the sequence number I expected";
-#endif
+        LOGV("Not the sequence number I expected");
 
         return WRONG_SEQUENCE_NUMBER;
     }
@@ -132,7 +134,7 @@
         queue->erase(queue->begin());
         ++mNextExpectedSeqNo;
 
-        LOG(VERBOSE) << "AMR packet too short.";
+        LOGV("AMR packet too short.");
 
         return MALFORMED_PACKET;
     }
@@ -150,7 +152,7 @@
             queue->erase(queue->begin());
             ++mNextExpectedSeqNo;
 
-            LOG(VERBOSE) << "Unable to parse TOC.";
+            LOGV("Unable to parse TOC.");
 
             return MALFORMED_PACKET;
         }
@@ -164,7 +166,7 @@
             queue->erase(queue->begin());
             ++mNextExpectedSeqNo;
 
-            LOG(VERBOSE) << "Illegal TOC entry.";
+            LOGV("Illegal TOC entry.");
 
             return MALFORMED_PACKET;
         }
@@ -191,7 +193,7 @@
             queue->erase(queue->begin());
             ++mNextExpectedSeqNo;
 
-            LOG(VERBOSE) << "AMR packet too short.";
+            LOGV("AMR packet too short.");
 
             return MALFORMED_PACKET;
         }
diff --git a/media/libstagefright/rtsp/AAVCAssembler.cpp b/media/libstagefright/rtsp/AAVCAssembler.cpp
index 6b1e292..11c6ae7 100644
--- a/media/libstagefright/rtsp/AAVCAssembler.cpp
+++ b/media/libstagefright/rtsp/AAVCAssembler.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AAVCAssembler"
+#include <utils/Log.h>
+
 #include "AAVCAssembler.h"
 
 #include "ARTPSource.h"
@@ -25,8 +29,6 @@
 
 #include <stdint.h>
 
-#define BE_VERBOSE      0
-
 namespace android {
 
 // static
@@ -70,9 +72,7 @@
         mNextExpectedSeqNoValid = true;
         mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
     } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
-#if BE_VERBOSE
-        LOG(VERBOSE) << "Not the sequence number I expected";
-#endif
+        LOGV("Not the sequence number I expected");
 
         return WRONG_SEQUENCE_NUMBER;
     }
@@ -83,7 +83,7 @@
     if (size < 1 || (data[0] & 0x80)) {
         // Corrupt.
 
-        LOG(ERROR) << "Ignoring corrupt buffer.";
+        LOGV("Ignoring corrupt buffer.");
         queue->erase(queue->begin());
 
         ++mNextExpectedSeqNo;
@@ -107,7 +107,7 @@
 
         return success ? OK : MALFORMED_PACKET;
     } else {
-        LOG(ERROR) << "Ignoring unsupported buffer (nalType=" << nalType << ")";
+        LOGV("Ignoring unsupported buffer (nalType=%d)", nalType);
 
         queue->erase(queue->begin());
         ++mNextExpectedSeqNo;
@@ -117,8 +117,8 @@
 }
 
 void AAVCAssembler::addSingleNALUnit(const sp<ABuffer> &buffer) {
-#if BE_VERBOSE
-    LOG(VERBOSE) << "addSingleNALUnit of size " << buffer->size();
+    LOGV("addSingleNALUnit of size %d", buffer->size());
+#if !LOG_NDEBUG
     hexdump(buffer->data(), buffer->size());
 #endif
 
@@ -138,7 +138,7 @@
     size_t size = buffer->size();
 
     if (size < 3) {
-        LOG(ERROR) << "Discarding too small STAP-A packet.";
+        LOGV("Discarding too small STAP-A packet.");
         return false;
     }
 
@@ -148,7 +148,7 @@
         size_t nalSize = (data[0] << 8) | data[1];
 
         if (size < nalSize + 2) {
-            LOG(ERROR) << "Discarding malformed STAP-A packet.";
+            LOGV("Discarding malformed STAP-A packet.");
             return false;
         }
 
@@ -164,7 +164,7 @@
     }
 
     if (size != 0) {
-        LOG(WARNING) << "Unexpected padding at end of STAP-A packet.";
+        LOGV("Unexpected padding at end of STAP-A packet.");
     }
 
     return true;
@@ -184,7 +184,7 @@
     CHECK((indicator & 0x1f) == 28);
 
     if (size < 2) {
-        LOG(ERROR) << "Ignoring malformed FU buffer (size = " << size << ")";
+        LOGV("Ignoring malformed FU buffer (size = %d)", size);
 
         queue->erase(queue->begin());
         ++mNextExpectedSeqNo;
@@ -194,9 +194,7 @@
     if (!(data[1] & 0x80)) {
         // Start bit not set on the first buffer.
 
-#if BE_VERBOSE
-        LOG(ERROR) << "Start bit not set on first buffer";
-#endif
+        LOGV("Start bit not set on first buffer");
 
         queue->erase(queue->begin());
         ++mNextExpectedSeqNo;
@@ -214,17 +212,13 @@
     if (data[1] & 0x40) {
         // Huh? End bit also set on the first buffer.
 
-#if BE_VERBOSE
-        LOG(WARNING) << "Grrr. This isn't fragmented at all.";
-#endif
+        LOGV("Grrr. This isn't fragmented at all.");
 
         complete = true;
     } else {
         List<sp<ABuffer> >::iterator it = ++queue->begin();
         while (it != queue->end()) {
-#if BE_VERBOSE
-            LOG(VERBOSE) << "sequence length " << totalCount;
-#endif
+            LOGV("sequence length %d", totalCount);
 
             const sp<ABuffer> &buffer = *it;
 
@@ -232,11 +226,8 @@
             size_t size = buffer->size();
 
             if ((uint32_t)buffer->int32Data() != expectedSeqNo) {
-#if BE_VERBOSE
-                LOG(VERBOSE) << "sequence not complete, expected seqNo "
-                     << expectedSeqNo << ", got "
-                     << (uint32_t)buffer->int32Data();
-#endif
+                LOGV("sequence not complete, expected seqNo %d, got %d",
+                     expectedSeqNo, (uint32_t)buffer->int32Data());
 
                 return WRONG_SEQUENCE_NUMBER;
             }
@@ -245,7 +236,7 @@
                     || data[0] != indicator
                     || (data[1] & 0x1f) != nalType
                     || (data[1] & 0x80)) {
-                LOG(ERROR) << "Ignoring malformed FU buffer.\n";
+                LOGV("Ignoring malformed FU buffer.");
 
                 // Delete the whole start of the FU.
 
@@ -296,8 +287,8 @@
     for (size_t i = 0; i < totalCount; ++i) {
         const sp<ABuffer> &buffer = *it;
 
-#if BE_VERBOSE
-        LOG(VERBOSE) << "piece #" << (i + 1) << "/" << totalCount;
+        LOGV("piece #%d/%d", i + 1, totalCount);
+#if !LOG_NDEBUG
         hexdump(buffer->data(), buffer->size());
 #endif
 
@@ -311,9 +302,7 @@
 
     addSingleNALUnit(unit);
 
-#if BE_VERBOSE
-    LOG(VERBOSE) << "successfully assembled a NAL unit from fragments.";
-#endif
+    LOGV("successfully assembled a NAL unit from fragments.");
 
     return OK;
 }
@@ -321,9 +310,7 @@
 void AAVCAssembler::submitAccessUnit() {
     CHECK(!mNALUnits.empty());
 
-#if BE_VERBOSE
-    LOG(VERBOSE) << "Access unit complete (" << mNALUnits.size() << " nal units)";
-#endif
+    LOGV("Access unit complete (%d nal units)", mNALUnits.size());
 
     size_t totalSize = 0;
     for (List<sp<ABuffer> >::iterator it = mNALUnits.begin();
@@ -373,7 +360,7 @@
 
 void AAVCAssembler::packetLost() {
     CHECK(mNextExpectedSeqNoValid);
-    LOG(VERBOSE) << "packetLost (expected " << mNextExpectedSeqNo << ")";
+    LOGV("packetLost (expected %d)", mNextExpectedSeqNo);
 
     ++mNextExpectedSeqNo;
 
diff --git a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
index f68a35b..13988cd 100644
--- a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
+++ b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AMPEG4ElementaryAssembler"
+#include <utils/Log.h>
+
 #include "AMPEG4ElementaryAssembler.h"
 
 #include "ARTPSource.h"
@@ -28,8 +32,6 @@
 #include <ctype.h>
 #include <stdint.h>
 
-#define BE_VERBOSE      0
-
 namespace android {
 
 static bool GetAttribute(const char *s, const char *key, AString *value) {
@@ -201,9 +203,7 @@
         mNextExpectedSeqNoValid = true;
         mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
     } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
-#if BE_VERBOSE
-        LOG(VERBOSE) << "Not the sequence number I expected";
-#endif
+        LOGV("Not the sequence number I expected");
 
         return WRONG_SEQUENCE_NUMBER;
     }
@@ -336,9 +336,7 @@
 void AMPEG4ElementaryAssembler::submitAccessUnit() {
     CHECK(!mPackets.empty());
 
-#if BE_VERBOSE
-    LOG(VERBOSE) << "Access unit complete (" << mPackets.size() << " nal units)";
-#endif
+    LOGV("Access unit complete (%d nal units)", mPackets.size());
 
     size_t totalSize = 0;
     for (List<sp<ABuffer> >::iterator it = mPackets.begin();
@@ -385,7 +383,7 @@
 
 void AMPEG4ElementaryAssembler::packetLost() {
     CHECK(mNextExpectedSeqNoValid);
-    LOG(VERBOSE) << "packetLost (expected " << mNextExpectedSeqNo << ")";
+    LOGV("packetLost (expected %d)", mNextExpectedSeqNo);
 
     ++mNextExpectedSeqNo;
 
diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp
index b3e86eb..78754e6 100644
--- a/media/libstagefright/rtsp/APacketSource.cpp
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "APacketSource"
+#include <utils/Log.h>
+
 #include "APacketSource.h"
 
 #include "ASessionDescription.h"
@@ -188,7 +192,7 @@
 
         if (i == 0) {
             FindAVCDimensions(nal, width, height);
-            LOG(INFO) << "dimensions " << *width << "x" << *height;
+            LOGI("dimensions %dx%d", *width, *height);
         }
     }
 
@@ -412,7 +416,7 @@
     *width = video_object_layer_width;
     *height = video_object_layer_height;
 
-    LOG(INFO) << "VOL dimensions = " << *width << "x" << *height;
+    LOGI("VOL dimensions = %dx%d", *width, *height);
 
     return true;
 }
@@ -711,7 +715,7 @@
 void APacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
     int32_t damaged;
     if (buffer->meta()->findInt32("damaged", &damaged) && damaged) {
-        LOG(VERBOSE) << "discarding damaged AU";
+        LOGV("discarding damaged AU");
         return;
     }
 
@@ -765,8 +769,9 @@
     CHECK(last->meta()->findInt64("timeUs", &lastTimeUs));
 
     if (lastTimeUs < firstTimeUs) {
-        LOG(ERROR) << "Huh? Time moving backwards? "
-                   << firstTimeUs << " > " << lastTimeUs;
+        LOGE("Huh? Time moving backwards? %lld > %lld",
+             firstTimeUs, lastTimeUs);
+
         return 0;
     }
 
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index 10c9e02..ded3b24 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ARTPConnection"
+#include <utils/Log.h>
+
 #include "ARTPConnection.h"
 
 #include "ARTPSource.h"
@@ -319,7 +323,7 @@
             }
 
             if (buffer->size() > 0) {
-                LOG(VERBOSE) << "Sending RR...";
+                LOGV("Sending RR...");
 
                 ssize_t n = sendto(
                         s->mRTCPSocket, buffer->data(), buffer->size(), 0,
@@ -356,7 +360,7 @@
 
     buffer->setRange(0, nbytes);
 
-    // LOG(INFO) << "received " << buffer->size() << " bytes.";
+    // LOGI("received %d bytes.", buffer->size());
 
     status_t err;
     if (receiveRTP) {
@@ -521,9 +525,8 @@
 
             default:
             {
-                LOG(WARNING) << "Unknown RTCP packet type "
-                             << (unsigned)data[1]
-                             << " of size " << headerLength;
+                LOGW("Unknown RTCP packet type %u of size %d",
+                     (unsigned)data[1], headerLength);
                 break;
             }
         }
@@ -567,10 +570,10 @@
     uint32_t rtpTime = u32at(&data[16]);
 
 #if 0
-    LOG(INFO) << StringPrintf(
-            "XXX timeUpdate: ssrc=0x%08x, rtpTime %u == ntpTime %.3f",
-            id,
-            rtpTime, (ntpTime >> 32) + (double)(ntpTime & 0xffffffff) / (1ll << 32));
+    LOGI("XXX timeUpdate: ssrc=0x%08x, rtpTime %u == ntpTime %.3f",
+         id,
+         rtpTime,
+         (ntpTime >> 32) + (double)(ntpTime & 0xffffffff) / (1ll << 32));
 #endif
 
     sp<ARTPSource> source = findSource(s, id);
diff --git a/media/libstagefright/rtsp/ARTPSession.cpp b/media/libstagefright/rtsp/ARTPSession.cpp
index 8ce93b7..39c6619 100644
--- a/media/libstagefright/rtsp/ARTPSession.cpp
+++ b/media/libstagefright/rtsp/ARTPSession.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ARTPSession"
+#include <utils/Log.h>
+
 #include "ARTPSession.h"
 
 #include <media/stagefright/foundation/ABuffer.h>
@@ -51,24 +55,24 @@
         if (!mDesc->findAttribute(i, "c=", &connection)) {
             // No per-stream connection information, try global fallback.
             if (!mDesc->findAttribute(0, "c=", &connection)) {
-                LOG(ERROR) << "Unable to find connection attribtue.";
+                LOGE("Unable to find connection attribute.");
                 return mInitCheck;
             }
         }
         if (!(connection == "IN IP4 127.0.0.1")) {
-            LOG(ERROR) << "We only support localhost connections for now.";
+            LOGE("We only support localhost connections for now.");
             return mInitCheck;
         }
 
         unsigned port;
         if (!validateMediaFormat(i, &port) || (port & 1) != 0) {
-            LOG(ERROR) << "Invalid media format.";
+            LOGE("Invalid media format.");
             return mInitCheck;
         }
 
         sp<APacketSource> source = new APacketSource(mDesc, i);
         if (source->initCheck() != OK) {
-            LOG(ERROR) << "Unsupported format.";
+            LOGE("Unsupported format.");
             return mInitCheck;
         }
 
@@ -157,9 +161,8 @@
             printf("access unit complete size=%d\tntp-time=0x%016llx\n",
                    accessUnit->size(), ntpTime);
 #else
-            LOG(INFO) << "access unit complete, "
-                      << "size=" << accessUnit->size() << ", "
-                      << "ntp-time=" << ntpTime;
+            LOGI("access unit complete, size=%d, ntp-time=%llu",
+                 accessUnit->size(), ntpTime);
             hexdump(accessUnit->data(), accessUnit->size());
 #endif
 #endif
@@ -169,9 +172,8 @@
             CHECK(!memcmp("\x00\x00\x00\x01", accessUnit->data(), 4));
             unsigned x = accessUnit->data()[4];
 
-            LOG(INFO) << "access unit complete: "
-                      << StringPrintf("nalType=0x%02x, nalRefIdc=0x%02x",
-                                      x & 0x1f, (x & 0x60) >> 5);
+            LOGI("access unit complete: nalType=0x%02x, nalRefIdc=0x%02x",
+                 x & 0x1f, (x & 0x60) >> 5);
 #endif
 
             accessUnit->meta()->setInt64("ntp-time", ntpTime);
@@ -181,7 +183,7 @@
             int32_t damaged;
             if (accessUnit->meta()->findInt32("damaged", &damaged)
                     && damaged != 0) {
-                LOG(INFO) << "ignoring damaged AU";
+                LOGI("ignoring damaged AU");
             } else
 #endif
             {
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index 9656ba2..2518264 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ARTPSource"
+#include <utils/Log.h>
+
 #include "ARTPSource.h"
 
 #include "AAMRAssembler.h"
@@ -27,8 +31,6 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 
-#define BE_VERBOSE      0
-
 namespace android {
 
 static const uint32_t kSourceID = 0xdeadbeef;
@@ -83,14 +85,10 @@
             && mAssembler != NULL) {
         mAssembler->onPacketReceived(this);
     }
-
-    dump();
 }
 
 void ARTPSource::timeUpdate(uint32_t rtpTime, uint64_t ntpTime) {
-#if BE_VERBOSE
-    LOG(VERBOSE) << "timeUpdate";
-#endif
+    LOGV("timeUpdate");
 
     mLastNTPTime = ntpTime;
     mLastNTPTimeUpdateUs = ALooper::GetNowUs();
@@ -173,7 +171,7 @@
     }
 
     if (it != mQueue.end() && (uint32_t)(*it)->int32Data() == seqNum) {
-        LOG(WARNING) << "Discarding duplicate buffer";
+        LOGW("Discarding duplicate buffer");
         return false;
     }
 
@@ -182,89 +180,6 @@
     return true;
 }
 
-void ARTPSource::dump() const {
-    if ((mNumBuffersReceived % 128) != 0) {
-        return;
-    }
-
-#if 0
-    if (mAssembler == NULL) {
-        char tmp[20];
-        sprintf(tmp, "0x%08x", mID);
-
-        int32_t numMissing = 0;
-
-        if (!mQueue.empty()) {
-            List<sp<ABuffer> >::const_iterator it = mQueue.begin();
-            uint32_t expectedSeqNum = (uint32_t)(*it)->int32Data();
-            ++expectedSeqNum;
-            ++it;
-
-            for (; it != mQueue.end(); ++it) {
-                uint32_t seqNum = (uint32_t)(*it)->int32Data();
-                CHECK_GE(seqNum, expectedSeqNum);
-
-                if (seqNum != expectedSeqNum) {
-                    numMissing += seqNum - expectedSeqNum;
-                    expectedSeqNum = seqNum;
-                }
-
-                ++expectedSeqNum;
-            }
-        }
-
-        LOG(VERBOSE) << "[" << tmp << "] Missing " << numMissing
-             << " / " << (mNumBuffersReceived + numMissing) << " packets. ("
-             << (100.0 * numMissing / (mNumBuffersReceived + numMissing))
-             << " %%)";
-    }
-#endif
-
-#if 0
-    AString out;
-
-    out.append(tmp);
-    out.append(" [");
-
-    List<sp<ABuffer> >::const_iterator it = mQueue.begin();
-    while (it != mQueue.end()) {
-        uint32_t start = (uint32_t)(*it)->int32Data();
-
-        out.append(start);
-
-        ++it;
-        uint32_t expected = start + 1;
-
-        while (it != mQueue.end()) {
-            uint32_t seqNum = (uint32_t)(*it)->int32Data();
-
-            if (seqNum != expected) {
-                if (expected > start + 1) {
-                    out.append("-");
-                    out.append(expected - 1);
-                }
-                out.append(", ");
-                break;
-            }
-
-            ++it;
-            ++expected;
-        }
-
-        if (it == mQueue.end()) {
-            if (expected > start + 1) {
-                out.append("-");
-                out.append(expected - 1);
-            }
-        }
-    }
-
-    out.append("]");
-
-    LOG(VERBOSE) << out;
-#endif
-}
-
 uint64_t ARTPSource::RTP2NTP(uint32_t rtpTime) const {
     CHECK_EQ(mNumTimes, 2u);
 
@@ -291,7 +206,7 @@
     mLastFIRRequestUs = nowUs;
 
     if (buffer->size() + 20 > buffer->capacity()) {
-        LOG(WARNING) << "RTCP buffer too small to accomodate FIR.";
+        LOGW("RTCP buffer too small to accomodate FIR.");
         return;
     }
 
@@ -324,12 +239,12 @@
 
     buffer->setRange(buffer->offset(), buffer->size() + 20);
 
-    LOG(VERBOSE) << "Added FIR request.";
+    LOGV("Added FIR request.");
 }
 
 void ARTPSource::addReceiverReport(const sp<ABuffer> &buffer) {
     if (buffer->size() + 32 > buffer->capacity()) {
-        LOG(WARNING) << "RTCP buffer too small to accomodate RR.";
+        LOGW("RTCP buffer too small to accomodate RR.");
         return;
     }
 
diff --git a/media/libstagefright/rtsp/ARTPSource.h b/media/libstagefright/rtsp/ARTPSource.h
index 252d6d6..e62c3f1 100644
--- a/media/libstagefright/rtsp/ARTPSource.h
+++ b/media/libstagefright/rtsp/ARTPSource.h
@@ -72,7 +72,6 @@
     uint64_t RTP2NTP(uint32_t rtpTime) const;
 
     bool queuePacket(const sp<ABuffer> &buffer);
-    void dump() const;
 
     DISALLOW_EVIL_CONSTRUCTORS(ARTPSource);
 };
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index ce1ee0e..155fd96 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -1,3 +1,23 @@
+/*
+ * 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 "ARTPWriter"
+#include <utils/Log.h>
+
 #include "ARTPWriter.h"
 
 #include <fcntl.h>
@@ -249,7 +269,7 @@
     status_t err = mSource->read(&mediaBuf);
 
     if (err != OK) {
-        LOG(INFO) << "reached EOS.";
+        LOGI("reached EOS.");
 
         Mutex::Autolock autoLock(mLock);
         mFlags |= kFlagEOS;
@@ -257,7 +277,7 @@
     }
 
     if (mediaBuf->range_length() > 0) {
-        LOG(VERBOSE) << "read buffer of size " << mediaBuf->range_length();
+        LOGV("read buffer of size %d", mediaBuf->range_length());
 
         if (mMode == H264) {
             StripStartcode(mediaBuf);
@@ -500,7 +520,7 @@
         sdp.append("a=fmtp:" PT_STR " octed-align\r\n");
     }
 
-    LOG(INFO) << sdp;
+    LOGI("%s", sdp.c_str());
 }
 
 void ARTPWriter::makeH264SPropParamSets(MediaBuffer *buffer) {
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index dcff64c..f928c06 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ARTSPConnection"
+#include <utils/Log.h>
+
 #include "ARTSPConnection.h"
 
 #include <media/stagefright/foundation/ABuffer.h>
@@ -41,7 +45,7 @@
 
 ARTSPConnection::~ARTSPConnection() {
     if (mSocket >= 0) {
-        LOG(ERROR) << "Connection is still open, closing the socket.";
+        LOGE("Connection is still open, closing the socket.");
         close(mSocket);
         mSocket = -1;
     }
@@ -184,7 +188,7 @@
     AString host, path;
     unsigned port;
     if (!ParseURL(url.c_str(), &host, &port, &path)) {
-        LOG(ERROR) << "Malformed rtsp url " << url;
+        LOGE("Malformed rtsp url %s", url.c_str());
 
         reply->setInt32("result", ERROR_MALFORMED);
         reply->post();
@@ -195,7 +199,7 @@
 
     struct hostent *ent = gethostbyname(host.c_str());
     if (ent == NULL) {
-        LOG(ERROR) << "Unknown host " << host;
+        LOGE("Unknown host %s", host.c_str());
 
         reply->setInt32("result", -ENOENT);
         reply->post();
@@ -300,7 +304,7 @@
     CHECK_EQ(optionLen, (socklen_t)sizeof(err));
 
     if (err != 0) {
-        LOG(ERROR) << "err = " << err << " (" << strerror(err) << ")";
+        LOGE("err = %d (%s)", err, strerror(err));
 
         reply->setInt32("result", -err);
 
@@ -343,7 +347,7 @@
 
     request.insert(cseqHeader, i + 2);
 
-    LOG(VERBOSE) << request;
+    LOGV("%s", request.c_str());
 
     size_t numBytesSent = 0;
     while (numBytesSent < request.size()) {
@@ -353,7 +357,7 @@
 
         if (n == 0) {
             // Server closed the connection.
-            LOG(ERROR) << "Server unexpectedly closed the connection.";
+            LOGE("Server unexpectedly closed the connection.");
 
             reply->setInt32("result", ERROR_IO);
             reply->post();
@@ -363,7 +367,7 @@
                 continue;
             }
 
-            LOG(ERROR) << "Error sending rtsp request.";
+            LOGE("Error sending rtsp request.");
             reply->setInt32("result", -errno);
             reply->post();
             return;
@@ -438,14 +442,14 @@
         ssize_t n = recv(mSocket, (uint8_t *)data + offset, size - offset, 0);
         if (n == 0) {
             // Server closed the connection.
-            LOG(ERROR) << "Server unexpectedly closed the connection.";
+            LOGE("Server unexpectedly closed the connection.");
             return ERROR_IO;
         } else if (n < 0) {
             if (errno == EINTR) {
                 continue;
             }
 
-            LOG(ERROR) << "Error reading rtsp response.";
+            LOGE("Error reading rtsp response.");
             return -errno;
         }
 
@@ -516,7 +520,7 @@
             notify->setObject("buffer", buffer);
             notify->post();
         } else {
-            LOG(WARNING) << "received binary data, but no one cares.";
+            LOGW("received binary data, but no one cares.");
         }
 
         return true;
@@ -525,7 +529,7 @@
     sp<ARTSPResponse> response = new ARTSPResponse;
     response->mStatusLine = statusLine;
 
-    LOG(INFO) << "status: " << response->mStatusLine;
+    LOGI("status: %s", response->mStatusLine.c_str());
 
     ssize_t space1 = response->mStatusLine.find(" ");
     if (space1 < 0) {
@@ -555,7 +559,7 @@
             break;
         }
 
-        LOG(VERBOSE) << "line: " << line;
+        LOGV("line: %s", line.c_str());
 
         ssize_t colonPos = line.find(":");
         if (colonPos < 0) {
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
index 4a8cce85..612caff 100644
--- a/media/libstagefright/rtsp/ASessionDescription.cpp
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ASessionDescription"
+#include <utils/Log.h>
+
 #include "ASessionDescription.h"
 
 #include <media/stagefright/foundation/ADebug.h>
@@ -49,7 +53,7 @@
     mFormats.push(AString("[root]"));
 
     AString desc((const char *)data, size);
-    LOG(INFO) << desc;
+    LOGI("%s", desc.c_str());
 
     size_t i = 0;
     for (;;) {
@@ -102,7 +106,7 @@
                 key.trim();
                 value.trim();
 
-                LOG(VERBOSE) << "adding '" << key << "' => '" << value << "'";
+                LOGV("adding '%s' => '%s'", key.c_str(), value.c_str());
 
                 mTracks.editItemAt(mTracks.size() - 1).add(key, value);
                 break;
@@ -110,7 +114,8 @@
 
             case 'm':
             {
-                LOG(VERBOSE) << "new section '" << AString(line, 2, line.size() - 2) << "'";
+                LOGV("new section '%s'",
+                     AString(line, 2, line.size() - 2).c_str());
 
                 mTracks.push(Attribs());
                 mFormats.push(AString(line, 2, line.size() - 2));
@@ -129,7 +134,7 @@
                 key.trim();
                 value.trim();
 
-                LOG(VERBOSE) << "adding '" << key << "' => '" << value << "'";
+                LOGV("adding '%s' => '%s'", key.c_str(), value.c_str());
 
                 mTracks.editItemAt(mTracks.size() - 1).add(key, value);
                 break;
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index a3864f1..09dc156 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -18,6 +18,10 @@
 
 #define MY_HANDLER_H_
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MyHandler"
+#include <utils/Log.h>
+
 #include "APacketSource.h"
 #include "ARTPConnection.h"
 #include "ARTSPConnection.h"
@@ -137,8 +141,8 @@
                 int32_t result;
                 CHECK(msg->findInt32("result", &result));
 
-                LOG(INFO) << "connection request completed with result "
-                     << result << " (" << strerror(-result) << ")";
+                LOGI("connection request completed with result %d (%s)",
+                     result, strerror(-result));
 
                 if (result == OK) {
                     AString request;
@@ -173,8 +177,8 @@
                 int32_t result;
                 CHECK(msg->findInt32("result", &result));
 
-                LOG(INFO) << "DESCRIBE completed with result "
-                     << result << " (" << strerror(-result) << ")";
+                LOGI("DESCRIBE completed with result %d (%s)",
+                     result, strerror(-result));
 
                 if (result == OK) {
                     sp<RefBase> obj;
@@ -251,8 +255,8 @@
                 int32_t result;
                 CHECK(msg->findInt32("result", &result));
 
-                LOG(INFO) << "SETUP(" << index << ") completed with result "
-                     << result << " (" << strerror(-result) << ")";
+                LOGI("SETUP(%d) completed with result %d (%s)",
+                     index, result, strerror(-result));
 
                 if (result == OK) {
                     CHECK(track != NULL);
@@ -326,8 +330,8 @@
                 int32_t result;
                 CHECK(msg->findInt32("result", &result));
 
-                LOG(INFO) << "PLAY completed with result "
-                     << result << " (" << strerror(-result) << ")";
+                LOGI("PLAY completed with result %d (%s)",
+                     result, strerror(-result));
 
                 if (result == OK) {
                     sp<RefBase> obj;
@@ -404,8 +408,8 @@
                 int32_t result;
                 CHECK(msg->findInt32("result", &result));
 
-                LOG(INFO) << "TEARDOWN completed with result "
-                     << result << " (" << strerror(-result) << ")";
+                LOGI("TEARDOWN completed with result %d (%s)",
+                     result, strerror(-result));
 
                 sp<AMessage> reply = new AMessage('disc', id());
 
@@ -431,7 +435,7 @@
             case 'chek':
             {
                 if (mNumAccessUnitsReceived == 0) {
-                    LOG(INFO) << "stream ended? aborting.";
+                    LOGI("stream ended? aborting.");
                     (new AMessage('abor', id()))->post();
                     break;
                 }
@@ -461,7 +465,7 @@
                 CHECK(msg->findSize("track-index", &trackIndex));
 
                 if (trackIndex >= mTracks.size()) {
-                    LOG(ERROR) << "late packets ignored.";
+                    LOGV("late packets ignored.");
                     break;
                 }
 
@@ -469,7 +473,7 @@
 
                 int32_t eos;
                 if (msg->findInt32("eos", &eos)) {
-                    LOG(INFO) << "received BYE on track index " << trackIndex;
+                    LOGI("received BYE on track index %d", trackIndex);
 #if 0
                     track->mPacketSource->signalEOS(ERROR_END_OF_STREAM);
 #endif
@@ -484,14 +488,13 @@
                 uint32_t seqNum = (uint32_t)accessUnit->int32Data();
 
                 if (mSeekPending) {
-                    LOG(INFO) << "we're seeking, dropping stale packet.";
+                    LOGV("we're seeking, dropping stale packet.");
                     break;
                 }
 
                 if (seqNum < track->mFirstSeqNumInSegment) {
-                    LOG(INFO) << "dropping stale access-unit "
-                              << "(" << seqNum << " < "
-                              << track->mFirstSeqNumInSegment << ")";
+                    LOGV("dropping stale access-unit (%d < %d)",
+                         seqNum, track->mFirstSeqNumInSegment);
                     break;
                 }
 
@@ -506,10 +509,8 @@
                 if (track->mNewSegment) {
                     track->mNewSegment = false;
 
-                    LOG(VERBOSE) << "first segment unit ntpTime="
-                              << StringPrintf("0x%016llx", ntpTime)
-                              << " rtpTime=" << rtpTime
-                              << " seq=" << seqNum;
+                    LOGV("first segment unit ntpTime=0x%016llx rtpTime=%u seq=%d",
+                         ntpTime, rtpTime, seqNum);
                 }
 
                 if (mFirstAccessUnit) {
@@ -535,7 +536,7 @@
                 int32_t damaged;
                 if (accessUnit->meta()->findInt32("damaged", &damaged)
                         && damaged != 0) {
-                    LOG(INFO) << "ignoring damaged AU";
+                    LOGI("ignoring damaged AU");
                 } else
 #endif
                 {
@@ -608,8 +609,8 @@
                 int32_t result;
                 CHECK(msg->findInt32("result", &result));
 
-                LOG(INFO) << "PLAY completed with result "
-                     << result << " (" << strerror(-result) << ")";
+                LOGI("PLAY completed with result %d (%s)",
+                     result, strerror(-result));
 
                 if (result == OK) {
                     sp<RefBase> obj;
@@ -622,12 +623,12 @@
                     } else {
                         parsePlayResponse(response);
 
-                        LOG(INFO) << "seek completed.";
+                        LOGI("seek completed.");
                     }
                 }
 
                 if (result != OK) {
-                    LOG(ERROR) << "seek failed, aborting.";
+                    LOGE("seek failed, aborting.");
                     (new AMessage('abor', id()))->post();
                 }
 
@@ -652,11 +653,10 @@
             {
                 if (!mReceivedFirstRTCPPacket) {
                     if (mTryTCPInterleaving) {
-                        LOG(WARNING) << "Never received any data, disconnecting.";
+                        LOGW("Never received any data, disconnecting.");
                         (new AMessage('abor', id()))->post();
                     } else {
-                        LOG(WARNING)
-                            << "Never received any data, switching transports.";
+                        LOGW("Never received any data, switching transports.");
 
                         mTryTCPInterleaving = true;
 
@@ -700,7 +700,7 @@
         }
 
         AString range = response->mHeaders.valueAt(i);
-        LOG(VERBOSE) << "Range: " << range;
+        LOGV("Range: %s", range.c_str());
 
         AString val;
         CHECK(GetAttribute(range.c_str(), "npt", &val));
@@ -724,7 +724,7 @@
         for (List<AString>::iterator it = streamInfos.begin();
              it != streamInfos.end(); ++it) {
             (*it).trim();
-            LOG(VERBOSE) << "streamInfo[" << n << "] = " << *it;
+            LOGV("streamInfo[%d] = %s", n, (*it).c_str());
 
             CHECK(GetAttribute((*it).c_str(), "url", &val));
 
@@ -748,8 +748,7 @@
 
             uint32_t rtpTime = strtoul(val.c_str(), &end, 10);
 
-            LOG(VERBOSE) << "track #" << n
-                      << ": rtpTime=" << rtpTime << " <=> npt=" << npt1;
+            LOGV("track #%d: rtpTime=%u <=> ntp=%.2f", n, rtpTime, npt1);
 
             info->mPacketSource->setNormalPlayTimeMapping(
                     rtpTime, (int64_t)(npt1 * 1E6));
@@ -806,8 +805,7 @@
             new APacketSource(mSessionDesc, index);
 
         if (source->initCheck() != OK) {
-            LOG(WARNING) << "Unsupported format. Ignoring track #"
-                         << index << ".";
+            LOGW("Unsupported format. Ignoring track #%d.", index);
 
             sp<AMessage> reply = new AMessage('setu', id());
             reply->setSize("index", index);
@@ -830,7 +828,7 @@
         info->mFirstSeqNumInSegment = 0;
         info->mNewSegment = true;
 
-        LOG(VERBOSE) << "track #" << mTracks.size() << " URL=" << trackURL;
+        LOGV("track #%d URL=%s", mTracks.size(), trackURL.c_str());
 
         AString request = "SETUP ";
         request.append(trackURL);
diff --git a/media/libstagefright/rtsp/UDPPusher.cpp b/media/libstagefright/rtsp/UDPPusher.cpp
index 28a343f..576b3ca 100644
--- a/media/libstagefright/rtsp/UDPPusher.cpp
+++ b/media/libstagefright/rtsp/UDPPusher.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "UDPPusher"
+#include <utils/Log.h>
+
 #include "UDPPusher.h"
 
 #include <media/stagefright/foundation/ABuffer.h>
@@ -67,7 +71,7 @@
 bool UDPPusher::onPush() {
     uint32_t length;
     if (fread(&length, 1, sizeof(length), mFile) < sizeof(length)) {
-        LOG(INFO) << "No more data to push.";
+        LOGI("No more data to push.");
         return false;
     }
 
@@ -77,7 +81,7 @@
 
     sp<ABuffer> buffer = new ABuffer(length);
     if (fread(buffer->data(), 1, length, mFile) < length) {
-        LOG(ERROR) << "File truncated?.";
+        LOGE("File truncated?.");
         return false;
     }
 
@@ -89,7 +93,7 @@
 
     uint32_t timeMs;
     if (fread(&timeMs, 1, sizeof(timeMs), mFile) < sizeof(timeMs)) {
-        LOG(INFO) << "No more data to push.";
+        LOGI("No more data to push.");
         return false;
     }
 
@@ -109,7 +113,7 @@
         case kWhatPush:
         {
             if (!onPush() && !(ntohs(mRemoteAddr.sin_port) & 1)) {
-                LOG(INFO) << "emulating BYE packet";
+                LOGI("emulating BYE packet");
 
                 sp<ABuffer> buffer = new ABuffer(8);
                 uint8_t *data = buffer->data();
diff --git a/media/libstagefright/rtsp/rtp_test.cpp b/media/libstagefright/rtsp/rtp_test.cpp
index cec6c0c..f0cb5a5 100644
--- a/media/libstagefright/rtsp/rtp_test.cpp
+++ b/media/libstagefright/rtsp/rtp_test.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "rtp_test"
+#include <utils/Log.h>
+
 #include <binder/ProcessState.h>
 
 #include <media/stagefright/foundation/ADebug.h>
@@ -200,8 +204,7 @@
                 continue;
             }
 
-            LOG(ERROR) << "decoder returned error "
-                       << StringPrintf("0x%08x", err);
+            LOGE("decoder returned error 0x%08x", err);
             break;
         }
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java
index db0db70..d5538f1 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java
@@ -414,13 +414,13 @@
         EnergyProbe probe = null;
         AudioEffect vc = null;
         MediaPlayer mp = null;
+        AudioEffect rvb = null;
         AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
         int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
         am.setStreamVolume(AudioManager.STREAM_MUSIC,
                            am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
                            0);
         try {
-            probe = new EnergyProbe(0);
             // creating a volume controller on output mix ensures that ro.audio.silent mutes
             // audio after the effects and not before
             vc = new AudioEffect(
@@ -433,11 +433,24 @@
             mp = new MediaPlayer();
             mp.setDataSource(MediaNames.SINE_200_1000);
             mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
-            getReverb(mp.getAudioSessionId());
-            mReverb.setRoomLevel((short)0);
-            mReverb.setReverbLevel((short)0);
-            mReverb.setDecayTime(2000);
-            mReverb.setEnabled(true);
+
+            // create reverb with UUID instead of EnvironmentalReverb constructor otherwise an
+            // auxiliary reverb will be chosen by the effect framework as we are on session 0
+            rvb = new AudioEffect(
+                        AudioEffect.EFFECT_TYPE_NULL,
+                        UUID.fromString("c7a511a0-a3bb-11df-860e-0002a5d5c51b"),
+                        0,
+                        0);
+
+            rvb.setParameter(EnvironmentalReverb.PARAM_ROOM_LEVEL, (short)0);
+            rvb.setParameter(EnvironmentalReverb.PARAM_REVERB_LEVEL, (short)0);
+            rvb.setParameter(EnvironmentalReverb.PARAM_DECAY_TIME, 2000);
+            rvb.setEnabled(true);
+
+            // create probe after reverb so that it is chained behind the reverb in the
+            // effect chain
+            probe = new EnergyProbe(0);
+
             mp.prepare();
             mp.start();
             Thread.sleep(1000);
@@ -460,13 +473,15 @@
             loge(msg, "sleep() interrupted");
         }
         finally {
-            releaseReverb();
             if (mp != null) {
                 mp.release();
             }
             if (vc != null) {
                 vc.release();
             }
+            if (rvb != null) {
+                rvb.release();
+            }
             if (probe != null) {
                 probe.release();
             }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java
index c14319a..fbd8a78 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java
@@ -257,13 +257,13 @@
         EnergyProbe probe = null;
         AudioEffect vc = null;
         MediaPlayer mp = null;
+        AudioEffect rvb = null;
         AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
         int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
         am.setStreamVolume(AudioManager.STREAM_MUSIC,
                            am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
                            0);
         try {
-            probe = new EnergyProbe(0);
             // creating a volume controller on output mix ensures that ro.audio.silent mutes
             // audio after the effects and not before
             vc = new AudioEffect(
@@ -279,6 +279,22 @@
             getReverb(mp.getAudioSessionId());
             mReverb.setPreset((short)PresetReverb.PRESET_PLATE);
             mReverb.setEnabled(true);
+
+            // create reverb with UUID instead of PresetReverb constructor otherwise an auxiliary
+            // reverb will be chosen by the effect framework as we are on session 0
+            rvb = new AudioEffect(
+                        AudioEffect.EFFECT_TYPE_NULL,
+                        UUID.fromString("172cdf00-a3bc-11df-a72f-0002a5d5c51b"),
+                        0,
+                        0);
+
+            rvb.setParameter(PresetReverb.PARAM_PRESET, PresetReverb.PRESET_PLATE);
+            rvb.setEnabled(true);
+
+            // create probe after reverb so that it is chained behind the reverb in the
+            // effect chain
+            probe = new EnergyProbe(0);
+
             mp.prepare();
             mp.start();
             Thread.sleep(1000);
@@ -308,6 +324,9 @@
             if (vc != null) {
                 vc.release();
             }
+            if (rvb != null) {
+                rvb.release();
+            }
             if (probe != null) {
                 probe.release();
             }
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 43bb26a..3980189 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -3,16 +3,16 @@
 /**
  * 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 
+ * 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 
+ *     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 
+ * 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.
  */
 -->
@@ -24,6 +24,7 @@
     <string name="def_airplane_mode_radios" translatable="false">cell,bluetooth,wifi</string>
     <string name="airplane_mode_toggleable_radios" translatable="false">bluetooth,wifi</string>
     <bool name="def_auto_time">true</bool>
+    <bool name="def_auto_time_zone">true</bool>
     <bool name="def_accelerometer_rotation">true</bool>
     <!-- Default screen brightness, from 0 to 255.  102 is 40%. -->
     <integer name="def_screen_brightness">102</integer>
@@ -31,12 +32,12 @@
     <fraction name="def_window_animation_scale">100%</fraction>
     <fraction name="def_window_transition_scale">100%</fraction>
     <bool name="def_haptic_feedback">true</bool>
-    
+
     <bool name="def_bluetooth_on">false</bool>
     <bool name="def_install_non_market_apps">false</bool>
-    <!-- Comma-separated list of location providers. 
+    <!-- Comma-separated list of location providers.
          Network location is off by default because it requires
-         user opt-in via Setup Wizard or Settings.  
+         user opt-in via Setup Wizard or Settings.
     -->
     <string name="def_location_providers_allowed" translatable="false">gps</string>
     <bool name="assisted_gps_enabled">true</bool>
@@ -45,11 +46,11 @@
     <bool name="def_usb_mass_storage_enabled">true</bool>
     <bool name="def_wifi_on">false</bool>
     <bool name="def_networks_available_notification_on">true</bool>
-    
+
     <bool name="def_backup_enabled">false</bool>
     <string name="def_backup_transport" translatable="false">android/com.android.internal.backup.LocalTransport</string>
 
-    <!-- Default value for whether or not to pulse the notification LED when there is a 
+    <!-- Default value for whether or not to pulse the notification LED when there is a
          pending notification -->
     <bool name="def_notification_pulse">true</bool>
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 8eb3fe6..9ac832b 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -16,6 +16,15 @@
 
 package com.android.providers.settings;
 
+import com.android.internal.content.PackageHelper;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.util.XmlUtils;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternView;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
 import android.content.ComponentName;
 import android.content.ContentValues;
 import android.content.Context;
@@ -36,14 +45,6 @@
 import android.text.TextUtils;
 import android.util.Log;
 
-import com.android.internal.content.PackageHelper;
-import com.android.internal.telephony.RILConstants;
-import com.android.internal.util.XmlUtils;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.LockPatternView;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import java.io.IOException;
 import java.util.HashSet;
 import java.util.List;
@@ -60,7 +61,7 @@
     // database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
     // is properly propagated through your change.  Not doing so will result in a loss of user
     // settings.
-    private static final int DATABASE_VERSION = 58;
+    private static final int DATABASE_VERSION = 59;
 
     private Context mContext;
 
@@ -757,6 +758,23 @@
             upgradeVersion = 58;
         }
 
+        if (upgradeVersion == 58) {
+            /* Add default for new Auto Time Zone */
+            db.beginTransaction();
+            SQLiteStatement stmt = null;
+            try {
+                stmt = db.compileStatement("INSERT INTO secure(name,value)"
+                        + " VALUES(?,?);");
+                loadBooleanSetting(stmt, Settings.System.AUTO_TIME_ZONE,
+                        R.bool.def_auto_time_zone); // Sync timezone to NITZ
+                db.setTransactionSuccessful();
+            } finally {
+                db.endTransaction();
+                if (stmt != null) stmt.close();
+            }
+            upgradeVersion = 59;
+        }
+
         // *** Remember to update DATABASE_VERSION above!
 
         if (upgradeVersion != currentVersion) {
@@ -1067,7 +1085,10 @@
     
             loadBooleanSetting(stmt, Settings.System.AUTO_TIME,
                     R.bool.def_auto_time); // Sync time to NITZ
-    
+
+            loadBooleanSetting(stmt, Settings.System.AUTO_TIME_ZONE,
+                    R.bool.def_auto_time_zone); // Sync timezone to NITZ
+
             loadIntegerSetting(stmt, Settings.System.SCREEN_BRIGHTNESS,
                     R.integer.def_screen_brightness);
     
diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java
index 024aec5..29ca9a4 100644
--- a/services/java/com/android/server/InputManager.java
+++ b/services/java/com/android/server/InputManager.java
@@ -53,10 +53,6 @@
     private final Context mContext;
     private final WindowManagerService mWindowManagerService;
     
-    private int mTouchScreenConfig;
-    private int mKeyboardConfig;
-    private int mNavigationConfig;
-    
     private static native void nativeInit(Callbacks callbacks);
     private static native void nativeStart();
     private static native void nativeSetDisplaySize(int displayId, int width, int height);
@@ -79,6 +75,7 @@
     private static native void nativeSetInputDispatchMode(boolean enabled, boolean frozen);
     private static native void nativeSetFocusedApplication(InputApplication application);
     private static native InputDevice nativeGetInputDevice(int deviceId);
+    private static native void nativeGetInputConfiguration(Configuration configuration);
     private static native int[] nativeGetInputDeviceIds();
     private static native String nativeDump();
     
@@ -114,10 +111,6 @@
         
         this.mCallbacks = new Callbacks();
         
-        mTouchScreenConfig = Configuration.TOUCHSCREEN_NOTOUCH;
-        mKeyboardConfig = Configuration.KEYBOARD_NOKEYS;
-        mNavigationConfig = Configuration.NAVIGATION_NONAV;
-        
         init();
     }
     
@@ -154,9 +147,7 @@
             throw new IllegalArgumentException("config must not be null.");
         }
         
-        config.touchscreen = mTouchScreenConfig;
-        config.keyboard = mKeyboardConfig;
-        config.navigation = mNavigationConfig;
+        nativeGetInputConfiguration(config);
     }
     
     /**
@@ -367,12 +358,7 @@
         }
         
         @SuppressWarnings("unused")
-        public void notifyConfigurationChanged(long whenNanos,
-                int touchScreenConfig, int keyboardConfig, int navigationConfig) {
-            mTouchScreenConfig = touchScreenConfig;
-            mKeyboardConfig = keyboardConfig;
-            mNavigationConfig = navigationConfig;
-            
+        public void notifyConfigurationChanged(long whenNanos) {
             mWindowManagerService.sendNewConfiguration();
         }
         
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 1f8d697..c896c94 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -7105,6 +7105,12 @@
                     dumpServicesLocked(fd, pw, args, opti, true);
                 }
                 return;
+            } else {
+                // Dumping a single activity?
+                if (dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
+                    return;
+                }
+                pw.println("Bad activity command: " + cmd);
             }
         }
         
@@ -7458,6 +7464,82 @@
         }
     }
 
+    /**
+     * There are three things that cmd can be:
+     *  - a flattened component name that matched an existing activity
+     *  - the cmd arg isn't the flattened component name of an existing activity:
+     *    dump all activity whose component contains the cmd as a substring
+     *  - A hex number of the ActivityRecord object instance.
+     */
+    protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
+            int opti, boolean dumpAll) {
+        String[] newArgs;
+        ComponentName componentName = ComponentName.unflattenFromString(name);
+        int objectId = 0;
+        try {
+            objectId = Integer.parseInt(name, 16);
+            name = null;
+            componentName = null;
+        } catch (RuntimeException e) {
+        }
+        newArgs = new String[args.length - opti];
+        if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
+
+        ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
+        synchronized (this) {
+            for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
+                if (componentName != null) {
+                    if (r1.intent.getComponent().equals(componentName)) {
+                        activities.add(r1);
+                    }
+                } else if (name != null) {
+                    if (r1.intent.getComponent().flattenToString().contains(name)) {
+                        activities.add(r1);
+                    }
+                } else if (System.identityHashCode(this) == objectId) {
+                    activities.add(r1);
+                }
+            }
+        }
+
+        if (activities.size() <= 0) {
+            return false;
+        }
+
+        for (int i=0; i<activities.size(); i++) {
+            dumpActivity(fd, pw, activities.get(i), newArgs, dumpAll);
+        }
+        return true;
+    }
+
+    /**
+     * Invokes IApplicationThread.dumpActivity() on the thread of the specified activity if
+     * there is a thread associated with the activity.
+     */
+    private void dumpActivity(FileDescriptor fd, PrintWriter pw, ActivityRecord r, String[] args,
+            boolean dumpAll) {
+        pw.println("  Activity " + r.intent.getComponent().flattenToString());
+        if (dumpAll) {
+            synchronized (this) {
+                pw.print("  * "); pw.println(r);
+                r.dump(pw, "    ");
+            }
+            pw.println("");
+        }
+        if (r.app != null && r.app.thread != null) {
+            try {
+                // flush anything that is already in the PrintWriter since the thread is going
+                // to write to the file descriptor directly
+                pw.flush();
+                r.app.thread.dumpActivity(fd, r, args);
+                pw.print("\n");
+                pw.flush();
+            } catch (RemoteException e) {
+                pw.println("got a RemoteException while dumping the activity");
+            }
+        }
+    }
+
     boolean dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
             int opti, boolean dumpAll) {
         boolean needSep = false;
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 3bf6ee4..39ce0b6 100755
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -1171,7 +1171,10 @@
     private void reportAGpsStatus(int type, int status) {
         switch (status) {
             case GPS_REQUEST_AGPS_DATA_CONN:
-                 int result = mConnMgr.startUsingNetworkFeature(
+                // Set mAGpsDataConnectionState before calling startUsingNetworkFeature
+                //  to avoid a race condition with handleUpdateNetworkState()
+                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
+                int result = mConnMgr.startUsingNetworkFeature(
                         ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
                 if (result == Phone.APN_ALREADY_ACTIVE) {
                     if (mAGpsApn != null) {
@@ -1179,11 +1182,13 @@
                         mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
                     } else {
                         Log.e(TAG, "mAGpsApn not set when receiving Phone.APN_ALREADY_ACTIVE");
+                        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
                         native_agps_data_conn_failed();
                     }
                 } else if (result == Phone.APN_REQUEST_STARTED) {
-                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
+                    // Nothing to do here
                 } else {
+                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
                     native_agps_data_conn_failed();
                 }
                 break;
diff --git a/services/java/com/android/server/sip/SipService.java b/services/java/com/android/server/sip/SipService.java
index a2ebc69..f1dcd5a 100644
--- a/services/java/com/android/server/sip/SipService.java
+++ b/services/java/com/android/server/sip/SipService.java
@@ -172,7 +172,7 @@
         SipSessionGroupExt group = mSipGroups.remove(localProfileUri);
         if (group != null) {
             notifyProfileRemoved(group.getLocalProfile());
-            group.closeToNotReceiveCalls();
+            group.close();
             if (isWifiOn() && !anyOpened()) releaseWifiLock();
         }
     }
@@ -449,9 +449,9 @@
             }
         }
 
-        public void closeToNotReceiveCalls() {
+        public void close() {
             mOpened = false;
-            mSipGroup.closeToNotReceiveCalls();
+            mSipGroup.close();
             mAutoRegistration.stop();
             if (DEBUG) Log.d(TAG, "   close: " + getUri() + ": "
                     + mIncomingCallBroadcastAction);
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index d27c2c6..e3bae56 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -138,6 +138,14 @@
     jfieldID mMotionRanges;
 } gInputDeviceClassInfo;
 
+static struct {
+    jclass clazz;
+
+    jfieldID touchscreen;
+    jfieldID keyboard;
+    jfieldID navigation;
+} gConfigurationClassInfo;
+
 // ----------------------------------------------------------------------------
 
 static inline nsecs_t now() {
@@ -698,11 +706,7 @@
 
     JNIEnv* env = jniEnv();
 
-    InputConfiguration config;
-    mInputManager->getReader()->getInputConfiguration(& config);
-
-    env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyConfigurationChanged,
-            when, config.touchScreen, config.keyboard, config.navigation);
+    env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyConfigurationChanged, when);
     checkAndClearExceptionFromCallback(env, "notifyConfigurationChanged");
 }
 
@@ -1270,6 +1274,20 @@
     return deviceIdsObj;
 }
 
+static void android_server_InputManager_nativeGetInputConfiguration(JNIEnv* env,
+        jclass clazz, jobject configObj) {
+    if (checkInputManagerUnitialized(env)) {
+        return;
+    }
+
+    InputConfiguration config;
+    gNativeInputManager->getInputManager()->getReader()->getInputConfiguration(& config);
+
+    env->SetIntField(configObj, gConfigurationClassInfo.touchscreen, config.touchScreen);
+    env->SetIntField(configObj, gConfigurationClassInfo.keyboard, config.keyboard);
+    env->SetIntField(configObj, gConfigurationClassInfo.navigation, config.navigation);
+}
+
 static jstring android_server_InputManager_nativeDump(JNIEnv* env, jclass clazz) {
     if (checkInputManagerUnitialized(env)) {
         return NULL;
@@ -1316,6 +1334,8 @@
             (void*) android_server_InputManager_nativeGetInputDevice },
     { "nativeGetInputDeviceIds", "()[I",
             (void*) android_server_InputManager_nativeGetInputDeviceIds },
+    { "nativeGetInputConfiguration", "(Landroid/content/res/Configuration;)V",
+            (void*) android_server_InputManager_nativeGetInputConfiguration },
     { "nativeDump", "()Ljava/lang/String;",
             (void*) android_server_InputManager_nativeDump },
 };
@@ -1343,7 +1363,7 @@
     FIND_CLASS(gCallbacksClassInfo.clazz, "com/android/server/InputManager$Callbacks");
 
     GET_METHOD_ID(gCallbacksClassInfo.notifyConfigurationChanged, gCallbacksClassInfo.clazz,
-            "notifyConfigurationChanged", "(JIII)V");
+            "notifyConfigurationChanged", "(J)V");
 
     GET_METHOD_ID(gCallbacksClassInfo.notifyLidSwitchChanged, gCallbacksClassInfo.clazz,
             "notifyLidSwitchChanged", "(JZ)V");
@@ -1543,6 +1563,19 @@
     GET_FIELD_ID(gInputDeviceClassInfo.mMotionRanges, gInputDeviceClassInfo.clazz,
             "mMotionRanges", "[Landroid/view/InputDevice$MotionRange;");
 
+    // Configuration
+
+    FIND_CLASS(gConfigurationClassInfo.clazz, "android/content/res/Configuration");
+
+    GET_FIELD_ID(gConfigurationClassInfo.touchscreen, gConfigurationClassInfo.clazz,
+            "touchscreen", "I");
+
+    GET_FIELD_ID(gConfigurationClassInfo.keyboard, gConfigurationClassInfo.clazz,
+            "keyboard", "I");
+
+    GET_FIELD_ID(gConfigurationClassInfo.navigation, gConfigurationClassInfo.clazz,
+            "navigation", "I");
+
     return 0;
 }
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index 5d4dc58..b71cf13 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -16,6 +16,16 @@
 
 package com.android.internal.telephony.cdma;
 
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.DataConnectionTracker;
+import com.android.internal.telephony.EventLogTags;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.MccTable;
+import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.TelephonyProperties;
+
 import android.app.AlarmManager;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -38,19 +48,8 @@
 import android.text.TextUtils;
 import android.util.EventLog;
 import android.util.Log;
-import android.util.Config;
 import android.util.TimeUtils;
 
-import com.android.internal.telephony.CommandException;
-import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.DataConnectionTracker;
-import com.android.internal.telephony.EventLogTags;
-import com.android.internal.telephony.IccCard;
-import com.android.internal.telephony.MccTable;
-import com.android.internal.telephony.ServiceStateTracker;
-import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.telephony.TelephonyProperties;
-
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Date;
@@ -987,7 +986,7 @@
         mNeedFixZone = false;
 
         if (zone != null) {
-            if (getAutoTime()) {
+            if (getAutoTimeZone()) {
                 setAndBroadcastNetworkSetTimeZone(zone.getID());
             }
             saveNitzTimeZone(zone.getID());
@@ -1439,7 +1438,7 @@
             }
 
             if (zone != null) {
-                if (getAutoTime()) {
+                if (getAutoTimeZone()) {
                     setAndBroadcastNetworkSetTimeZone(zone.getID());
                 }
                 saveNitzTimeZone(zone.getID());
@@ -1529,6 +1528,14 @@
         }
     }
 
+    private boolean getAutoTimeZone() {
+        try {
+            return Settings.System.getInt(cr, Settings.System.AUTO_TIME_ZONE) > 0;
+        } catch (SettingNotFoundException snfe) {
+            return true;
+        }
+    }
+
     private void saveNitzTimeZone(String zoneId) {
         mSavedTimeZone = zoneId;
     }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index b639eea..83ad552 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -16,6 +16,17 @@
 
 package com.android.internal.telephony.gsm;
 
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.DataConnectionTracker;
+import com.android.internal.telephony.EventLogTags;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.MccTable;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.TelephonyProperties;
+
 import android.app.AlarmManager;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -47,17 +58,6 @@
 import android.util.Log;
 import android.util.TimeUtils;
 
-import com.android.internal.telephony.CommandException;
-import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.DataConnectionTracker;
-import com.android.internal.telephony.EventLogTags;
-import com.android.internal.telephony.IccCard;
-import com.android.internal.telephony.MccTable;
-import com.android.internal.telephony.RILConstants;
-import com.android.internal.telephony.ServiceStateTracker;
-import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.telephony.TelephonyProperties;
-
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Date;
@@ -995,7 +995,7 @@
                     mNeedFixZone = false;
 
                     if (zone != null) {
-                        if (getAutoTime()) {
+                        if (getAutoTimeZone()) {
                             setAndBroadcastNetworkSetTimeZone(zone.getID());
                         }
                         saveNitzTimeZone(zone.getID());
@@ -1476,7 +1476,7 @@
             }
 
             if (zone != null) {
-                if (getAutoTime()) {
+                if (getAutoTimeZone()) {
                     setAndBroadcastNetworkSetTimeZone(zone.getID());
                 }
                 saveNitzTimeZone(zone.getID());
@@ -1546,6 +1546,15 @@
         }
     }
 
+    private boolean getAutoTimeZone() {
+        try {
+            return Settings.System.getInt(phone.getContext().getContentResolver(),
+                    Settings.System.AUTO_TIME_ZONE) > 0;
+        } catch (SettingNotFoundException snfe) {
+            return true;
+        }
+    }
+
     private void saveNitzTimeZone(String zoneId) {
         mSavedTimeZone = zoneId;
     }
diff --git a/tests/DumpRenderTree2/assets/run_apache2.py b/tests/DumpRenderTree2/assets/run_apache2.py
index c799b5c..5edead1 100755
--- a/tests/DumpRenderTree2/assets/run_apache2.py
+++ b/tests/DumpRenderTree2/assets/run_apache2.py
@@ -109,18 +109,17 @@
 
   # Try to execute the commands
   logging.info("Will " + run_cmd + " apache2 server.")
-  cmd_template = export_envvars_cmd + " && " + apache2_restart_template + directives + conf_file_cmd
 
   # It is worth noting here that if the configuration file with which we restart the server points
-  # to a different PidFile it will not work and result in second apache2 instance.
+  # to a different PidFile it will not work and will result in a second apache2 instance.
   if (run_cmd == 'restart'):
     logging.info("First will stop...")
-    execute_cmd(cmd_template % ('stop'))
+    execute_cmd(export_envvars_cmd + " && " + (apache2_restart_template % ('stop')) + directives + conf_file_cmd)
     logging.info("Stopped. Will start now...")
     # We need to sleep breifly to avoid errors with apache being stopped and started too quickly
     time.sleep(0.5)
 
-  execute_cmd(cmd_template % (run_cmd))
+  execute_cmd(export_envvars_cmd + " && " + (apache2_restart_template % (run_cmd)) + directives + conf_file_cmd)
 
 def execute_cmd(cmd):
   p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java
index 96c1e5e..614b03c 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/AbstractResult.java
@@ -32,7 +32,7 @@
  * A class that represent a result of the test. It is responsible for returning the result's
  * raw data and generating its own diff in HTML format.
  */
-public abstract class AbstractResult implements Comparable<AbstractResult> {
+public abstract class AbstractResult implements Comparable<AbstractResult>, Serializable {
 
     private static final String LOG_TAG = "AbstractResult";
 
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
index b9fc274..c0ba9e5 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
@@ -22,6 +22,7 @@
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.net.Uri;
+import android.net.http.SslError;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.Handler;
@@ -30,19 +31,20 @@
 import android.os.Messenger;
 import android.os.PowerManager;
 import android.os.Process;
-import android.os.RemoteException;
 import android.os.PowerManager.WakeLock;
+import android.os.RemoteException;
 import android.util.Log;
 import android.view.Window;
 import android.webkit.ConsoleMessage;
+import android.webkit.GeolocationPermissions;
 import android.webkit.HttpAuthHandler;
 import android.webkit.JsPromptResult;
 import android.webkit.JsResult;
+import android.webkit.SslErrorHandler;
 import android.webkit.WebChromeClient;
 import android.webkit.WebSettings;
 import android.webkit.WebView;
 import android.webkit.WebViewClient;
-import android.webkit.GeolocationPermissions;
 import android.webkit.WebStorage.QuotaUpdater;
 
 import java.io.File;
@@ -74,7 +76,7 @@
         }
     }
 
-    private static final String LOG_TAG = "LayoutTestExecutor";
+    private static final String LOG_TAG = "LayoutTestsExecutor";
 
     public static final String EXTRA_TESTS_LIST = "TestsList";
     public static final String EXTRA_TEST_INDEX = "TestIndex";
@@ -180,6 +182,13 @@
              }
              handler.cancel();
          }
+
+         @Override
+         public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
+             // We ignore SSL errors. In particular, the certificate used by the LayoutTests server
+             // produces an error as it lacks a CN field.
+             handler.proceed();
+         }
     };
 
     private WebChromeClient mWebChromeClient = new WebChromeClient() {
@@ -236,7 +245,7 @@
                  * We never display the new window, just create the view and allow it's content to
                  * execute and be recorded by the executor.
                  */
-                newWindowWebView = new WebView(LayoutTestsExecutor.this);
+                newWindowWebView = createWebViewWithJavascriptInterfaces();
                 setupWebView(newWindowWebView);
             }
 
@@ -317,7 +326,7 @@
         mCurrentResult = null;
         mCurrentAdditionalTextOutput = null;
 
-        mCurrentWebView = new WebView(this);
+        mCurrentWebView = createWebViewWithJavascriptInterfaces();
         setupWebView(mCurrentWebView);
 
         mEventSender.reset(mCurrentWebView);
@@ -329,11 +338,26 @@
         }
     }
 
+    private static class WebViewWithJavascriptInterfaces extends WebView {
+        public WebViewWithJavascriptInterfaces(
+                Context context, Map<String, Object> javascriptInterfaces) {
+            super(context,
+                  null, // attribute set
+                  0, // default style resource ID
+                  javascriptInterfaces,
+                  false); // is private browsing
+        }
+    }
+    private WebView createWebViewWithJavascriptInterfaces() {
+        Map<String, Object> javascriptInterfaces = new HashMap<String, Object>();
+        javascriptInterfaces.put("layoutTestController", mLayoutTestController);
+        javascriptInterfaces.put("eventSender", mEventSender);
+        return new WebViewWithJavascriptInterfaces(this, javascriptInterfaces);
+    }
+
     private void setupWebView(WebView webView) {
         webView.setWebViewClient(mWebViewClient);
         webView.setWebChromeClient(mWebChromeClient);
-        webView.addJavascriptInterface(mLayoutTestController, "layoutTestController");
-        webView.addJavascriptInterface(mEventSender, "eventSender");
 
         /**
          * Setting a touch interval of -1 effectively disables the optimisation in WebView
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java
index e232021..27974e7 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/AdvancedGradientsActivity.java
@@ -42,19 +42,25 @@
         private final RadialGradient mRadialGradient;
         private final Matrix mMatrix;
         private final Matrix mMatrix2;
+        private final Matrix mMatrix3;
 
         GradientsView(Context c) {
             super(c);
 
-            mSweepGradient = new SweepGradient(100.0f, 100.0f, 0xff000000, 0xffffffff);
-            mRadialGradient = new RadialGradient(100.0f, 100.0f, 100.0f, 0xff000000, 0xffffffff,
+            mSweepGradient = new SweepGradient(0.0f, 0.0f, 0xff000000, 0xffffffff);
+            mRadialGradient = new RadialGradient(0.0f, 0.0f, 100.0f, 0xff000000, 0xffffffff,
                     Shader.TileMode.MIRROR);
             
             mMatrix = new Matrix();
-            mMatrix.setTranslate(50.0f, 50.0f);
+            mMatrix.setRotate(-45, 0.0f, 0.0f);
+            mMatrix.postTranslate(100.0f, 100.0f);
 
             mMatrix2 = new Matrix();
-            mMatrix2.setScale(2.0f, 2.0f);
+            mMatrix2.setScale(1.0f, 2.0f);
+            mMatrix2.postRotate(-45, 0.0f, 0.0f);
+
+            mMatrix3 = new Matrix();
+            mMatrix3.setTranslate(100.0f, 100.0f);            
             
             mPaint = new Paint();
         }
@@ -64,30 +70,42 @@
             super.onDraw(canvas);
             canvas.drawRGB(255, 255, 255);
 
-            // Bitmap shaders
             canvas.save();
             canvas.translate(130.0f, 100.0f);
 
-            mSweepGradient.setLocalMatrix(null);
+            mSweepGradient.setLocalMatrix(mMatrix3);
             mPaint.setShader(mSweepGradient);
             canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
 
             canvas.translate(400.0f, 000.0f);
             
-            mPaint.setShader(mRadialGradient);
-            canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
-
-            canvas.translate(400.0f, 000.0f);
-            
             mSweepGradient.setLocalMatrix(mMatrix);
             mPaint.setShader(mSweepGradient);
-            canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
+            canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);            
 
-            canvas.translate(-800.0f, 300.0f);
+            canvas.translate(400.0f, 000.0f);
             
             mSweepGradient.setLocalMatrix(mMatrix2);
             mPaint.setShader(mSweepGradient);
             canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
+
+            canvas.translate(-800.0f, 300.0f);
+
+            mRadialGradient.setLocalMatrix(null);
+            mPaint.setShader(mRadialGradient);
+            canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
+            
+            canvas.translate(400.0f, 000.0f);
+            
+            mRadialGradient.setLocalMatrix(mMatrix);
+            mPaint.setShader(mRadialGradient);
+            canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
+
+            canvas.translate(400.0f, 000.0f);
+            
+            mRadialGradient.setLocalMatrix(mMatrix2);
+            mPaint.setShader(mRadialGradient);
+            canvas.drawRect(0.0f, 0.0f, 200.0f, 200.0f, mPaint);
             
             
             canvas.restore();
diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
index 0910d79..4bc8855 100644
--- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
+++ b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
@@ -116,10 +116,10 @@
     }
     
     @Override
-    public View createViewFromTag(String name, AttributeSet attrs) {
+    public View createViewFromTag(View parent, String name, AttributeSet attrs) {
         View view = null;
         try {
-            view = super.createViewFromTag(name, attrs);
+            view = super.createViewFromTag(parent, name, attrs);
         } catch (InflateException e) {
             // try to load the class from using the custom view loader
             try {
diff --git a/tools/layoutlib/create/README.txt b/tools/layoutlib/create/README.txt
index 09b392b..c59e20d 100644
--- a/tools/layoutlib/create/README.txt
+++ b/tools/layoutlib/create/README.txt
@@ -4,68 +4,196 @@
 - Description -
 ---------------
 
-makeLayoutLib generates a library used by the Eclipse graphical layout editor
+Layoutlib_create generates a JAR library used by the Eclipse graphical layout editor
 to perform layout.
 
 
-
 - Usage -
 ---------
 
- ./makeLayoutLib path/to/android.jar destination.jar
+ ./layoutlib_create path/to/android.jar destination.jar
+
+
+- Design Overview -
+-------------------
+
+Layoutlib_create uses the "android.jar" containing all the Java code used by Android
+as generated by the Android build, right before the classes are converted to a DEX format.
+
+The Android JAR can't be used directly in Eclipse:
+- it contains references to native code (which we want to avoid in Eclipse),
+- some classes need to be overridden, for example all the drawing code that is
+  replaced by Java 2D calls in Eclipse.
+- some of the classes that need to be changed are final and/or we need access
+  to their private internal state.
+
+Consequently this tool:
+- parses the input JAR,
+- modifies some of the classes directly using some bytecode manipulation,
+- filters some packages and removes some that we don't want to end in the output JAR,
+- injects some new classes,
+- and generates a modified JAR file that is suitable for the Android plugin
+  for Eclipse to perform rendering.
+
+The ASM library is used to do the bytecode modification using its visitor pattern API.
+
+The layoutlib_create is *NOT* generic. There is no configuration file. Instead all the
+configuration is done in the main() method and the CreateInfo structure is expected to
+change with the Android platform as new classes are added, changed or removed.
+
+The resulting JAR is used by layoutlib_bridge (a.k.a. "the bridge"), also part of the
+platform, that provides all the necessary missing implementation for rendering graphics
+in Eclipse.
 
 
 
 - Implementation Notes -
 ------------------------
 
-The goal of makeLayoutLib is to list all the classes from the input jar and create a new
-jar that only keeps certain classes and create stubs for all their dependencies.
-
-First the input jar is parsed to find all the classes defined.
-
-In the Main(), the following list of classes are hardcoded (TODO config file later):
-- keep all classes that derive from android.view.View.
-- keep all classes in the android.view and android.widget packages (sub-packages excluded).
-- keep specific classes such as android.policy.PhoneLayoutInflater.
-
-For each class to keep, their dependencies are examined using BCEL.
-A dependency is defined as a class needed to instantiate the given class that should be kept,
-directly or indirectly. So a dependency is a class that is used by the input class, that is
-defined in the input jar and that is not part of the current JRE.
-
-Dependencies are computed recursively.
-
-Once all dependencies are found, the final jar can be created.
-There are three kind of classes to write:
-- classes that are to be kept as-is. They are just dumped in the new jar unchanged.
-- classes that are to be kept yet contain native methods or fields.
-- classes that are just dependencies. We don't want to expose their implementation in the final
-  jar.
-
-The implementation of native methods and all methods of mock classes is replaced by a stub
-that throws UnsupportedOperationException.
-
-Incidentally, the access level of native and mock classes needs to be changed in order for
-native methods to be later overridden. Methods that are "final private native" must become
-non-final, non-native and at most protected. Package-default access is changed to public.
-Classes that are final are made non-final. Abstract methods are left untouched.
+The tool works in two phases:
+- first analyze the input jar (AsmAnalyzer class)
+- then generate the output jar (AsmGenerator class),
 
 
+- Analyzer
+----------
 
-----
-20080617 Replace Class
+The goal of the analyzer is to create a graph of all the classes from the input JAR
+with their dependencies and then only keep the ones we want.
 
-Some classes are basically wrappers over native objects.
-Subclassing doesn't work as most methods are either static or we don't
-control object creation. In this scenario the idea is to be able to
-replace classes in the final jar.
+To do that, the analyzer is created with a list of base classes to keep -- everything
+that derives from these is kept. Currently the one such class is android.view.View:
+since we want to render layouts, anything that is sort of the view needs to be kept.
 
-Example: android.graphics.Paint would get renamed to OriginalPaint
-in the generated jar. Then in the bridge we'll introduce a replacement
-Paint class that derives from OriginalPaint.
+The analyzer is also given a list of class names to keep in the output.
+This is done using shell-like glob patterns that filter on the fully-qualified
+class names, for example "android.*.R**" ("*" does not matches dots whilst "**" does,
+and "." and "$" are interpreted as-is).
+In practice we almost but not quite request the inclusion of full packages.
+
+With this information, the analyzer parses the input zip to find all the classes.
+All classes deriving from the requested bases classes are kept.
+All classes which name matched the glob pattern are kept.
+The analysis then finds all the dependencies of the classes that are to be kept
+using an ASM visitor on the class, the field types, the method types and annotations types.
+Classes that belong to the current JRE are excluded.
+
+The output of the analyzer is a set of ASM ClassReader instances which are then
+fed to the generator.
+
+
+- Generator
+-----------
+
+The generator is constructed from a CreateInfo struct that acts as a config file
+and lists:
+- the classes to inject in the output JAR -- these classes are directly implemented
+  in layoutlib_create and will be used to interface with the renderer in Eclipse.
+- specific methods to override (see method stubs details below).
+- specific methods to remove based on their return type.
+- specific classes to rename.
+
+Each of these are specific strategies we use to be able to modify the Android code
+to fit within the Eclipse renderer. These strategies are explained beow.
+
+The core method of the generator is transform(): it takes an input ASM ClassReader
+and modifies it to produce a byte array suitable for the final JAR file.
+
+The first step of the transformation is changing the name of the class in case
+we requested the class to be renamed. This uses the RenameClassAdapter to also rename
+all inner classes and references in methods and types. Note that other classes are
+not transformed and keep referencing the original name.
+
+The TransformClassAdapter is then used to process the potentially renamed class.
+All protected or private classes are market as public.
+All classes are made non-final.
+Interfaces are left as-is.
+
+If a method has a return type that must be erased, the whole method is skipped.
+Methods are also changed from protected/private to public.
+The code of the methods is then kept as-is, except for native methods which are
+replaced by a stub. Methods that are to be overridden are also replaced by a stub.
+
+Finally fields are also visited and changed from protected/private to public.
+
+
+- Method stubs
+--------------
+
+As indicated above, all native and overridden methods are replaced by a stub.
+We don't have the code to replace with in layoutlib_create.
+Instead the StubMethodAdapter replaces the code of the method by a call to
+OverrideMethod.invokeX(). When using the final JAR, the bridge can register
+listeners from these overridden method calls based on the method signatures.
+
+The listeners are currently pretty basic: we only pass the signature of the
+method being called, its caller object and a flag indicating whether the
+method was native. We do not currently provide the parameters. The listener
+can however specify the return value of the overridden method.
+
+An extension being worked on is to actually replace these listeners by
+direct calls to a delegate class, complete with parameters.
+
+
+- Strategies
+------------
+
+We currently have 4 strategies to deal with overriding the rendering code
+and make it run in Eclipse. Most of these strategies are implemented hand-in-hand
+by the bridge (which runs in Eclipse) and the generator.
+
+
+1- Class Injection
+
+This is the easiest: we currently inject 4 classes, namely:
+- OverrideMethod and its associated MethodListener and MethodAdapter are used
+  to intercept calls to some specific methods that are stubbed out and change
+  their return value.
+- CreateInfo class, which configured the generator. Not used yet, but could
+  in theory help us track what the generator changed.
+
+
+2- Overriding methods
+
+As explained earlier, the creator doesn't have any replacement code for
+methods to override. Instead it removes the original code and replaces it
+by a call to a specific OveriddeMethod.invokeX(). The bridge then registers
+a listener on the method signature and can provide an implementation.
+
+
+3- Renaming classes
+
+This simply changes the name of a class in its definition, as well as all its
+references in internal inner classes and methods.
+Calls from other classes are not modified -- they keep referencing the original
+class name. This allows the bridge to literally replace an implementation.
+
+An example will make this easier: android.graphics.Paint is the main drawing
+class that we need to replace. To do so, the generator renames Paint to _original_Paint.
+Later the bridge provides its own replacement version of Paint which will be used
+by the rest of the Android stack. The replacement version of Paint can still use
+(either by inheritance or delegation) all the original non-native code of _original_Paint
+if it so desires.
+
+Some of the Android classes are basically wrappers over native objects and since
+we don't have the native code in Eclipse, we need to provide a full alternate
+implementation. Sub-classing doesn't work as some native methods are static and
+we don't control object creation.
 
 This won't rename/replace the inner static methods of a given class.
 
 
+4- Method erasure based on return type
 
+This is mostly an implementation detail of the bridge: in the Paint class
+mentioned above, some inner static classes are used to pass around
+attributes (e.g. FontMetrics, or the Style enum) and all the original implementation
+is native.
+
+In this case we have a strategy that tells the generator that anything returning, for
+example, the inner class Paint$Style in the Paint class should be discarded and the
+bridge will provide its own implementation.
+
+
+--
+end
diff --git a/tools/obbtool/mkobb.sh b/tools/obbtool/mkobb.sh
new file mode 100755
index 0000000..f4cae9a1
--- /dev/null
+++ b/tools/obbtool/mkobb.sh
@@ -0,0 +1,260 @@
+#!/bin/bash
+#
+# 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.
+#
+
+# mkobb.sh - Creates OBB files on Linux machines
+
+# Directory where we should temporarily mount the OBB loopback to copy files
+MOUNTDIR=/tmp
+
+# Presets. Changing these will probably break your OBB on the device
+CRYPTO=blowfish
+FS=vfat
+MKFS=mkfs.vfat
+LOSETUP=losetup
+BLOCK_SIZE=512
+SLOP=512 # Amount of filesystem slop in ${BLOCK_SIZE} blocks
+
+find_binaries() {
+    MKFSBIN=`which ${MKFS}`
+    LOSETUPBIN=`which ${LOSETUP}`
+    MOUNTBIN=`which mount`
+    UMOUNTBIN=`which umount`
+    DDBIN=`which dd`
+    RSYNCBIN=`which rsync`
+}
+
+check_prereqs() {
+    if [ "`uname -s`x" != "Linuxx" ]; then \
+        echo "ERROR: This script only works on Linux!"
+        exit 1
+    fi
+
+    if ! egrep -q "^cryptoloop " /proc/modules; then \
+        echo "ERROR: Could not find cryptoloop in the kernel."
+        echo "Perhaps you need to: modprobe cryptoloop"
+        exit 1
+    fi
+
+    if ! egrep -q "name\s*:\s*${CRYPTO}$" /proc/crypto; then \
+        echo "ERROR: Could not find crypto \`${CRYPTO}' in the kernel."
+        echo "Perhaps you need to: modprobe ${CRYPTO}"
+        exit 1
+    fi
+
+    if ! egrep -q "^\s*${FS}$" /proc/filesystems; then \
+        echo "ERROR: Could not find filesystem \`${FS}' in the kernel."
+        echo "Perhaps you need to: modprobe ${FS}"
+        exit 1
+    fi
+
+    if [ "${MKFSBIN}x" = "x" ]; then \
+        echo "ERROR: Could not find ${MKFS} in your path!"
+        exit 1
+    elif [ ! -x "${MKFSBIN}" ]; then \
+        echo "ERROR: ${MKFSBIN} is not executable!"
+        exit 1
+    fi
+
+    if [ "${LOSETUPBIN}x" = "x" ]; then \
+        echo "ERROR: Could not find ${LOSETUP} in your path!"
+        exit 1
+    elif [ ! -x "${LOSETUPBIN}" ]; then \
+        echo "ERROR: ${LOSETUPBIN} is not executable!"
+        exit 1
+    fi
+}
+
+cleanup() {
+    if [ "${loopdev}x" != "x" ]; then \
+        ${LOSETUPBIN} -d ${loopdev}
+    fi
+}
+
+hidden_prompt() {
+    unset output
+    prompt="$1"
+    outvar="$2"
+    while read -s -n 1 -p "$prompt" c; do \
+        if [ "x$c" = "x" ]; then \
+            break
+        fi
+        prompt='*'
+        output="${output}${c}"
+    done
+    echo
+    eval $outvar="$output"
+    unset output
+}
+
+read_key() {
+    hidden_prompt "        Encryption key: " key
+
+    if [ "${key}x" = "x" ]; then \
+        echo "ERROR: An empty key is not allowed!"
+        exit 1
+    fi
+
+    hidden_prompt "Encryption key (again): " key2
+
+    if [ "${key}x" != "${key2}x" ]; then \
+        echo "ERROR: Encryption keys do not match!"
+        exit 1
+    fi
+}
+
+onexit() {
+    if [ "x${temp_mount}" != "x" ]; then \
+        ${UMOUNTBIN} ${temp_mount}
+        rmdir ${temp_mount}
+    fi
+    if [ "x${loop_dev}" != "x" ]; then \
+        ${LOSETUPBIN} -d ${loop_dev}
+    fi
+    if [ "x${tempfile}" != "x" -a -f "${tempfile}" ]; then \
+        rm -f ${tempfile}
+    fi
+    if [ "x${keyfile}" != "x" -a -f "${keyfile}" ]; then \
+        rm -f ${keyfile}
+    fi
+    echo "Fatal error."
+    exit 1
+}
+
+usage() {
+    echo "mkobb.sh -- Create OBB files for use on Android"
+    echo ""
+    echo " -c             Use an encrypted OBB; must specify key"
+    echo " -d <directory> Use <directory> as input for OBB files"
+    echo " -k <key>       Use <key> to encrypt OBB file"
+    echo " -K             Prompt for key to encrypt OBB file"
+    echo " -o <filename>  Write OBB file out to <filename>"
+    echo " -v             Verbose mode"
+    echo " -h             Help; this usage screen"
+}
+
+find_binaries
+check_prereqs
+
+use_crypto=0
+
+args=`getopt -o cd:hk:Ko:v -- "$@"`
+eval set -- "$args"
+
+while true; do \
+    case "$1" in
+        -c) use_crypto=1; shift;;
+        -d) directory=$2; shift 2;;
+        -h) usage; exit 1;;
+        -k) key=$2; shift 2;;
+        -K) prompt_key=1; shift;;
+        -v) verbose=1; shift;;
+        -o) filename=$2; shift 2;;
+        --) shift; break;;
+        *) echo "ERROR: Invalid argument in option parsing! Cannot recover. Ever."; exit 1;;
+    esac
+done
+
+if [ "${directory}x" = "x" -o ! -d "${directory}" ]; then \
+    echo "ERROR: Must specify valid input directory"
+    echo ""
+    usage
+    exit 1;
+fi
+
+if [ "${filename}x" = "x" ]; then \
+    echo "ERROR: Must specify filename"
+    echo ""
+    usage
+    exit 1;
+fi
+
+if [ ${use_crypto} -eq 1 -a "${key}x" = "x" -a 0${prompt_key} -eq 0 ]; then \
+    echo "ERROR: Crypto desired, but no key supplied or requested to prompt for."
+    exit 1
+fi
+
+if [ 0${prompt_key} -eq 1 ]; then \
+    read_key
+fi
+
+outdir=`dirname ${filename}`
+if [ ! -d "${outdir}" ]; then \
+    echo "ERROR: Output directory does not exist: ${outdir}"
+    exit 1
+fi
+
+# Make sure we clean up any stuff we create from here on during error conditions
+trap onexit ERR
+
+tempfile=$(tempfile -d ${outdir}) || ( echo "ERROR: couldn't create temporary file in ${outdir}"; exit 1 )
+
+block_count=`du --apparent-size --block-size=512 ${directory} | awk '{ print $1; }'`
+if [ $? -ne 0 ]; then \
+    echo "ERROR: Couldn't read size of input directory ${directory}"
+    exit 1
+fi
+
+echo "Creating temporary file..."
+${DDBIN} if=/dev/zero of=${tempfile} bs=${BLOCK_SIZE} count=$((${block_count} + ${SLOP})) > /dev/null 2>&1
+if [ $? -ne 0 ]; then \
+    echo "ERROR: creating temporary file: $?"
+fi
+
+loop_dev=$(${LOSETUPBIN} -f) || ( echo "ERROR: losetup wouldn't tell us the next unused device"; exit 1 )
+
+if [ ${use_crypto} -eq 1 ]; then \
+    keyfile=$(tempfile -d ${outdir}) || ( echo "ERROR: could not create temporary key file"; exit 1 )
+    ${LOSETUPBIN} -p 5 -e ${CRYPTO} ${loop_dev} ${tempfile} 5< ${keyfile} || ( echo "ERROR: couldn't create loopback device"; exit 1 )
+    rm -f ${keyfile}
+else \
+    ${LOSETUPBIN} ${loop_dev} ${tempfile} || ( echo "ERROR: couldn't create loopback device"; exit 1 )
+fi
+
+#
+# Create the filesystem
+#
+echo ""
+${MKFSBIN} -I ${loop_dev}
+echo ""
+
+#
+# Make the temporary mount point and mount it
+#
+temp_mount="${MOUNTDIR}/${RANDOM}"
+mkdir ${temp_mount}
+${MOUNTBIN} -t ${FS} -o loop ${loop_dev} ${temp_mount}
+
+#
+# rsync the files!
+#
+echo "Copying files:"
+${RSYNCBIN} -av --no-owner --no-group ${directory}/ ${temp_mount}/
+echo ""
+
+echo "Successfully created \`${filename}'"
+
+#
+# Undo all the temporaries
+#
+umount ${temp_mount}
+rmdir ${temp_mount}
+${LOSETUPBIN} -d ${loop_dev}
+mv ${tempfile} ${filename}
+
+trap - ERR
+
+exit 0