Merge "Add support for arbitrary axes in MotionEvents."
diff --git a/Android.mk b/Android.mk
index ebc5213..1407631 100644
--- a/Android.mk
+++ b/Android.mk
@@ -429,13 +429,13 @@
 		-samplecode $(sample_dir)/SpinnerTest \
 		            resources/samples/SpinnerTest "SpinnerTest" \
 		-samplecode $(sample_dir)/StackWidget \
-		            resources/samples/StackWidget "StackWidget" \
+		            resources/samples/StackWidget "StackView Widget" \
 		-samplecode $(sample_dir)/TicTacToeLib  \
 		            resources/samples/TicTacToeLib "TicTacToeLib" \
 		-samplecode $(sample_dir)/TicTacToeMain \
 		            resources/samples/TicTacToeMain "TicTacToeMain" \
 		-samplecode $(sample_dir)/WeatherListWidget \
-		            resources/samples/WeatherListWidget "Weather List Widget Sample" \
+		            resources/samples/WeatherListWidget "Weather List Widget" \
 		-samplecode $(sample_dir)/Wiktionary \
 		            resources/samples/Wiktionary "Wiktionary" \
 		-samplecode $(sample_dir)/WiktionarySimple \
diff --git a/api/11.xml b/api/11.xml
index ad06679..76669e3 100644
--- a/api/11.xml
+++ b/api/11.xml
@@ -37266,17 +37266,6 @@
  visibility="public"
 >
 </field>
-<field name="USES_POLICY_SETS_GLOBAL_PROXY"
- type="int"
- transient="false"
- volatile="false"
- value="5"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="USES_POLICY_WATCH_LOGIN"
  type="int"
  transient="false"
@@ -37592,17 +37581,6 @@
  visibility="public"
 >
 </method>
-<method name="getGlobalProxyAdmin"
- return="android.content.ComponentName"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="getMaximumFailedPasswordsForWipe"
  return="int"
  abstract="false"
@@ -37887,23 +37865,6 @@
 <parameter name="flags" type="int">
 </parameter>
 </method>
-<method name="setGlobalProxy"
- return="android.content.ComponentName"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="admin" type="android.content.ComponentName">
-</parameter>
-<parameter name="proxySpec" type="java.net.Proxy">
-</parameter>
-<parameter name="exclusionList" type="java.util.List&lt;java.lang.String&gt;">
-</parameter>
-</method>
 <method name="setMaximumFailedPasswordsForWipe"
  return="void"
  abstract="false"
diff --git a/api/current.xml b/api/current.xml
index d5decd9..9a38459 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -37376,17 +37376,6 @@
  visibility="public"
 >
 </field>
-<field name="USES_POLICY_SETS_GLOBAL_PROXY"
- type="int"
- transient="false"
- volatile="false"
- value="5"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="USES_POLICY_WATCH_LOGIN"
  type="int"
  transient="false"
@@ -37702,17 +37691,6 @@
  visibility="public"
 >
 </method>
-<method name="getGlobalProxyAdmin"
- return="android.content.ComponentName"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="getMaximumFailedPasswordsForWipe"
  return="int"
  abstract="false"
@@ -37997,23 +37975,6 @@
 <parameter name="flags" type="int">
 </parameter>
 </method>
-<method name="setGlobalProxy"
- return="android.content.ComponentName"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="admin" type="android.content.ComponentName">
-</parameter>
-<parameter name="proxySpec" type="java.net.Proxy">
-</parameter>
-<parameter name="exclusionList" type="java.util.List&lt;java.lang.String&gt;">
-</parameter>
-</method>
 <method name="setMaximumFailedPasswordsForWipe"
  return="void"
  abstract="false"
@@ -76410,6 +76371,17 @@
 <parameter name="offsetXY" type="int[]">
 </parameter>
 </method>
+<method name="getByteCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getConfig"
  return="android.graphics.Bitmap.Config"
  abstract="false"
@@ -94147,6 +94119,97 @@
 >
 </field>
 </class>
+<class name="UsbAccessory"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getManufacturer"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getModel"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getType"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getVersion"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="parcel" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="UsbConstants"
  extends="java.lang.Object"
  abstract="false"
@@ -95097,6 +95160,17 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<method name="getAccessoryList"
+ return="android.hardware.UsbAccessory[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getDeviceList"
  return="java.util.HashMap&lt;java.lang.String, android.hardware.UsbDevice&gt;"
  abstract="false"
@@ -95134,6 +95208,19 @@
 <parameter name="function" type="java.lang.String">
 </parameter>
 </method>
+<method name="openAccessory"
+ return="android.os.ParcelFileDescriptor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="accessory" type="android.hardware.UsbAccessory">
+</parameter>
+</method>
 <method name="openDevice"
  return="boolean"
  abstract="false"
@@ -95147,6 +95234,28 @@
 <parameter name="device" type="android.hardware.UsbDevice">
 </parameter>
 </method>
+<field name="ACTION_USB_ACCESSORY_ATTACHED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.hardware.action.USB_ACCESSORY_ATTACHED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_USB_ACCESSORY_DETACHED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.hardware.action.USB_ACCESSORY_DETACHED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ACTION_USB_DEVICE_ATTACHED"
  type="java.lang.String"
  transient="false"
@@ -95180,6 +95289,61 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_ACCESSORY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;accessory&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_ACCESSORY_MANUFACTURER"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;accessory-manufacturer&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_ACCESSORY_PRODUCT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;accessory-product&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_ACCESSORY_TYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;accessory-type&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_ACCESSORY_VERSION"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;accessory-version&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="EXTRA_DEVICE"
  type="java.lang.String"
  transient="false"
@@ -95279,6 +95443,17 @@
  visibility="public"
 >
 </field>
+<field name="USB_FUNCTION_ACCESSORY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;accessory&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="USB_FUNCTION_ADB"
  type="java.lang.String"
  transient="false"
@@ -117430,7 +117605,7 @@
  type="android.net.http.SslCertificate"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="issuedTo" type="java.lang.String">
@@ -121010,6 +121185,17 @@
  visibility="public"
 >
 </field>
+<field name="WIFI_MODE_FULL_HIGH_PERF"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="WIFI_MODE_SCAN_ONLY"
  type="int"
  transient="false"
@@ -224158,17 +224344,6 @@
  visibility="public"
 >
 </method>
-<field name="DRAG_FLAG_GLOBAL"
- type="int"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="DRAWING_CACHE_QUALITY_AUTO"
  type="int"
  transient="false"
@@ -237716,6 +237891,19 @@
 >
 <implements name="android.os.Parcelable">
 </implements>
+<method name="containsExtraValueKey"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="java.lang.String">
+</parameter>
+</method>
 <method name="describeContents"
  return="int"
  abstract="false"
@@ -237738,6 +237926,19 @@
  visibility="public"
 >
 </method>
+<method name="getExtraValueOf"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="key" type="java.lang.String">
+</parameter>
+</method>
 <method name="getIconResId"
  return="int"
  abstract="false"
diff --git a/core/java/android/animation/FloatKeyframeSet.java b/core/java/android/animation/FloatKeyframeSet.java
index 4009f13..377b5a05 100644
--- a/core/java/android/animation/FloatKeyframeSet.java
+++ b/core/java/android/animation/FloatKeyframeSet.java
@@ -87,7 +87,7 @@
             }
             float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction);
             return mEvaluator == null ?
-                    prevValue + fraction * (nextValue - prevValue) :
+                    prevValue + intervalFraction * (nextValue - prevValue) :
                     ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).
                             floatValue();
         } else if (fraction >= 1f) {
@@ -103,7 +103,7 @@
             }
             float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction);
             return mEvaluator == null ?
-                    prevValue + fraction * (nextValue - prevValue) :
+                    prevValue + intervalFraction * (nextValue - prevValue) :
                     ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).
                             floatValue();
         }
@@ -120,7 +120,7 @@
                 float prevValue = prevKeyframe.getFloatValue();
                 float nextValue = nextKeyframe.getFloatValue();
                 return mEvaluator == null ?
-                        prevValue + fraction * (nextValue - prevValue) :
+                        prevValue + intervalFraction * (nextValue - prevValue) :
                         ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).
                             floatValue();
             }
diff --git a/core/java/android/animation/IntKeyframeSet.java b/core/java/android/animation/IntKeyframeSet.java
index 5629c5e..7b7c876 100644
--- a/core/java/android/animation/IntKeyframeSet.java
+++ b/core/java/android/animation/IntKeyframeSet.java
@@ -87,7 +87,7 @@
             }
             float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction);
             return mEvaluator == null ?
-                    prevValue + (int)(fraction * (nextValue - prevValue)) :
+                    prevValue + (int)(intervalFraction * (nextValue - prevValue)) :
                     ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).
                             intValue();
         } else if (fraction >= 1f) {
@@ -103,7 +103,7 @@
             }
             float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction);
             return mEvaluator == null ?
-                    prevValue + (int)(fraction * (nextValue - prevValue)) :
+                    prevValue + (int)(intervalFraction * (nextValue - prevValue)) :
                     ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).intValue();
         }
         IntKeyframe prevKeyframe = (IntKeyframe) mKeyframes.get(0);
@@ -119,7 +119,7 @@
                 int prevValue = prevKeyframe.getIntValue();
                 int nextValue = nextKeyframe.getIntValue();
                 return mEvaluator == null ?
-                        prevValue + (int)(fraction * (nextValue - prevValue)) :
+                        prevValue + (int)(intervalFraction * (nextValue - prevValue)) :
                         ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).
                                 intValue();
             }
diff --git a/core/java/android/animation/KeyframeSet.java b/core/java/android/animation/KeyframeSet.java
index fa61b71..6172aab 100644
--- a/core/java/android/animation/KeyframeSet.java
+++ b/core/java/android/animation/KeyframeSet.java
@@ -212,4 +212,13 @@
         // shouldn't reach here
         return mLastKeyframe.getValue();
     }
+
+    @Override
+    public String toString() {
+        String returnVal = " ";
+        for (int i = 0; i < mNumKeyframes; ++i) {
+            returnVal += mKeyframes.get(i).getValue() + "  ";
+        }
+        return returnVal;
+    }
 }
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index d038cd6..b8a7cb2 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -394,4 +394,16 @@
         final ObjectAnimator anim = (ObjectAnimator) super.clone();
         return anim;
     }
+
+    @Override
+    public String toString() {
+        String returnVal = "ObjectAnimator@" + Integer.toHexString(hashCode()) + ", target " +
+            mTarget;
+        if (mValues != null) {
+            for (int i = 0; i < mValues.length; ++i) {
+                returnVal += "\n    " + mValues[i].toString();
+            }
+        }
+        return returnVal;
+    }
 }
diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java
index 0c30aad..6f91fc0 100644
--- a/core/java/android/animation/PropertyValuesHolder.java
+++ b/core/java/android/animation/PropertyValuesHolder.java
@@ -578,6 +578,11 @@
         return mAnimatedValue;
     }
 
+    @Override
+    public String toString() {
+        return mPropertyName + ": " + mKeyframeSet.toString();
+    }
+
     /**
      * Utility method to derive a setter/getter method name from a property name, where the
      * prefix is typically "set" or "get" and the first letter of the property name is
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 5a8a74a..2e44d6d 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -1207,4 +1207,15 @@
         sPendingAnimations.get().clear();
         sDelayedAnims.get().clear();
     }
+
+    @Override
+    public String toString() {
+        String returnVal = "ValueAnimator@" + Integer.toHexString(hashCode());
+        if (mValues != null) {
+            for (int i = 0; i < mValues.length; ++i) {
+                returnVal += "\n    " + mValues[i].toString();
+            }
+        }
+        return returnVal;
+    }
 }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index b7b0ef58..67e4806 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -349,7 +349,7 @@
  * section for more information on how the lifecycle of a process is tied
  * to the activities it is hosting.  Note that it is important to save
  * persistent data in {@link #onPause} instead of {@link #onSaveInstanceState}
- * because the later is not part of the lifecycle callbacks, so will not
+ * because the latter is not part of the lifecycle callbacks, so will not
  * be called in every situation as described in its documentation.</p>
  *
  * <p class="note">Be aware that these semantics will change slightly between
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index ec4ec89..1c7eb98 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -109,6 +109,7 @@
      *
      * <p>To control this policy, the device admin must have a "set-global-proxy"
      * tag in the "uses-policies" section of its meta-data.
+     * @hide
      */
     public static final int USES_POLICY_SETS_GLOBAL_PROXY = 5;
 
@@ -363,7 +364,7 @@
      * the given policy control.  The possible policy identifier inputs are:
      * {@link #USES_POLICY_LIMIT_PASSWORD}, {@link #USES_POLICY_WATCH_LOGIN},
      * {@link #USES_POLICY_RESET_PASSWORD}, {@link #USES_POLICY_FORCE_LOCK},
-     * {@link #USES_POLICY_WIPE_DATA}, {@link #USES_POLICY_SETS_GLOBAL_PROXY},
+     * {@link #USES_POLICY_WIPE_DATA},
      * {@link #USES_POLICY_EXPIRE_PASSWORD}, {@link #USES_ENCRYPTED_STORAGE}.
      */
     public boolean usesPolicy(int policyIdent) {
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index eccd7c9..29f8caf 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -148,7 +148,7 @@
 
     /**
      * Action periodically sent to a device administrator when the device password
-     * is expiring. 
+     * is expiring.
      *
      * <p>The calling device admin must have requested
      * {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD} to receive
@@ -266,8 +266,8 @@
 
     /**
      * Called periodically when the password is about to expire or has expired.  It will typically
-     * be called on device boot, once per day before the password expires and at the time when it
-     * expires.
+     * be called at these times: on device boot, once per day before the password expires,
+     * and at the time when the password expires.
      *
      * <p>If the password is not updated by the user, this method will continue to be called
      * once per day until the password is changed or the device admin disables password expiration.
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 3f3aa74..440cb54 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -730,8 +730,10 @@
     }
 
     /**
-     * Get the current password expiration timeout for the given admin or the aggregate
-     * of all admins if admin is null.
+     * Get the password expiration timeout for the given admin. The expiration timeout is the
+     * recurring expiration timeout provided in the call to
+     * {@link #setPasswordExpirationTimeout(ComponentName, long)} for the given admin or the
+     * aggregate of all policy administrators if admin is null.
      *
      * @param admin The name of the admin component to check, or null to aggregate all admins.
      * @return The timeout for the given admin or the minimum of all timeouts
@@ -749,7 +751,9 @@
 
     /**
      * Get the current password expiration time for the given admin or an aggregate of
-     * all admins if admin is null.
+     * all admins if admin is null. If the password is expired, this will return the time since
+     * the password expired as a negative number.  If admin is null, then a composite of all
+     * expiration timeouts is returned - which will be the minimum of all timeouts.
      *
      * @param admin The name of the admin component to check, or null to aggregate all admins.
      * @return The password expiration time, in ms.
@@ -1028,6 +1032,7 @@
      * @param exclusionList a list of domains to be excluded from the global proxy.
      * @return returns null if the proxy was successfully set, or a {@link ComponentName}
      *            of the device admin that sets thew proxy otherwise.
+     * @hide
      */
     public ComponentName setGlobalProxy(ComponentName admin, Proxy proxySpec,
             List<String> exclusionList ) {
@@ -1080,6 +1085,7 @@
      * Returns the component name setting the global proxy.
      * @return ComponentName object of the device admin that set the global proxy, or
      *            null if no admin has set the proxy.
+     * @hide
      */
     public ComponentName getGlobalProxyAdmin() {
         if (mService != null) {
diff --git a/core/java/android/app/package.html b/core/java/android/app/package.html
index 5137600..f37f1dc 100644
--- a/core/java/android/app/package.html
+++ b/core/java/android/app/package.html
@@ -32,8 +32,9 @@
 action bar.</p>
 
 <p>For information about using some the classes in this package, see the following
-documents: <a href="{@docRoot}guide/topics/fundamentals/index.html">Application
-Fundamentals</a> (for activities, services, and fragments), <a
+documents: <a href="{@docRoot}guide/topics/fundamentals/activities.html">Activities</a>, <a
+href="{@docRoot}guide/topics/fundamentals/services.html">Services</a>, <a
+href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a>, <a
 href="{@docRoot}guide/topics/ui/actionbar.html">Using the Action Bar</a>, <a
 href="{@docRoot}guide/topics/ui/dialogs.html">Creating Dialogs</a>, and <a
 href="{@docRoot}guide/topics/ui/notifiers/index.html">Notifying the User</a>.</p>
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 659b937..2cb8a86 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -237,10 +237,28 @@
     private BroadcastReceiver mConnectivityIntentReceiver =
             new BroadcastReceiver() {
         public void onReceive(Context context, Intent intent) {
-            sendCheckAlarmsMessage();
+            final boolean wasConnected = mDataConnectionIsConnected;
+
+            // don't use the intent to figure out if network is connected, just check
+            // ConnectivityManager directly.
+            mDataConnectionIsConnected = readDataConnectionState();
+            if (mDataConnectionIsConnected) {
+                if (!wasConnected) {
+                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                        Log.v(TAG, "Reconnection detected: clearing all backoffs");
+                    }
+                    mSyncStorageEngine.clearAllBackoffs(mSyncQueue);
+                }
+                sendCheckAlarmsMessage();
+            }
         }
     };
 
+    private boolean readDataConnectionState() {
+        NetworkInfo networkInfo = getConnectivityManager().getActiveNetworkInfo();
+        return (networkInfo != null) && networkInfo.isConnected();
+    }
+
     private BroadcastReceiver mShutdownIntentReceiver =
             new BroadcastReceiver() {
         public void onReceive(Context context, Intent intent) {
@@ -1411,8 +1429,7 @@
             // to have the most recent value used.
             try {
                 waitUntilReadyToRun();
-                NetworkInfo networkInfo = getConnectivityManager().getActiveNetworkInfo();
-                mDataConnectionIsConnected = (networkInfo != null) && networkInfo.isConnected();
+                mDataConnectionIsConnected = readDataConnectionState();
                 mSyncManagerWakeLock.acquire();
                 // Always do this first so that we be sure that any periodic syncs that
                 // are ready to run have been converted into pending syncs. This allows the
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index c8ca6189..a1e174b 100644
--- a/core/java/android/content/SyncStorageEngine.java
+++ b/core/java/android/content/SyncStorageEngine.java
@@ -525,7 +525,7 @@
         }
     }
 
-    public void clearAllBackoffs() {
+    public void clearAllBackoffs(SyncQueue syncQueue) {
         boolean changed = false;
         synchronized (mAuthorities) {
             for (AccountInfo accountInfo : mAccounts.values()) {
@@ -541,6 +541,7 @@
                         }
                         authorityInfo.backoffTime = NOT_IN_BACKOFF_MODE;
                         authorityInfo.backoffDelay = NOT_IN_BACKOFF_MODE;
+                        syncQueue.onBackoffChanged(accountInfo.account, authorityInfo.authority, 0);
                         changed = true;
                     }
                 }
diff --git a/core/java/android/content/pm/package.html b/core/java/android/content/pm/package.html
index b18adb2..d55f0f7 100644
--- a/core/java/android/content/pm/package.html
+++ b/core/java/android/content/pm/package.html
@@ -5,7 +5,7 @@
 permissions, services, signatures, and providers.</p>
 <p>Most of the information about an application package is defined by its manifest file. For
 more information, see the <a
-href="{@docRoot}guide/topics/manifest/guide/topics/manifest/manifest-intro.html">AndroidManifest.xml
-File</a> documentation.</p>
+href="{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml File</a>
+documentation.</p>
 </BODY>
 </HTML>
\ No newline at end of file
diff --git a/core/java/android/database/AbstractCursor.java b/core/java/android/database/AbstractCursor.java
index bfaeb82..3ffc714 100644
--- a/core/java/android/database/AbstractCursor.java
+++ b/core/java/android/database/AbstractCursor.java
@@ -133,6 +133,8 @@
                 result.getChars(0, result.length(), data, 0);
             }
             buffer.sizeCopied = result.length();
+        } else {
+            buffer.sizeCopied = 0;
         }
     }
     
diff --git a/core/java/android/hardware/IUsbManager.aidl b/core/java/android/hardware/IUsbManager.aidl
index b50b6b9..6c99ab3 100644
--- a/core/java/android/hardware/IUsbManager.aidl
+++ b/core/java/android/hardware/IUsbManager.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware;
 
+import android.hardware.UsbAccessory;
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 
@@ -25,4 +26,6 @@
     /* Returns a list of all currently attached USB devices */
     void getDeviceList(out Bundle devices);
     ParcelFileDescriptor openDevice(String deviceName);
+    UsbAccessory getCurrentAccessory();
+    ParcelFileDescriptor openAccessory();
 }
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index f079e42..dd4096b 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -380,6 +380,58 @@
 
     /*-----------------------------------------------------------------------*/
 
+    private class SensorEventPool {
+        private final int mPoolSize;
+        private final SensorEvent mPool[];
+        private int mNumItemsInPool;
+
+        private SensorEvent createSensorEvent() {
+            // maximal size for all legacy events is 3
+            return new SensorEvent(3);
+        }
+
+        SensorEventPool(int poolSize) {
+            mPoolSize = poolSize;
+            mNumItemsInPool = poolSize;
+            mPool = new SensorEvent[poolSize];
+        }
+
+        SensorEvent getFromPool() {
+            SensorEvent t = null;
+            synchronized (this) {
+                if (mNumItemsInPool > 0) {
+                    // remove the "top" item from the pool
+                    final int index = mPoolSize - mNumItemsInPool;
+                    t = mPool[index];
+                    mPool[index] = null;
+                    mNumItemsInPool--;
+                }
+            }
+            if (t == null) {
+                // the pool was empty or this item was removed from the pool for
+                // the first time. In any case, we need to create a new item.
+                t = createSensorEvent();
+            }
+            return t;
+        }
+
+        void returnToPool(SensorEvent t) {
+            synchronized (this) {
+                // is there space left in the pool?
+                if (mNumItemsInPool < mPoolSize) {
+                    // if so, return the item to the pool
+                    mNumItemsInPool++;
+                    final int index = mPoolSize - mNumItemsInPool;
+                    mPool[index] = t;
+                }
+            }
+        }
+    }
+
+    private static SensorEventPool sPool;
+
+    /*-----------------------------------------------------------------------*/
+
     static private class SensorThread {
 
         Thread mThread;
@@ -485,10 +537,9 @@
     /*-----------------------------------------------------------------------*/
 
     private class ListenerDelegate {
-        final SensorEventListener mSensorEventListener;
+        private final SensorEventListener mSensorEventListener;
         private final ArrayList<Sensor> mSensorList = new ArrayList<Sensor>();
         private final Handler mHandler;
-        private SensorEvent mValuesPool;
         public SparseBooleanArray mSensors = new SparseBooleanArray();
         public SparseBooleanArray mFirstEvent = new SparseBooleanArray();
         public SparseIntArray mSensorAccuracies = new SparseIntArray();
@@ -527,40 +578,12 @@
                     }
 
                     mSensorEventListener.onSensorChanged(t);
-                    returnToPool(t);
+                    sPool.returnToPool(t);
                 }
             };
             addSensor(sensor);
         }
 
-        protected SensorEvent createSensorEvent() {
-            // maximal size for all legacy events is 3
-            return new SensorEvent(3);
-        }
-
-        protected SensorEvent getFromPool() {
-            SensorEvent t = null;
-            synchronized (this) {
-                // remove the array from the pool
-                t = mValuesPool;
-                mValuesPool = null;
-            }
-            if (t == null) {
-                // the pool was empty, we need a new one
-                t = createSensorEvent();
-            }
-            return t;
-        }
-
-        protected void returnToPool(SensorEvent t) {
-            synchronized (this) {
-                // put back the array into the pool
-                if (mValuesPool == null) {
-                    mValuesPool = t;
-                }
-            }
-        }
-
         Object getListener() {
             return mSensorEventListener;
         }
@@ -582,7 +605,7 @@
         }
 
         void onSensorChangedLocked(Sensor sensor, float[] values, long[] timestamp, int accuracy) {
-            SensorEvent t = getFromPool();
+            SensorEvent t = sPool.getFromPool();
             final float[] v = t.values;
             v[0] = values[0];
             v[1] = values[1];
@@ -644,6 +667,7 @@
                     }
                 } while (i>0);
 
+                sPool = new SensorEventPool( sFullSensorsList.size()*2 );
                 sSensorThread = new SensorThread();
             }
         }
@@ -1970,7 +1994,8 @@
         if (rotationVector.length == 4) {
             q0 = rotationVector[3];
         } else {
-            q0 = (float)Math.sqrt(1 - q1*q1 - q2*q2 - q3*q3);
+            q0 = 1 - q1*q1 - q2*q2 - q3*q3;
+            q0 = (q0 > 0) ? (float)Math.sqrt(q0) : 0;
         }
 
         float sq_q1 = 2 * q1 * q1;
diff --git a/core/java/android/hardware/UsbAccessory.aidl b/core/java/android/hardware/UsbAccessory.aidl
new file mode 100644
index 0000000..97a777b
--- /dev/null
+++ b/core/java/android/hardware/UsbAccessory.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware;
+
+parcelable UsbAccessory;
diff --git a/core/java/android/hardware/UsbAccessory.java b/core/java/android/hardware/UsbAccessory.java
new file mode 100644
index 0000000..71672fa
--- /dev/null
+++ b/core/java/android/hardware/UsbAccessory.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+/**
+ * A class representing a USB accessory.
+ */
+public final class UsbAccessory implements Parcelable {
+
+    private static final String TAG = "UsbAccessory";
+
+    private String mManufacturer;
+    private String mModel;
+    private String mType;
+    private String mVersion;
+
+    private UsbAccessory() {
+    }
+
+    /**
+     * UsbAccessory should only be instantiated by UsbService implementation
+     * @hide
+     */
+    public UsbAccessory(String manufacturer, String model, String type, String version) {
+        mManufacturer = manufacturer;
+        mModel = model;
+        mType = type;
+        mVersion = version;
+    }
+
+    /**
+     * UsbAccessory should only be instantiated by UsbService implementation
+     * @hide
+     */
+    public UsbAccessory(String[] strings) {
+        mManufacturer = strings[0];
+        mModel = strings[1];
+        mType = strings[2];
+        mVersion = strings[3];
+    }
+
+    /**
+     * Returns the manufacturer of the accessory.
+     *
+     * @return the accessory manufacturer
+     */
+    public String getManufacturer() {
+        return mManufacturer;
+    }
+
+    /**
+     * Returns the model name of the accessory.
+     *
+     * @return the accessory model
+     */
+    public String getModel() {
+        return mModel;
+    }
+
+    /**
+     * Returns the type of the accessory.
+     *
+     * @return the accessory type
+     */
+    public String getType() {
+        return mType;
+    }
+
+    /**
+     * Returns the version of the accessory.
+     *
+     * @return the accessory version
+     */
+    public String getVersion() {
+        return mVersion;
+    }
+
+    @Override
+    public String toString() {
+        return "UsbAccessory[mManufacturer=" + mManufacturer +
+                            ", mModel=" + mModel +
+                            ", mType=" + mType +
+                            ", mVersion=" + mVersion + "]";
+    }
+
+    public static final Parcelable.Creator<UsbAccessory> CREATOR =
+        new Parcelable.Creator<UsbAccessory>() {
+        public UsbAccessory createFromParcel(Parcel in) {
+            String manufacturer = in.readString();
+            String model = in.readString();
+            String type = in.readString();
+            String version = in.readString();
+            return new UsbAccessory(manufacturer, model, type, version);
+        }
+
+        public UsbAccessory[] newArray(int size) {
+            return new UsbAccessory[size];
+        }
+    };
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeString(mManufacturer);
+        parcel.writeString(mModel);
+        parcel.writeString(mType);
+        parcel.writeString(mVersion);
+   }
+}
diff --git a/core/java/android/hardware/UsbManager.java b/core/java/android/hardware/UsbManager.java
index 8fad210..0f616ff 100644
--- a/core/java/android/hardware/UsbManager.java
+++ b/core/java/android/hardware/UsbManager.java
@@ -24,6 +24,7 @@
 
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.HashMap;
 
@@ -44,11 +45,14 @@
      * Broadcast Action:  A sticky broadcast for USB state change events when in device mode.
      *
      * This is a sticky broadcast for clients that includes USB connected/disconnected state,
-     * the USB configuration that is currently set and a bundle containing name/value pairs
-     * with the names of the functions and a value of either {@link #USB_FUNCTION_ENABLED}
-     * or {@link #USB_FUNCTION_DISABLED}.
-     * Possible USB function names include {@link #USB_FUNCTION_MASS_STORAGE},
-     * {@link #USB_FUNCTION_ADB}, {@link #USB_FUNCTION_RNDIS} and {@link #USB_FUNCTION_MTP}.
+     * <ul>
+     * <li> {@link #USB_CONNECTED} boolean indicating whether USB is connected or disconnected.
+     * <li> {@link #USB_CONFIGURATION} a Bundle containing name/value pairs where the name
+     * is the name of a USB function and the value is either {@link #USB_FUNCTION_ENABLED}
+     * or {@link #USB_FUNCTION_DISABLED}.  The possible function names include
+     * {@link #USB_FUNCTION_MASS_STORAGE}, {@link #USB_FUNCTION_ADB}, {@link #USB_FUNCTION_RNDIS},
+     * {@link #USB_FUNCTION_MTP} and {@link #USB_FUNCTION_ACCESSORY}.
+     * </ul>
      */
     public static final String ACTION_USB_STATE =
             "android.hardware.action.USB_STATE";
@@ -57,6 +61,16 @@
      * Broadcast Action:  A broadcast for USB device attached event.
      *
      * This intent is sent when a USB device is attached to the USB bus when in host mode.
+     * <ul>
+     * <li> {@link #EXTRA_DEVICE_NAME} containing the device's name (String)
+     * <li> {@link #EXTRA_VENDOR_ID} containing the device's vendor ID (Integer)
+     * <li> {@link #EXTRA_PRODUCT_ID} containing the device's product ID (Integer)
+     * <li> {@link #EXTRA_DEVICE_CLASS} } containing the device class (Integer)
+     * <li> {@link #EXTRA_DEVICE_SUBCLASS} containing the device subclass (Integer)
+     * <li> {@link #EXTRA_DEVICE_PROTOCOL} containing the device protocol (Integer)
+     * <li> {@link #EXTRA_DEVICE} containing the {@link android.hardware.UsbDevice}
+     * for the attached device
+     * </ul>
      */
     public static final String ACTION_USB_DEVICE_ATTACHED =
             "android.hardware.action.USB_DEVICE_ATTACHED";
@@ -65,10 +79,41 @@
      * Broadcast Action:  A broadcast for USB device detached event.
      *
      * This intent is sent when a USB device is detached from the USB bus when in host mode.
+     * <ul>
+     * <li> {@link #EXTRA_DEVICE_NAME} containing the device's name (String)
+     * </ul>
      */
     public static final String ACTION_USB_DEVICE_DETACHED =
             "android.hardware.action.USB_DEVICE_DETACHED";
 
+   /**
+     * Broadcast Action:  A broadcast for USB accessory attached event.
+     *
+     * This intent is sent when a USB accessory is attached.
+     * <ul>
+     * <li> {@link #EXTRA_ACCESSORY_MANUFACTURER} containing the accessory's manufacturer (String)
+     * <li> {@link #EXTRA_ACCESSORY_PRODUCT} containing the accessory's product name (String)
+     * <li> {@link #EXTRA_ACCESSORY_TYPE} containing the accessory's type (String)
+     * <li> {@link #EXTRA_ACCESSORY_VERSION} containing the accessory's version (String)
+     * <li> {@link #EXTRA_ACCESSORY} containing the {@link android.hardware.UsbAccessory}
+     * for the attached accessory
+     * </ul>
+     */
+    public static final String ACTION_USB_ACCESSORY_ATTACHED =
+            "android.hardware.action.USB_ACCESSORY_ATTACHED";
+
+   /**
+     * Broadcast Action:  A broadcast for USB accessory detached event.
+     *
+     * This intent is sent when a USB accessory is detached.
+     * <ul>
+      * <li> {@link #EXTRA_ACCESSORY} containing the {@link android.hardware.UsbAccessory}
+     * for the attached accessory that was detached
+     * </ul>
+     */
+    public static final String ACTION_USB_ACCESSORY_DETACHED =
+            "android.hardware.action.USB_ACCESSORY_DETACHED";
+
     /**
      * Boolean extra indicating whether USB is connected or disconnected.
      * Used in extras for the {@link #ACTION_USB_STATE} broadcast.
@@ -106,14 +151,22 @@
     public static final String USB_FUNCTION_MTP = "mtp";
 
     /**
-     * Value indicating that a USB function is enabled.
+     * Name of the Accessory USB function.
      * Used in extras for the {@link #ACTION_USB_STATE} broadcast
      */
+    public static final String USB_FUNCTION_ACCESSORY = "accessory";
+
+    /**
+     * Value indicating that a USB function is enabled.
+     * Used in {@link #USB_CONFIGURATION} extras bundle for the
+     * {@link #ACTION_USB_STATE} broadcast
+     */
     public static final String USB_FUNCTION_ENABLED = "enabled";
 
     /**
      * Value indicating that a USB function is disabled.
-     * Used in extras for the {@link #ACTION_USB_STATE} broadcast
+     * Used in {@link #USB_CONFIGURATION} extras bundle for the
+     * {@link #ACTION_USB_STATE} broadcast
      */
     public static final String USB_FUNCTION_DISABLED = "disabled";
 
@@ -158,8 +211,39 @@
      * Name of extra for {@link #ACTION_USB_DEVICE_ATTACHED} broadcast
      * containing the UsbDevice object for the device.
      */
+
     public static final String EXTRA_DEVICE = "device";
 
+    /**
+     * Name of extra for {@link #ACTION_USB_ACCESSORY_ATTACHED} broadcast
+     * containing the UsbAccessory object for the accessory.
+     */
+    public static final String EXTRA_ACCESSORY = "accessory";
+
+    /**
+     * Name of extra for {@link #ACTION_USB_ACCESSORY_ATTACHED} broadcast
+     * containing the accessory's manufacturer name.
+     */
+    public static final String EXTRA_ACCESSORY_MANUFACTURER = "accessory-manufacturer";
+
+    /**
+     * Name of extra for {@link #ACTION_USB_ACCESSORY_ATTACHED} broadcast
+     * containing the accessory's product name.
+     */
+    public static final String EXTRA_ACCESSORY_PRODUCT = "accessory-product";
+
+    /**
+     * Name of extra for {@link #ACTION_USB_ACCESSORY_ATTACHED} broadcast
+     * containing the accessory's type.
+     */
+    public static final String EXTRA_ACCESSORY_TYPE = "accessory-type";
+
+    /**
+     * Name of extra for {@link #ACTION_USB_ACCESSORY_ATTACHED} broadcast
+     * containing the accessory's version.
+     */
+    public static final String EXTRA_ACCESSORY_VERSION = "accessory-version";
+
     private IUsbManager mService;
 
     /**
@@ -214,6 +298,41 @@
         }
     }
 
+    /**
+     * Returns a list of currently attached USB accessories.
+     * (in the current implementation there can be at most one)
+     *
+     * @return list of USB accessories, or null if none are attached.
+     */
+    public UsbAccessory[] getAccessoryList() {
+        try {
+            UsbAccessory accessory = mService.getCurrentAccessory();
+            if (accessory == null) {
+                return null;
+            } else {
+                return new UsbAccessory[] { accessory };
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in openAccessory" , e);
+            return null;
+        }
+    }
+
+    /**
+     * Opens a file descriptor for reading and writing data to the USB accessory.
+     *
+     * @param accessory the USB accessory to open
+     * @return file descriptor, or null if the accessor could not be opened.
+     */
+    public ParcelFileDescriptor openAccessory(UsbAccessory accessory) {
+        try {
+            return mService.openAccessory();
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in openAccessory" , e);
+            return null;
+        }
+    }
+
     private static File getFunctionEnableFile(String function) {
         return new File("/sys/class/usb_composite/" + function + "/enable");
     }
@@ -245,4 +364,20 @@
             return false;
         }
     }
+
+    /**
+     * Enables or disables a USB function.
+     *
+     * @hide
+     */
+    public static boolean setFunctionEnabled(String function, boolean enable) {
+        try {
+            FileOutputStream stream = new FileOutputStream(getFunctionEnableFile(function));
+            stream.write(enable ? '1' : '0');
+            stream.close();
+            return true;
+        } catch (IOException e) {
+            return false;
+        }
+    }
 }
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 97f96da..b3f3988 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -159,17 +159,7 @@
      */
     public static InetAddress numericToInetAddress(String addrString)
             throws IllegalArgumentException {
-        // TODO - do this for real, using a hidden method on InetAddress that aborts
-        // instead of doing dns step
-        if (!InetAddress.isNumeric(addrString)) {
-            throw new IllegalArgumentException("numericToInetAddress with non numeric: '" +
-                    addrString + "'");
-        }
-        try {
-            return InetAddress.getByName(addrString);
-        } catch (UnknownHostException e) {
-            throw new IllegalArgumentException(e);
-        }
+        return InetAddress.parseNumericAddress(addrString);
     }
 
     /**
diff --git a/core/java/android/net/http/SslCertificate.java b/core/java/android/net/http/SslCertificate.java
index bba11b0..5079c23 100644
--- a/core/java/android/net/http/SslCertificate.java
+++ b/core/java/android/net/http/SslCertificate.java
@@ -110,7 +110,7 @@
      * @param issuedBy The entity that issued this certificate
      * @param validNotBefore The not-before date from the certificate validity period in ISO 8601 format
      * @param validNotAfter The not-after date from the certificate validity period in ISO 8601 format
-     * @deprecated Use {@link #SslCertificate(String, String, Date, Date)}
+     * @deprecated Use {@link #SslCertificate(X509Certificate)}
      */
     @Deprecated
     public SslCertificate(
@@ -124,7 +124,9 @@
      * @param issuedBy The entity that issued this certificate
      * @param validNotBefore The not-before date from the certificate validity period
      * @param validNotAfter The not-after date from the certificate validity period
+     * @deprecated Use {@link #SslCertificate(X509Certificate)}
      */
+    @Deprecated
     public SslCertificate(
             String issuedTo, String issuedBy, Date validNotBefore, Date validNotAfter) {
         mIssuedTo = new DName(issuedTo);
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 622bcdb..8c56fda 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -702,4 +702,28 @@
             return null;
         }
     }
+
+    /**
+     * To change the Secure Element Card Emulation state (ON/OFF)
+     * @hide
+     */
+    public void changeNfcSecureElementCardEmulationState(boolean state)
+    {
+        int seId = 11259375;
+        if(state){
+            /* Enable card emulation */
+            try {
+                sService.selectSecureElement(seId);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Enable card emulation failed", e);
+            }
+        }else{
+            /* Disable card emulation */
+            try {
+                sService.deselectSecureElement();
+            } catch (RemoteException e) {
+                Log.e(TAG, " card emulation failed", e);
+            }
+        }
+    }
 }
diff --git a/core/java/android/nfc/tech/package.html b/core/java/android/nfc/tech/package.html
new file mode 100644
index 0000000..a99828f
--- /dev/null
+++ b/core/java/android/nfc/tech/package.html
@@ -0,0 +1,13 @@
+<HTML>
+<BODY>
+<p>
+These classes provide access to a tag technology's features, which vary by the type
+of tag that is scanned. A scanned tag can support multiple technologies, and you can find
+out what they are by calling {@link android.nfc.Tag#getTechList getTechList()}.</p>
+
+<p>For more information on dealing with tag technologies and handling the ones that you care about, see
+<a href="{@docRoot}guide/topics/nfc/index.html#dispatch">The Tag Dispatch System</a>.
+The {@link android.nfc.tech.TagTechnology} interface provides an overview of the
+supported technologies.</p>
+</BODY>
+</HTML>
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 8700af8..97a216a 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -600,8 +600,9 @@
      * are at different run levels (and thus there's a split caret).
      * @param offset the offset
      * @return true if at a level boundary
+     * @hide
      */
-    private boolean isLevelBoundary(int offset) {
+    public boolean isLevelBoundary(int offset) {
         int line = getLineForOffset(offset);
         Directions dirs = getLineDirections(line);
         if (dirs == DIRS_ALL_LEFT_TO_RIGHT || dirs == DIRS_ALL_RIGHT_TO_LEFT) {
@@ -1148,8 +1149,7 @@
         int bottom = getLineTop(line+1);
 
         float h1 = getPrimaryHorizontal(point) - 0.5f;
-        float h2 = isLevelBoundary(point) ?
-                    getSecondaryHorizontal(point) - 0.5f : h1;
+        float h2 = isLevelBoundary(point) ? getSecondaryHorizontal(point) - 0.5f : h1;
 
         int caps = TextKeyListener.getMetaState(editingBuffer, TextKeyListener.META_SHIFT_ON) |
                    TextKeyListener.getMetaState(editingBuffer, TextKeyListener.META_SELECTING);
diff --git a/core/java/android/text/SpannableStringInternal.java b/core/java/android/text/SpannableStringInternal.java
index 0412285..0825bf3 100644
--- a/core/java/android/text/SpannableStringInternal.java
+++ b/core/java/android/text/SpannableStringInternal.java
@@ -212,6 +212,10 @@
         Object ret1 = null;
 
         for (int i = 0; i < spanCount; i++) {
+            if (kind != null && !kind.isInstance(spans[i])) {
+                continue;
+            }
+
             int spanStart = data[i * COLUMNS + START];
             int spanEnd = data[i * COLUMNS + END];
 
@@ -231,10 +235,6 @@
                 }
             }
 
-            if (kind != null && !kind.isInstance(spans[i])) {
-                continue;
-            }
-
             if (count == 0) {
                 ret1 = spans[i];
                 count++;
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index ac3df79..a4546f0 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -36,8 +36,8 @@
  * float, float, android.graphics.Paint)
  * Canvas.drawText()} directly.</p>
  */
-public class StaticLayout extends Layout
-{
+public class StaticLayout extends Layout {
+
     public StaticLayout(CharSequence source, TextPaint paint,
                         int width,
                         Alignment align, float spacingmult, float spacingadd,
@@ -114,8 +114,8 @@
         mMeasured = MeasuredText.obtain();
     }
 
-    /* package */ void generate(CharSequence source, int bufstart, int bufend,
-                        TextPaint paint, int outerwidth,
+    /* package */ void generate(CharSequence source, int bufStart, int bufEnd,
+                        TextPaint paint, int outerWidth,
                         Alignment align,
                         float spacingmult, float spacingadd,
                         boolean includepad, boolean trackpad,
@@ -126,7 +126,7 @@
         boolean needMultiply = (spacingmult != 1 || spacingadd != 0);
 
         Paint.FontMetricsInt fm = mFontMetricsInt;
-        int[] choosehtv = null;
+        int[] chooseHtv = null;
 
         MeasuredText measured = mMeasured;
 
@@ -137,27 +137,26 @@
         int DEFAULT_DIR = DIR_LEFT_TO_RIGHT; // XXX
 
         int paraEnd;
-        for (int paraStart = bufstart; paraStart <= bufend; paraStart = paraEnd) {
-            paraEnd = TextUtils.indexOf(source, '\n', paraStart, bufend);
+        for (int paraStart = bufStart; paraStart <= bufEnd; paraStart = paraEnd) {
+            paraEnd = TextUtils.indexOf(source, CHAR_NEW_LINE, paraStart, bufEnd);
             if (paraEnd < 0)
-                paraEnd = bufend;
+                paraEnd = bufEnd;
             else
                 paraEnd++;
-            int paraLen = paraEnd - paraStart;
 
             int firstWidthLineLimit = mLineCount + 1;
-            int firstwidth = outerwidth;
-            int restwidth = outerwidth;
+            int firstWidth = outerWidth;
+            int restWidth = outerWidth;
 
-            LineHeightSpan[] chooseht = null;
+            LineHeightSpan[] chooseHt = null;
 
             if (spanned != null) {
                 LeadingMarginSpan[] sp = getParagraphSpans(spanned, paraStart, paraEnd,
                         LeadingMarginSpan.class);
                 for (int i = 0; i < sp.length; i++) {
                     LeadingMarginSpan lms = sp[i];
-                    firstwidth -= sp[i].getLeadingMargin(true);
-                    restwidth -= sp[i].getLeadingMargin(false);
+                    firstWidth -= sp[i].getLeadingMargin(true);
+                    restWidth -= sp[i].getLeadingMargin(false);
                     
                     // LeadingMarginSpan2 is odd.  The count affects all
                     // leading margin spans, not just this particular one,
@@ -166,32 +165,31 @@
                     if (lms instanceof LeadingMarginSpan2) {
                         LeadingMarginSpan2 lms2 = (LeadingMarginSpan2) lms;
                         int lmsFirstLine = getLineForOffset(spanned.getSpanStart(lms2));
-                        firstWidthLineLimit = lmsFirstLine + 
-                            lms2.getLeadingMarginLineCount();
+                        firstWidthLineLimit = lmsFirstLine + lms2.getLeadingMarginLineCount();
                     }
                 }
 
-                chooseht = getParagraphSpans(spanned, paraStart, paraEnd, LineHeightSpan.class);
+                chooseHt = getParagraphSpans(spanned, paraStart, paraEnd, LineHeightSpan.class);
 
-                if (chooseht.length != 0) {
-                    if (choosehtv == null ||
-                        choosehtv.length < chooseht.length) {
-                        choosehtv = new int[ArrayUtils.idealIntArraySize(
-                                            chooseht.length)];
+                if (chooseHt.length != 0) {
+                    if (chooseHtv == null ||
+                        chooseHtv.length < chooseHt.length) {
+                        chooseHtv = new int[ArrayUtils.idealIntArraySize(
+                                            chooseHt.length)];
                     }
 
-                    for (int i = 0; i < chooseht.length; i++) {
-                        int o = spanned.getSpanStart(chooseht[i]);
+                    for (int i = 0; i < chooseHt.length; i++) {
+                        int o = spanned.getSpanStart(chooseHt[i]);
 
                         if (o < paraStart) {
                             // starts in this layout, before the
                             // current paragraph
 
-                            choosehtv[i] = getLineTop(getLineForOffset(o));
+                            chooseHtv[i] = getLineTop(getLineForOffset(o));
                         } else {
                             // starts in this paragraph
 
-                            choosehtv[i] = v;
+                            chooseHtv[i] = v;
                         }
                     }
                 }
@@ -204,20 +202,18 @@
             int dir = measured.mDir;
             boolean easy = measured.mEasy;
 
-            CharSequence sub = source;
-
-            int width = firstwidth;
+            int width = firstWidth;
 
             float w = 0;
             int here = paraStart;
 
             int ok = paraStart;
-            float okwidth = w;
-            int okascent = 0, okdescent = 0, oktop = 0, okbottom = 0;
+            float okWidth = w;
+            int okAscent = 0, okDescent = 0, okTop = 0, okBottom = 0;
 
             int fit = paraStart;
-            float fitwidth = w;
-            int fitascent = 0, fitdescent = 0, fittop = 0, fitbottom = 0;
+            float fitWidth = w;
+            int fitAscent = 0, fitDescent = 0, fitTop = 0, fitBottom = 0;
 
             boolean hasTabOrEmoji = false;
             boolean hasTab = false;
@@ -244,21 +240,18 @@
                 }
 
                 nextSpanStart = spanEnd;
-                int startInPara = spanStart - paraStart;
-                int endInPara = spanEnd - paraStart;
 
-                int fmtop = fm.top;
-                int fmbottom = fm.bottom;
-                int fmascent = fm.ascent;
-                int fmdescent = fm.descent;
+                int fmTop = fm.top;
+                int fmBottom = fm.bottom;
+                int fmAscent = fm.ascent;
+                int fmDescent = fm.descent;
 
                 for (int j = spanStart; j < spanEnd; j++) {
                     char c = chs[j - paraStart];
-                    float before = w;
 
-                    if (c == '\n') {
+                    if (c == CHAR_NEW_LINE) {
                         // intentionally left empty
-                    } else if (c == '\t') {
+                    } else if (c == CHAR_TAB) {
                         if (hasTab == false) {
                             hasTab = true;
                             hasTabOrEmoji = true;
@@ -276,7 +269,8 @@
                         } else {
                             w = TabStops.nextDefaultStop(w, TAB_INCREMENT);
                         }
-                    } else if (c >= 0xD800 && c <= 0xDFFF && j + 1 < spanEnd) {
+                    } else if (c >= CHAR_FIRST_HIGH_SURROGATE && c <= CHAR_LAST_LOW_SURROGATE
+                            && j + 1 < spanEnd) {
                         int emoji = Character.codePointAt(chs, j - paraStart);
 
                         if (emoji >= MIN_EMOJI && emoji <= MAX_EMOJI) {
@@ -311,17 +305,17 @@
                     // Log.e("text", "was " + before + " now " + w + " after " + c + " within " + width);
 
                     if (w <= width) {
-                        fitwidth = w;
+                        fitWidth = w;
                         fit = j + 1;
 
-                        if (fmtop < fittop)
-                            fittop = fmtop;
-                        if (fmascent < fitascent)
-                            fitascent = fmascent;
-                        if (fmdescent > fitdescent)
-                            fitdescent = fmdescent;
-                        if (fmbottom > fitbottom)
-                            fitbottom = fmbottom;
+                        if (fmTop < fitTop)
+                            fitTop = fmTop;
+                        if (fmAscent < fitAscent)
+                            fitAscent = fmAscent;
+                        if (fmDescent > fitDescent)
+                            fitDescent = fmDescent;
+                        if (fmBottom > fitBottom)
+                            fitBottom = fmBottom;
 
                         /*
                          * From the Unicode Line Breaking Algorithm:
@@ -339,25 +333,26 @@
                          * after but not before.
                          */
 
-                        if (c == ' ' || c == '\t' ||
-                            ((c == '.'  || c == ',' || c == ':' || c == ';') &&
+                        if (c == CHAR_SPACE || c == CHAR_TAB ||
+                            ((c == CHAR_DOT || c == CHAR_COMMA ||
+                                    c == CHAR_COLON || c == CHAR_SEMICOLON) &&
                              (j - 1 < here || !Character.isDigit(chs[j - 1 - paraStart])) &&
                              (j + 1 >= spanEnd || !Character.isDigit(chs[j + 1 - paraStart]))) ||
-                            ((c == '/' || c == '-') &&
+                            ((c == CHAR_SLASH || c == CHAR_HYPHEN) &&
                              (j + 1 >= spanEnd || !Character.isDigit(chs[j + 1 - paraStart]))) ||
-                            (c >= FIRST_CJK && isIdeographic(c, true) &&
+                            (c >= CHAR_FIRST_CJK && isIdeographic(c, true) &&
                              j + 1 < spanEnd && isIdeographic(chs[j + 1 - paraStart], false))) {
-                            okwidth = w;
+                            okWidth = w;
                             ok = j + 1;
 
-                            if (fittop < oktop)
-                                oktop = fittop;
-                            if (fitascent < okascent)
-                                okascent = fitascent;
-                            if (fitdescent > okdescent)
-                                okdescent = fitdescent;
-                            if (fitbottom > okbottom)
-                                okbottom = fitbottom;
+                            if (fitTop < okTop)
+                                okTop = fitTop;
+                            if (fitAscent < okAscent)
+                                okAscent = fitAscent;
+                            if (fitDescent > okDescent)
+                                okDescent = fitDescent;
+                            if (fitBottom > okBottom)
+                                okBottom = fitBottom;
                         }
                     } else {
                         if (ellipsize != null) {
@@ -365,56 +360,56 @@
                             if (ok != here) {
                                 // Log.e("text", "output ok " + here + " to " +ok);
 
-                                while (ok < spanEnd && chs[ok - paraStart] == ' ') {
+                                while (ok < spanEnd && chs[ok - paraStart] == CHAR_SPACE) {
                                     ok++;
                                 }
 
                                 v = out(source,
                                         here, ok,
-                                        okascent, okdescent, oktop, okbottom,
+                                        okAscent, okDescent, okTop, okBottom,
                                         v,
-                                        spacingmult, spacingadd, chooseht,
-                                        choosehtv, fm, hasTabOrEmoji,
+                                        spacingmult, spacingadd, chooseHt,
+                                        chooseHtv, fm, hasTabOrEmoji,
                                         needMultiply, paraStart, chdirs, dir, easy,
-                                        ok == bufend, includepad, trackpad,
+                                        ok == bufEnd, includepad, trackpad,
                                         chs, widths, here - paraStart,
-                                        ellipsize, ellipsizedWidth, okwidth,
+                                        ellipsize, ellipsizedWidth, okWidth,
                                         paint);
 
                                 here = ok;
                             } else {
                                 // Act like it fit even though it didn't.
 
-                                fitwidth = w;
+                                fitWidth = w;
                                 here = fit = j + 1;
 
-                                if (fmtop < fittop)
-                                    fittop = fmtop;
-                                if (fmascent < fitascent)
-                                    fitascent = fmascent;
-                                if (fmdescent > fitdescent)
-                                    fitdescent = fmdescent;
-                                if (fmbottom > fitbottom)
-                                    fitbottom = fmbottom;
+                                if (fmTop < fitTop)
+                                    fitTop = fmTop;
+                                if (fmAscent < fitAscent)
+                                    fitAscent = fmAscent;
+                                if (fmDescent > fitDescent)
+                                    fitDescent = fmDescent;
+                                if (fmBottom > fitBottom)
+                                    fitBottom = fmBottom;
                             }
                         } else {
                             if (ok != here) {
                                 // Log.e("text", "output ok " + here + " to " +ok);
 
-                                while (ok < spanEnd && chs[ok - paraStart] == ' ') {
+                                while (ok < spanEnd && chs[ok - paraStart] == CHAR_SPACE) {
                                     ok++;
                                 }
 
                                 v = out(source,
                                         here, ok,
-                                        okascent, okdescent, oktop, okbottom,
+                                        okAscent, okDescent, okTop, okBottom,
                                         v,
-                                        spacingmult, spacingadd, chooseht,
-                                        choosehtv, fm, hasTabOrEmoji,
+                                        spacingmult, spacingadd, chooseHt,
+                                        chooseHtv, fm, hasTabOrEmoji,
                                         needMultiply, paraStart, chdirs, dir, easy,
-                                        ok == bufend, includepad, trackpad,
+                                        ok == bufEnd, includepad, trackpad,
                                         chs, widths, here - paraStart,
-                                        ellipsize, ellipsizedWidth, okwidth,
+                                        ellipsize, ellipsizedWidth, okWidth,
                                         paint);
 
                                 here = ok;
@@ -422,15 +417,15 @@
                                 // Log.e("text", "output fit " + here + " to " +fit);
                                 v = out(source,
                                         here, fit,
-                                        fitascent, fitdescent,
-                                        fittop, fitbottom,
+                                        fitAscent, fitDescent,
+                                        fitTop, fitBottom,
                                         v,
-                                        spacingmult, spacingadd, chooseht,
-                                        choosehtv, fm, hasTabOrEmoji,
+                                        spacingmult, spacingadd, chooseHt,
+                                        chooseHtv, fm, hasTabOrEmoji,
                                         needMultiply, paraStart, chdirs, dir, easy,
-                                        fit == bufend, includepad, trackpad,
+                                        fit == bufEnd, includepad, trackpad,
                                         chs, widths, here - paraStart,
-                                        ellipsize, ellipsizedWidth, fitwidth,
+                                        ellipsize, ellipsizedWidth, fitWidth,
                                         paint);
 
                                 here = fit;
@@ -446,10 +441,10 @@
                                         fm.ascent, fm.descent,
                                         fm.top, fm.bottom,
                                         v,
-                                        spacingmult, spacingadd, chooseht,
-                                        choosehtv, fm, hasTabOrEmoji,
+                                        spacingmult, spacingadd, chooseHt,
+                                        chooseHtv, fm, hasTabOrEmoji,
                                         needMultiply, paraStart, chdirs, dir, easy,
-                                        here + 1 == bufend, includepad,
+                                        here + 1 == bufEnd, includepad,
                                         trackpad,
                                         chs, widths, here - paraStart,
                                         ellipsize, ellipsizedWidth,
@@ -470,65 +465,64 @@
 
                         ok = fit = here;
                         w = 0;
-                        fitascent = fitdescent = fittop = fitbottom = 0;
-                        okascent = okdescent = oktop = okbottom = 0;
+                        fitAscent = fitDescent = fitTop = fitBottom = 0;
+                        okAscent = okDescent = okTop = okBottom = 0;
 
                         if (--firstWidthLineLimit <= 0) {
-                            width = restwidth;
+                            width = restWidth;
                         }
                     }
                 }
             }
 
             if (paraEnd != here) {
-                if ((fittop | fitbottom | fitdescent | fitascent) == 0) {
+                if ((fitTop | fitBottom | fitDescent | fitAscent) == 0) {
                     paint.getFontMetricsInt(fm);
 
-                    fittop = fm.top;
-                    fitbottom = fm.bottom;
-                    fitascent = fm.ascent;
-                    fitdescent = fm.descent;
+                    fitTop = fm.top;
+                    fitBottom = fm.bottom;
+                    fitAscent = fm.ascent;
+                    fitDescent = fm.descent;
                 }
 
                 // Log.e("text", "output rest " + here + " to " + end);
 
                 v = out(source,
-                        here, paraEnd, fitascent, fitdescent,
-                        fittop, fitbottom,
+                        here, paraEnd, fitAscent, fitDescent,
+                        fitTop, fitBottom,
                         v,
-                        spacingmult, spacingadd, chooseht,
-                        choosehtv, fm, hasTabOrEmoji,
+                        spacingmult, spacingadd, chooseHt,
+                        chooseHtv, fm, hasTabOrEmoji,
                         needMultiply, paraStart, chdirs, dir, easy,
-                        paraEnd == bufend, includepad, trackpad,
+                        paraEnd == bufEnd, includepad, trackpad,
                         chs, widths, here - paraStart,
                         ellipsize, ellipsizedWidth, w, paint);
             }
 
             paraStart = paraEnd;
 
-            if (paraEnd == bufend)
+            if (paraEnd == bufEnd)
                 break;
         }
 
-        if (bufend == bufstart || source.charAt(bufend - 1) == '\n') {
-            // Log.e("text", "output last " + bufend);
+        if (bufEnd == bufStart || source.charAt(bufEnd - 1) == CHAR_NEW_LINE) {
+            // Log.e("text", "output last " + bufEnd);
 
             paint.getFontMetricsInt(fm);
 
             v = out(source,
-                    bufend, bufend, fm.ascent, fm.descent,
+                    bufEnd, bufEnd, fm.ascent, fm.descent,
                     fm.top, fm.bottom,
                     v,
                     spacingmult, spacingadd, null,
                     null, fm, false,
-                    needMultiply, bufend, null, DEFAULT_DIR, true,
+                    needMultiply, bufEnd, null, DEFAULT_DIR, true,
                     true, includepad, trackpad,
-                    null, null, bufstart,
+                    null, null, bufStart,
                     ellipsize, ellipsizedWidth, 0, paint);
         }
     }
 
-    private static final char FIRST_CJK = '\u2E80';
     /**
      * Returns true if the specified character is one of those specified
      * as being Ideographic (class ID) by the Unicode Line Breaking Algorithm
@@ -636,14 +630,14 @@
     private int out(CharSequence text, int start, int end,
                       int above, int below, int top, int bottom, int v,
                       float spacingmult, float spacingadd,
-                      LineHeightSpan[] chooseht, int[] choosehtv,
+                      LineHeightSpan[] chooseHt, int[] chooseHtv,
                       Paint.FontMetricsInt fm, boolean hasTabOrEmoji,
                       boolean needMultiply, int pstart, byte[] chdirs,
                       int dir, boolean easy, boolean last,
-                      boolean includepad, boolean trackpad,
-                      char[] chs, float[] widths, int widstart,
-                      TextUtils.TruncateAt ellipsize, float ellipsiswidth,
-                      float textwidth, TextPaint paint) {
+                      boolean includePad, boolean trackPad,
+                      char[] chs, float[] widths, int widthStart,
+                      TextUtils.TruncateAt ellipsize, float ellipsisWidth,
+                      float textWidth, TextPaint paint) {
         int j = mLineCount;
         int off = j * mColumns;
         int want = off + mColumns + TOP;
@@ -662,19 +656,19 @@
             mLineDirections = grow2;
         }
 
-        if (chooseht != null) {
+        if (chooseHt != null) {
             fm.ascent = above;
             fm.descent = below;
             fm.top = top;
             fm.bottom = bottom;
 
-            for (int i = 0; i < chooseht.length; i++) {
-                if (chooseht[i] instanceof LineHeightSpan.WithDensity) {
-                    ((LineHeightSpan.WithDensity) chooseht[i]).
-                        chooseHeight(text, start, end, choosehtv[i], v, fm, paint);
+            for (int i = 0; i < chooseHt.length; i++) {
+                if (chooseHt[i] instanceof LineHeightSpan.WithDensity) {
+                    ((LineHeightSpan.WithDensity) chooseHt[i]).
+                        chooseHeight(text, start, end, chooseHtv[i], v, fm, paint);
 
                 } else {
-                    chooseht[i].chooseHeight(text, start, end, choosehtv[i], v, fm);
+                    chooseHt[i].chooseHeight(text, start, end, chooseHtv[i], v, fm);
                 }
             }
 
@@ -685,20 +679,20 @@
         }
 
         if (j == 0) {
-            if (trackpad) {
+            if (trackPad) {
                 mTopPadding = top - above;
             }
 
-            if (includepad) {
+            if (includePad) {
                 above = top;
             }
         }
         if (last) {
-            if (trackpad) {
+            if (trackPad) {
                 mBottomPadding = bottom - below;
             }
 
-            if (includepad) {
+            if (includePad) {
                 below = bottom;
             }
         }
@@ -708,9 +702,9 @@
         if (needMultiply) {
             double ex = (below - above) * (spacingmult - 1) + spacingadd;
             if (ex >= 0) {
-                extra = (int)(ex + 0.5);
+                extra = (int)(ex + EXTRA_ROUNDING);
             } else {
-                extra = -(int)(-ex + 0.5);
+                extra = -(int)(-ex + EXTRA_ROUNDING);
             }
         } else {
             extra = 0;
@@ -735,45 +729,45 @@
         if (easy) {
             mLineDirections[j] = linedirs;
         } else {
-            mLineDirections[j] = AndroidBidi.directions(dir, chdirs, widstart, chs,
-                    widstart, end - start);
+            mLineDirections[j] = AndroidBidi.directions(dir, chdirs, widthStart, chs,
+                    widthStart, end - start);
         }
 
         // If ellipsize is in marquee mode, do not apply ellipsis on the first line
         if (ellipsize != null && (ellipsize != TextUtils.TruncateAt.MARQUEE || j != 0)) {
-            calculateEllipsis(start, end, widths, widstart,
-                    ellipsiswidth, ellipsize, j,
-                    textwidth, paint);
+            calculateEllipsis(start, end, widths, widthStart,
+                    ellipsisWidth, ellipsize, j,
+                    textWidth, paint);
         }
 
         mLineCount++;
         return v;
     }
 
-    private void calculateEllipsis(int linestart, int lineend,
-                                   float[] widths, int widstart,
+    private void calculateEllipsis(int lineStart, int lineEnd,
+                                   float[] widths, int widthStart,
                                    float avail, TextUtils.TruncateAt where,
-                                   int line, float textwidth, TextPaint paint) {
+                                   int line, float textWidth, TextPaint paint) {
 
-        if (textwidth <= avail) {
+        if (textWidth <= avail) {
             // Everything fits!
             mLines[mColumns * line + ELLIPSIS_START] = 0;
             mLines[mColumns * line + ELLIPSIS_COUNT] = 0;
             return;
         }
 
-        float ellipsiswid = paint.measureText("\u2026");
+        float ellipsisWidth = paint.measureText(HORIZONTAL_ELLIPSIS);
         int ellipsisStart, ellipsisCount;
-        int len = lineend - linestart;
+        int len = lineEnd - lineStart;
 
         if (where == TextUtils.TruncateAt.START) {
             float sum = 0;
             int i;
 
             for (i = len; i >= 0; i--) {
-                float w = widths[i - 1 + linestart - widstart];
+                float w = widths[i - 1 + lineStart - widthStart];
 
-                if (w + sum + ellipsiswid > avail) {
+                if (w + sum + ellipsisWidth > avail) {
                     break;
                 }
 
@@ -787,9 +781,9 @@
             int i;
 
             for (i = 0; i < len; i++) {
-                float w = widths[i + linestart - widstart];
+                float w = widths[i + lineStart - widthStart];
 
-                if (w + sum + ellipsiswid > avail) {
+                if (w + sum + ellipsisWidth > avail) {
                     break;
                 }
 
@@ -802,9 +796,9 @@
             float lsum = 0, rsum = 0;
             int left = 0, right = len;
 
-            float ravail = (avail - ellipsiswid) / 2;
+            float ravail = (avail - ellipsisWidth) / 2;
             for (right = len; right >= 0; right--) {
-                float w = widths[right - 1 + linestart - widstart];
+                float w = widths[right - 1 + lineStart - widthStart];
 
                 if (w + rsum > ravail) {
                     break;
@@ -813,9 +807,9 @@
                 rsum += w;
             }
 
-            float lavail = avail - ellipsiswid - rsum;
+            float lavail = avail - ellipsisWidth - rsum;
             for (left = 0; left < right; left++) {
-                float w = widths[left + linestart - widstart];
+                float w = widths[left + lineStart - widthStart];
 
                 if (w + lsum > lavail) {
                     break;
@@ -968,6 +962,24 @@
 
     private static final int TAB_INCREMENT = 20; // same as Layout, but that's private
 
+    private static final char CHAR_FIRST_CJK = '\u2E80';
+
+    private static final char CHAR_NEW_LINE = '\n';
+    private static final char CHAR_TAB = '\t';
+    private static final char CHAR_SPACE = ' ';
+    private static final char CHAR_DOT = '.';
+    private static final char CHAR_COMMA = ',';
+    private static final char CHAR_COLON = ':';
+    private static final char CHAR_SEMICOLON = ';';
+    private static final char CHAR_SLASH = '/';
+    private static final char CHAR_HYPHEN = '-';
+
+    private static final double EXTRA_ROUNDING = 0.5;
+    private static final String HORIZONTAL_ELLIPSIS = "\u2026"; // this is "..."
+
+    private static final int CHAR_FIRST_HIGH_SURROGATE = 0xD800;
+    private static final int CHAR_LAST_LOW_SURROGATE = 0xDFFF;
+
     /*
      * This is reused across calls to generate()
      */
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 0df464f..48451ba 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2241,6 +2241,8 @@
      * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
      * with this flag set, all visible applications will be able to participate
      * in the drag operation and receive the dragged content.
+     *
+     * @hide
      */
     public static final int DRAG_FLAG_GLOBAL = 1;
 
@@ -6059,9 +6061,7 @@
         if (top != mTop) {
             updateMatrix();
             if (mMatrixIsIdentity) {
-                final ViewParent p = mParent;
-                if (p != null && mAttachInfo != null) {
-                    final Rect r = mAttachInfo.mTmpInvalRect;
+                if (mAttachInfo != null) {
                     int minTop;
                     int yLoc;
                     if (top < mTop) {
@@ -6071,8 +6071,7 @@
                         minTop = mTop;
                         yLoc = 0;
                     }
-                    r.set(0, yLoc, mRight - mLeft, mBottom - minTop);
-                    p.invalidateChild(this, r);
+                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
                 }
             } else {
                 // Double-invalidation is necessary to capture view's old and new areas
@@ -6129,17 +6128,14 @@
         if (bottom != mBottom) {
             updateMatrix();
             if (mMatrixIsIdentity) {
-                final ViewParent p = mParent;
-                if (p != null && mAttachInfo != null) {
-                    final Rect r = mAttachInfo.mTmpInvalRect;
+                if (mAttachInfo != null) {
                     int maxBottom;
                     if (bottom < mBottom) {
                         maxBottom = mBottom;
                     } else {
                         maxBottom = bottom;
                     }
-                    r.set(0, 0, mRight - mLeft, maxBottom - mTop);
-                    p.invalidateChild(this, r);
+                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
                 }
             } else {
                 // Double-invalidation is necessary to capture view's old and new areas
@@ -6187,9 +6183,7 @@
         if (left != mLeft) {
             updateMatrix();
             if (mMatrixIsIdentity) {
-                final ViewParent p = mParent;
-                if (p != null && mAttachInfo != null) {
-                    final Rect r = mAttachInfo.mTmpInvalRect;
+                if (mAttachInfo != null) {
                     int minLeft;
                     int xLoc;
                     if (left < mLeft) {
@@ -6199,8 +6193,7 @@
                         minLeft = mLeft;
                         xLoc = 0;
                     }
-                    r.set(xLoc, 0, mRight - minLeft, mBottom - mTop);
-                    p.invalidateChild(this, r);
+                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
                 }
             } else {
                 // Double-invalidation is necessary to capture view's old and new areas
@@ -6248,17 +6241,14 @@
         if (right != mRight) {
             updateMatrix();
             if (mMatrixIsIdentity) {
-                final ViewParent p = mParent;
-                if (p != null && mAttachInfo != null) {
-                    final Rect r = mAttachInfo.mTmpInvalRect;
+                if (mAttachInfo != null) {
                     int maxRight;
                     if (right < mRight) {
                         maxRight = mRight;
                     } else {
                         maxRight = right;
                     }
-                    r.set(0, 0, maxRight - mLeft, mBottom - mTop);
-                    p.invalidateChild(this, r);
+                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
                 }
             } else {
                 // Double-invalidation is necessary to capture view's old and new areas
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index 0a9386d..25f2229 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -19,9 +19,11 @@
 import android.content.Context;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.Slog;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 
@@ -32,12 +34,17 @@
  * specified subtype of the designated input method directly.
  */
 public final class InputMethodSubtype implements Parcelable {
+    private static final String TAG = InputMethodSubtype.class.getSimpleName();
+    private static final String EXTRA_VALUE_PAIR_SEPARATOR = ",";
+    private static final String EXTRA_VALUE_KEY_VALUE_SEPARATOR = "=";
+
     private final int mSubtypeNameResId;
     private final int mSubtypeIconResId;
     private final String mSubtypeLocale;
     private final String mSubtypeMode;
     private final String mSubtypeExtraValue;
     private final int mSubtypeHashCode;
+    private HashMap<String, String> mExtraValueHashMapCache;
 
     /**
      * Constructor
@@ -106,6 +113,46 @@
         return mSubtypeExtraValue;
     }
 
+    private HashMap<String, String> getExtraValueHashMap() {
+        if (mExtraValueHashMapCache == null) {
+            mExtraValueHashMapCache = new HashMap<String, String>();
+            final String[] pairs = mSubtypeExtraValue.split(EXTRA_VALUE_PAIR_SEPARATOR);
+            final int N = pairs.length;
+            for (int i = 0; i < N; ++i) {
+                final String[] pair = pairs[i].split(EXTRA_VALUE_KEY_VALUE_SEPARATOR);
+                if (pair.length == 1) {
+                    mExtraValueHashMapCache.put(pair[0], null);
+                } else if (pair.length > 1) {
+                    if (pair.length > 2) {
+                        Slog.w(TAG, "ExtraValue has two or more '='s");
+                    }
+                    mExtraValueHashMapCache.put(pair[0], pair[1]);
+                }
+            }
+        }
+        return mExtraValueHashMapCache;
+    }
+
+    /**
+     * The string of ExtraValue in subtype should be defined as follows:
+     * example: key0,key1=value1,key2,key3,key4=value4
+     * @param key the key of extra value
+     * @return the subtype contains specified the extra value
+     */
+    public boolean containsExtraValueKey(String key) {
+        return getExtraValueHashMap().containsKey(key);
+    }
+
+    /**
+     * The string of ExtraValue in subtype should be defined as follows:
+     * example: key0,key1=value1,key2,key3,key4=value4
+     * @param key the key of extra value
+     * @return the value of the specified key
+     */
+    public String getExtraValueOf(String key) {
+        return getExtraValueHashMap().get(key);
+    }
+
     @Override
     public int hashCode() {
         return mSubtypeHashCode;
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 8e09986..fc1240f 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -21,6 +21,8 @@
 import android.content.Context;
 import android.content.res.AssetManager;
 import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
 import android.graphics.Bitmap;
 import android.net.ParseException;
 import android.net.Uri;
@@ -933,7 +935,19 @@
         if (androidResource != null) {
             return new WebResourceResponse(null, null, androidResource);
         }
-        return mCallbackProxy.shouldInterceptRequest(url);
+        WebResourceResponse response = mCallbackProxy.shouldInterceptRequest(url);
+        if (response == null && "browser:incognito".equals(url)) {
+            try {
+                Resources res = mContext.getResources();
+                InputStream ins = res.openRawResource(
+                        com.android.internal.R.raw.incognito_mode_start_page);
+                response = new WebResourceResponse("text/html", "utf8", ins);
+            } catch (NotFoundException ex) {
+                // This shouldn't happen, but try and gracefully handle it jic
+                Log.w(LOGTAG, "Failed opening raw.incognito_mode_start_page", ex);
+            }
+        }
+        return response;
     }
 
     /**
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 0bf0eab..71d6080 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -174,6 +174,7 @@
     private boolean         mBlockNetworkImage = false;
     private boolean         mBlockNetworkLoads;
     private boolean         mJavaScriptEnabled = false;
+    private boolean         mShowVisualIndicator = false;
     private PluginState     mPluginState = PluginState.OFF;
     private boolean         mJavaScriptCanOpenWindowsAutomatically = false;
     private boolean         mUseDoubleTree = false;
@@ -1191,6 +1192,26 @@
     }
 
     /**
+     * Tell the WebView to show the visual indicator
+     * @param flag True if the WebView should show the visual indicator
+     * @hide
+     */
+    public synchronized void setShowVisualIndicator(boolean flag) {
+        if (mShowVisualIndicator != flag) {
+            mShowVisualIndicator = flag;
+            postSync();
+        }
+    }
+
+    /**
+     * @return True if the WebView is showing the visual indicator
+     * @hide
+     */
+    public synchronized boolean getShowVisualIndicator() {
+        return mShowVisualIndicator;
+    }
+
+    /**
      * Tell the WebView to enable plugins.
      * @param flag True if the WebView should load plugins.
      * @deprecated This method has been deprecated in favor of
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 874eac8..69e658f1 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1175,6 +1175,8 @@
 
         mOverscrollDistance = configuration.getScaledOverscrollDistance();
         mOverflingDistance = configuration.getScaledOverflingDistance();
+
+        setScrollBarStyle(super.getScrollBarStyle());
     }
 
     /**
@@ -2087,7 +2089,7 @@
     public void clearView() {
         mContentWidth = 0;
         mContentHeight = 0;
-        setBaseLayer(0, null);
+        setBaseLayer(0, null, false);
         mWebViewCore.sendMessage(EventHub.CLEAR_CONTENT);
     }
 
@@ -3994,14 +3996,14 @@
         }
     }
 
-    void setBaseLayer(int layer, Rect invalRect) {
+    void setBaseLayer(int layer, Rect invalRect, boolean showVisualIndciator) {
         if (mNativeClass == 0)
             return;
         if (invalRect == null) {
             Rect rect = new Rect(0, 0, mContentWidth, mContentHeight);
-            nativeSetBaseLayer(layer, rect);
+            nativeSetBaseLayer(layer, rect, showVisualIndciator);
         } else {
-            nativeSetBaseLayer(layer, invalRect);
+            nativeSetBaseLayer(layer, invalRect, showVisualIndciator);
         }
     }
 
@@ -7203,7 +7205,8 @@
                 case NEW_PICTURE_MSG_ID: {
                     // called for new content
                     final WebViewCore.DrawData draw = (WebViewCore.DrawData) msg.obj;
-                    setBaseLayer(draw.mBaseLayer, draw.mInvalRegion.getBounds());
+                    setBaseLayer(draw.mBaseLayer, draw.mInvalRegion.getBounds(),
+                            getSettings().getShowVisualIndicator());
                     final Point viewSize = draw.mViewSize;
                     WebViewCore.ViewState viewState = draw.mViewState;
                     boolean isPictureAfterFirstLayout = viewState != null;
@@ -8335,7 +8338,8 @@
     private native void     nativeSetFindIsEmpty();
     private native void     nativeSetFindIsUp(boolean isUp);
     private native void     nativeSetHeightCanMeasure(boolean measure);
-    private native void     nativeSetBaseLayer(int layer, Rect invalRect);
+    private native void     nativeSetBaseLayer(int layer, Rect invalRect,
+            boolean showVisualIndciator);
     private native void     nativeShowCursorTimed();
     private native void     nativeReplaceBaseContent(int content);
     private native void     nativeCopyBaseContentToPicture(Picture pict);
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index efbcd58..de624e0 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -791,22 +791,30 @@
         // scaleAll(), we need to post a Runnable to ensure requestLayout().
         // Additionally, only update the text wrap scale if the width changed.
         mWebView.post(new PostScale(w != ow &&
-            !mWebView.getSettings().getUseFixedViewport()));
+            !mWebView.getSettings().getUseFixedViewport(), mInZoomOverview));
     }
 
     private class PostScale implements Runnable {
         final boolean mUpdateTextWrap;
+        // Remember the zoom overview state right after rotation since
+        // it could be changed between the time this callback is initiated and
+        // the time it's actually run.
+        final boolean mInZoomOverviewBeforeSizeChange;
 
-        public PostScale(boolean updateTextWrap) {
+        public PostScale(boolean updateTextWrap, boolean inZoomOverview) {
             mUpdateTextWrap = updateTextWrap;
+            mInZoomOverviewBeforeSizeChange = inZoomOverview;
         }
 
         public void run() {
             if (mWebView.getWebViewCore() != null) {
                 // we always force, in case our height changed, in which case we
                 // still want to send the notification over to webkit.
-                setZoomScale(Math.max(mActualScale, getZoomOverviewScale()),
-                    mUpdateTextWrap, true);
+                // Keep overview mode unchanged when rotating.
+                final float zoomOverviewScale = getZoomOverviewScale();
+                final float newScale = (mInZoomOverviewBeforeSizeChange) ?
+                    zoomOverviewScale : Math.max(mActualScale, zoomOverviewScale); 
+                setZoomScale(newScale, mUpdateTextWrap, true);
                 // update the zoom buttons as the scale can be changed
                 updateZoomPicker();
             }
@@ -846,23 +854,33 @@
     public void onNewPicture(WebViewCore.DrawData drawData) {
         final int viewWidth = mWebView.getViewWidth();
         final boolean zoomOverviewWidthChanged = setupZoomOverviewWidth(drawData, viewWidth);
+        final float newZoomOverviewScale = getZoomOverviewScale();
         WebSettings settings = mWebView.getSettings();
         if (zoomOverviewWidthChanged && settings.isNarrowColumnLayout() &&
             settings.getUseFixedViewport() &&
             (mInitialZoomOverview || mInZoomOverview)) {
-            mTextWrapScale = getReadingLevelScale();
+            // Keep mobile site's text wrap scale unchanged.  For mobile sites,
+            // the text wrap scale is the same as zoom overview scale, which is 1.0f.
+            if (exceedsMinScaleIncrement(mTextWrapScale, 1.0f) ||
+                    exceedsMinScaleIncrement(newZoomOverviewScale, 1.0f)) {
+                mTextWrapScale = getReadingLevelScale();
+            } else {
+                mTextWrapScale = newZoomOverviewScale;
+            }
         }
 
-        final float zoomOverviewScale = getZoomOverviewScale();
         if (!mMinZoomScaleFixed) {
-            mMinZoomScale = zoomOverviewScale;
+            mMinZoomScale = newZoomOverviewScale;
         }
-        // fit the content width to the current view. Ignore the rounding error case.
-        if (!mWebView.drawHistory() && (mInitialZoomOverview || (mInZoomOverview
-                && Math.abs((viewWidth * mInvActualScale) - mZoomOverviewWidth) > 1))) {
+        // fit the content width to the current view for the first new picture
+        // after first layout.
+        boolean scaleHasDiff = exceedsMinScaleIncrement(newZoomOverviewScale, mActualScale);
+        if (!mWebView.drawHistory() && mInitialZoomOverview && scaleHasDiff) {
             mInitialZoomOverview = false;
-            setZoomScale(zoomOverviewScale, !willScaleTriggerZoom(mTextWrapScale) &&
+            setZoomScale(newZoomOverviewScale, !willScaleTriggerZoom(mTextWrapScale) &&
                 !mWebView.getSettings().getUseFixedViewport());
+        } else if (scaleHasDiff) {
+            mInZoomOverview = false;
         }
     }
 
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 27020c5..eb53e56 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -3267,9 +3267,10 @@
             final int scrollY = mScrollY;
             if (!mEdgeGlowTop.isFinished()) {
                 final int restoreCount = canvas.save();
-                final int width = getWidth();
+                final int width = getWidth() - mListPadding.left - mListPadding.right;
 
-                canvas.translate(0, Math.min(0, scrollY + mFirstPositionDistanceGuess));
+                canvas.translate(mListPadding.left,
+                        Math.min(0, scrollY + mFirstPositionDistanceGuess));
                 mEdgeGlowTop.setSize(width, getHeight());
                 if (mEdgeGlowTop.draw(canvas)) {
                     invalidate();
@@ -3278,10 +3279,11 @@
             }
             if (!mEdgeGlowBottom.isFinished()) {
                 final int restoreCount = canvas.save();
-                final int width = getWidth();
+                final int width = getWidth() - mListPadding.left - mListPadding.right;
                 final int height = getHeight();
 
-                canvas.translate(-width, Math.max(height, scrollY + mLastPositionDistanceGuess));
+                canvas.translate(-width + mListPadding.left,
+                        Math.max(height, scrollY + mLastPositionDistanceGuess));
                 canvas.rotate(180, width, 0);
                 mEdgeGlowBottom.setSize(width, height);
                 if (mEdgeGlowBottom.draw(canvas)) {
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 3bdba62..27610b9f 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -92,6 +92,8 @@
     static final boolean DEBUG = false;
     static final String TAG = "AutoCompleteTextView";
 
+    static final int EXPAND_MAX = 3;
+
     private CharSequence mHintText;
     private TextView mHintView;
     private int mHintResource;
@@ -1057,8 +1059,10 @@
         if (!isPopupShowing()) {
             // Make sure the list does not obscure the IME when shown for the first time.
             mPopup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NEEDED);
+            mPopup.setListItemExpandMax(EXPAND_MAX);
         }
         mPopup.show();
+        mPopup.getListView().setOverScrollMode(View.OVER_SCROLL_ALWAYS);
     }
     
     /**
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 13f0890..d75748f 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -1422,11 +1422,11 @@
             final int scrollX = mScrollX;
             if (!mEdgeGlowLeft.isFinished()) {
                 final int restoreCount = canvas.save();
-                final int height = getHeight();
+                final int height = getHeight() - mPaddingTop - mPaddingBottom;
 
                 canvas.rotate(270);
-                canvas.translate(-height, Math.min(0, scrollX));
-                mEdgeGlowLeft.setSize(getHeight(), getWidth());
+                canvas.translate(-height + mPaddingTop, Math.min(0, scrollX));
+                mEdgeGlowLeft.setSize(height, getWidth());
                 if (mEdgeGlowLeft.draw(canvas)) {
                     invalidate();
                 }
@@ -1435,10 +1435,10 @@
             if (!mEdgeGlowRight.isFinished()) {
                 final int restoreCount = canvas.save();
                 final int width = getWidth();
-                final int height = getHeight();
+                final int height = getHeight() - mPaddingTop - mPaddingBottom;
 
                 canvas.rotate(90);
-                canvas.translate(0,
+                canvas.translate(-mPaddingTop,
                         -(Math.max(getScrollRange(), scrollX) + width));
                 mEdgeGlowRight.setSize(height, width);
                 if (mEdgeGlowRight.draw(canvas)) {
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 8811492..5642877 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -65,6 +65,7 @@
 
     private boolean mDropDownAlwaysVisible = false;
     private boolean mForceIgnoreOutsideTouch = false;
+    int mListItemExpandMaximum = Integer.MAX_VALUE;
 
     private View mPromptView;
     private int mPromptPosition = POSITION_PROMPT_ABOVE;
@@ -519,6 +520,7 @@
         int heightSpec = 0;
 
         boolean noInputMethod = isInputMethodNotNeeded();
+        mPopup.setAllowScrollingAnchorParent(!noInputMethod);
 
         if (mPopup.isShowing()) {
             if (mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT) {
@@ -604,6 +606,7 @@
         removePromptView();
         mPopup.setContentView(null);
         mDropDownList = null;
+        mHandler.removeCallbacks(mResizePopupRunnable);
     }
 
     /**
@@ -774,6 +777,16 @@
     }
 
     /**
+     * The maximum number of list items that can be visible and still have
+     * the list expand when touched.
+     *
+     * @param max Max number of items that can be visible and still allow the list to expand.
+     */
+    void setListItemExpandMax(int max) {
+        mListItemExpandMaximum = max;
+    }
+
+    /**
      * Filter key down events. By forwarding key down events to this function,
      * views using non-modal ListPopupWindow can have it handle key selection of items.
      *  
@@ -1209,8 +1222,11 @@
 
     private class ResizePopupRunnable implements Runnable {
         public void run() {
-            mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
-            show();
+            if (mDropDownList != null && mDropDownList.getCount() > mDropDownList.getChildCount() &&
+                    mDropDownList.getChildCount() <= mListItemExpandMaximum) {
+                mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
+                show();
+            }
         }
     }
 
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 439e0ca..53932af 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -90,6 +90,7 @@
     private int mSplitTouchEnabled = -1;
     private boolean mLayoutInScreen;
     private boolean mClipToScreen;
+    private boolean mAllowScrollingAnchorParent = true;
 
     private OnTouchListener mTouchInterceptor;
     
@@ -592,6 +593,16 @@
         mClipToScreen = enabled;
         setClippingEnabled(!enabled);
     }
+
+    /**
+     * Allow PopupWindow to scroll the anchor's parent to provide more room
+     * for the popup. Enabled by default.
+     *
+     * @param enabled True to scroll the anchor's parent when more room is desired by the popup.
+     */
+    void setAllowScrollingAnchorParent(boolean enabled) {
+        mAllowScrollingAnchorParent = enabled;
+    }
     
     /**
      * <p>Indicates whether the popup window supports splitting touches.</p>
@@ -1045,7 +1056,8 @@
         anchor.getWindowVisibleDisplayFrame(displayFrame);
         
         final View root = anchor.getRootView();
-        if (p.y + mPopupHeight > displayFrame.bottom || p.x + mPopupWidth - root.getWidth() > 0) {
+        if (mAllowScrollingAnchorParent && (p.y + mPopupHeight > displayFrame.bottom ||
+                p.x + mPopupWidth - root.getWidth() > 0)) {
             // if the drop down disappears at the bottom of the screen. we try to
             // scroll a parent scrollview or move the drop down back up on top of
             // the edit box
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index d1cfcec..4cc4a27 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -1470,9 +1470,9 @@
             final int scrollY = mScrollY;
             if (!mEdgeGlowTop.isFinished()) {
                 final int restoreCount = canvas.save();
-                final int width = getWidth();
+                final int width = getWidth() - mPaddingLeft - mPaddingRight;
 
-                canvas.translate(0, Math.min(0, scrollY));
+                canvas.translate(mPaddingLeft, Math.min(0, scrollY));
                 mEdgeGlowTop.setSize(width, getHeight());
                 if (mEdgeGlowTop.draw(canvas)) {
                     invalidate();
@@ -1481,10 +1481,11 @@
             }
             if (!mEdgeGlowBottom.isFinished()) {
                 final int restoreCount = canvas.save();
-                final int width = getWidth();
+                final int width = getWidth() - mPaddingLeft - mPaddingRight;
                 final int height = getHeight();
 
-                canvas.translate(-width, Math.max(getScrollRange(), scrollY) + height);
+                canvas.translate(-width + mPaddingLeft,
+                        Math.max(getScrollRange(), scrollY) + height);
                 canvas.rotate(180, width, 0);
                 mEdgeGlowBottom.setSize(width, height);
                 if (mEdgeGlowBottom.draw(canvas)) {
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index f051b77..22edcd0 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -394,7 +394,6 @@
         if (mIconifiedByDefault == iconified) return;
         mIconifiedByDefault = iconified;
         updateViewsVisibility(iconified);
-        setImeVisibility(!iconified);
     }
 
     /**
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 6a09d35..e6cf31e 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -1207,6 +1207,7 @@
         void invalidateGlobalRegion(View v, Rect r) {
             // We need to make a new rect here, so as not to modify the one passed
             globalInvalidateRect.set(r);
+            globalInvalidateRect.union(0, 0, getWidth(), getHeight());
             View p = v;
             if (!(v.getParent() != null && v.getParent() instanceof View)) return;
 
@@ -1223,8 +1224,9 @@
                 firstPass = false;
                 p = (View) p.getParent();
                 parentRect.set(p.getScrollX(), p.getScrollY(),
-                               p.getWidth() + p.getScrollX(), p.getHeight() + p.getScrollY());
-
+                        p.getWidth() + p.getScrollX(), p.getHeight() + p.getScrollY());
+                p.invalidate(globalInvalidateRect.left, globalInvalidateRect.top,
+                        globalInvalidateRect.right, globalInvalidateRect.bottom);
             }
 
             p.invalidate(globalInvalidateRect.left, globalInvalidateRect.top,
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 28b106b..993af31 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -304,15 +304,19 @@
     }
     InputMethodState mInputMethodState;
 
-    int mTextSelectHandleLeftRes;
-    int mTextSelectHandleRightRes;
-    int mTextSelectHandleRes;
-    int mTextEditPasteWindowLayout, mTextEditSidePasteWindowLayout;
-    int mTextEditNoPasteWindowLayout, mTextEditSideNoPasteWindowLayout;
+    private int mTextSelectHandleLeftRes;
+    private int mTextSelectHandleRightRes;
+    private int mTextSelectHandleRes;
+    private int mTextEditPasteWindowLayout, mTextEditSidePasteWindowLayout;
+    private int mTextEditNoPasteWindowLayout, mTextEditSideNoPasteWindowLayout;
 
-    Drawable mSelectHandleLeft;
-    Drawable mSelectHandleRight;
-    Drawable mSelectHandleCenter;
+    private int mCursorDrawableRes;
+    private final Drawable[] mCursorDrawable = new Drawable[2];
+    private int mCursorCount; // Actual current number of used mCursorDrawable: 0, 1 or 2
+
+    private Drawable mSelectHandleLeft;
+    private Drawable mSelectHandleRight;
+    private Drawable mSelectHandleCenter;
 
     private int mLastDownPositionX, mLastDownPositionY;
     private Callback mCustomSelectionActionModeCallback;
@@ -742,6 +746,10 @@
                 }
                 break;
 
+            case com.android.internal.R.styleable.TextView_textCursorDrawable:
+                mCursorDrawableRes = a.getResourceId(attr, 0);
+                break;
+
             case com.android.internal.R.styleable.TextView_textSelectHandleLeft:
                 mTextSelectHandleLeftRes = a.getResourceId(attr, 0);
                 break;
@@ -3770,33 +3778,40 @@
         if (mHighlightPathBogus) {
             invalidateCursor();
         } else {
-            synchronized (sTempRect) {
-                /*
-                 * The reason for this concern about the thickness of the
-                 * cursor and doing the floor/ceil on the coordinates is that
-                 * some EditTexts (notably textfields in the Browser) have
-                 * anti-aliased text where not all the characters are
-                 * necessarily at integer-multiple locations.  This should
-                 * make sure the entire cursor gets invalidated instead of
-                 * sometimes missing half a pixel.
-                 */
+            final int horizontalPadding = getCompoundPaddingLeft();
+            final int verticalPadding = getExtendedPaddingTop() + getVerticalOffset(true);
 
-                float thick = FloatMath.ceil(mTextPaint.getStrokeWidth());
-                if (thick < 1.0f) {
-                    thick = 1.0f;
+            if (mCursorCount == 0) {
+                synchronized (sTempRect) {
+                    /*
+                     * The reason for this concern about the thickness of the
+                     * cursor and doing the floor/ceil on the coordinates is that
+                     * some EditTexts (notably textfields in the Browser) have
+                     * anti-aliased text where not all the characters are
+                     * necessarily at integer-multiple locations.  This should
+                     * make sure the entire cursor gets invalidated instead of
+                     * sometimes missing half a pixel.
+                     */
+                    float thick = FloatMath.ceil(mTextPaint.getStrokeWidth());
+                    if (thick < 1.0f) {
+                        thick = 1.0f;
+                    }
+
+                    thick /= 2.0f;
+
+                    mHighlightPath.computeBounds(sTempRect, false);
+
+                    invalidate((int) FloatMath.floor(horizontalPadding + sTempRect.left - thick),
+                            (int) FloatMath.floor(verticalPadding + sTempRect.top - thick),
+                            (int) FloatMath.ceil(horizontalPadding + sTempRect.right + thick),
+                            (int) FloatMath.ceil(verticalPadding + sTempRect.bottom + thick));
                 }
-
-                thick /= 2;
-
-                mHighlightPath.computeBounds(sTempRect, false);
-
-                int left = getCompoundPaddingLeft();
-                int top = getExtendedPaddingTop() + getVerticalOffset(true);
-
-                invalidate((int) FloatMath.floor(left + sTempRect.left - thick),
-                           (int) FloatMath.floor(top + sTempRect.top - thick),
-                           (int) FloatMath.ceil(left + sTempRect.right + thick),
-                           (int) FloatMath.ceil(top + sTempRect.bottom + thick));
+            } else {
+                for (int i = 0; i < mCursorCount; i++) {
+                    Rect bounds = mCursorDrawable[i].getBounds();
+                    invalidate(bounds.left + horizontalPadding, bounds.top + verticalPadding,
+                            bounds.right + horizontalPadding, bounds.bottom + verticalPadding);
+                }
             }
         }
     }
@@ -3836,13 +3851,23 @@
                     line2 = mLayout.getLineForOffset(last);
 
                 int bottom = mLayout.getLineTop(line2 + 1);
-                int voffset = getVerticalOffset(true);
 
-                int left = getCompoundPaddingLeft() + mScrollX;
-                invalidate(left, top + voffset + getExtendedPaddingTop(),
-                           left + getWidth() - getCompoundPaddingLeft() -
-                           getCompoundPaddingRight(),
-                           bottom + voffset + getExtendedPaddingTop());
+                final int horizontalPadding = getCompoundPaddingLeft();
+                final int verticalPadding = getExtendedPaddingTop() + getVerticalOffset(true);
+                
+                // If used, the cursor drawables can have an arbitrary dimension that can go beyond
+                // the invalidated lines specified above.
+                for (int i = 0; i < mCursorCount; i++) {
+                    Rect bounds = mCursorDrawable[i].getBounds();
+                    top = Math.min(top, bounds.top);
+                    bottom = Math.max(bottom, bounds.bottom);
+                    // Horizontal bounds are already full width, no need to update
+                }
+
+                invalidate(horizontalPadding + mScrollX, top + verticalPadding,
+                        horizontalPadding + mScrollX + getWidth() -
+                        getCompoundPaddingLeft() - getCompoundPaddingRight(),
+                        bottom + verticalPadding);
             }
         }
     }
@@ -4346,6 +4371,7 @@
 
         Path highlight = null;
         int selStart = -1, selEnd = -1;
+        boolean drawCursor = false;
 
         //  If there is no movement method, then there can be no selection.
         //  Check that first and attempt to skip everything having to do with
@@ -4366,6 +4392,7 @@
                         if (mHighlightPathBogus) {
                             mHighlightPath.reset();
                             mLayout.getCursorPath(selStart, mHighlightPath, mText);
+                            updateCursorsPositions();
                             mHighlightPathBogus = false;
                         }
 
@@ -4377,7 +4404,11 @@
                         }
                         mHighlightPaint.setStyle(Paint.Style.STROKE);
 
-                        highlight = mHighlightPath;
+                        if (mCursorCount > 0) {
+                            drawCursor = true;
+                        } else {
+                            highlight = mHighlightPath;
+                        }
                     }
                 } else {
                     if (mHighlightPathBogus) {
@@ -4460,6 +4491,8 @@
             mCorrectionHighlighter.draw(canvas, cursorOffsetVertical);
         }
 
+        if (drawCursor) drawCursor(canvas, cursorOffsetVertical);
+
         layout.draw(canvas, highlight, mHighlightPaint, cursorOffsetVertical);
 
         if (mMarquee != null && mMarquee.shouldDrawGhost()) {
@@ -4478,6 +4511,52 @@
         updateCursorControllerPositions();
     }
 
+    private void updateCursorsPositions() {
+        if (mCursorDrawableRes == 0) return;
+
+        final int offset = getSelectionStart();
+        final int line = mLayout.getLineForOffset(offset);
+        final int top = mLayout.getLineTop(line);
+        final int bottom = mLayout.getLineTop(line + 1);
+
+        mCursorCount = mLayout.isLevelBoundary(offset) ? 2 : 1;
+
+        int middle = bottom;
+        if (mCursorCount == 2) {
+            // Similar to what is done in {@link Layout.#getCursorPath(int, Path, CharSequence)}
+            middle = (top + bottom) >> 1;
+        }
+
+        updateCursorPosition(0, top, middle, mLayout.getPrimaryHorizontal(offset));
+
+        if (mCursorCount == 2) {
+            updateCursorPosition(1, middle, bottom, mLayout.getSecondaryHorizontal(offset));
+        }
+    }
+
+    private void updateCursorPosition(int cursorIndex, int top, int bottom, float horizontal) {
+        if (mCursorDrawable[cursorIndex] == null)
+            mCursorDrawable[cursorIndex] = mContext.getResources().getDrawable(mCursorDrawableRes);
+
+        if (mTempRect == null) mTempRect = new Rect();
+
+        mCursorDrawable[cursorIndex].getPadding(mTempRect);
+        final int width = mCursorDrawable[cursorIndex].getIntrinsicWidth();
+        horizontal = Math.max(0.5f, horizontal - 0.5f);
+        final int left = (int) (horizontal) - mTempRect.left;
+        mCursorDrawable[cursorIndex].setBounds(left, top - mTempRect.top, left + width,
+                bottom + mTempRect.bottom);
+    }
+
+    private void drawCursor(Canvas canvas, int cursorOffsetVertical) {
+        final boolean translate = cursorOffsetVertical != 0;
+        if (translate) canvas.translate(0, cursorOffsetVertical);
+        for (int i = 0; i < mCursorCount; i++) {
+            mCursorDrawable[i].draw(canvas);
+        }
+        if (translate) canvas.translate(0, -cursorOffsetVertical);
+    }
+
     /**
      * Update the positions of the CursorControllers.  Needed by WebTextView,
      * which does not draw.
@@ -8699,7 +8778,7 @@
                 }
                 mDrawable = mSelectHandleLeft;
                 handleWidth = mDrawable.getIntrinsicWidth();
-                mHotspotX = (handleWidth * 3) / 4;
+                mHotspotX = handleWidth * 3.0f / 4.0f;
                 break;
             }
 
@@ -8710,7 +8789,7 @@
                 }
                 mDrawable = mSelectHandleRight;
                 handleWidth = mDrawable.getIntrinsicWidth();
-                mHotspotX = handleWidth / 4;
+                mHotspotX = handleWidth / 4.0f;
                 break;
             }
 
@@ -8722,7 +8801,7 @@
                 }
                 mDrawable = mSelectHandleCenter;
                 handleWidth = mDrawable.getIntrinsicWidth();
-                mHotspotX = handleWidth / 2;
+                mHotspotX = handleWidth / 2.0f;
                 mIsInsertionHandle = true;
                 break;
             }
@@ -8937,8 +9016,8 @@
             final int lineBottom = mLayout.getLineBottom(line);
 
             final Rect bounds = sCursorControllerTempRect;
-            bounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - mHotspotX)
-                + TextView.this.mScrollX;
+            bounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - 0.5f - mHotspotX) +
+                    TextView.this.mScrollX;
             bounds.top = (bottom ? lineBottom : lineTop - mHeight) + TextView.this.mScrollY;
 
             bounds.right = bounds.left + width;
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index 18d1825..029d690 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -43,8 +43,8 @@
  * or 'P' to pick. For a dialog using this view, see
  * {@link android.app.TimePickerDialog}.
  *<p>
- * See the <a href="{@docRoot}
- * resources/tutorials/views/hello-timepicker.html">Time Picker tutorial</a>.
+ * See the <a href="{@docRoot}resources/tutorials/views/hello-timepicker.html">Time Picker
+ * tutorial</a>.
  * </p>
  */
 @Widget
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 1f93eac..6c9e7bb 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -101,8 +101,10 @@
         }
 
         if (anchor != null) {
-            mTreeObserver = anchor.getViewTreeObserver();
-            mTreeObserver.addOnGlobalLayoutListener(this);
+            if (mTreeObserver == null) {
+                mTreeObserver = anchor.getViewTreeObserver();
+                mTreeObserver.addOnGlobalLayoutListener(this);
+            }
             mPopup.setAnchorView(anchor);
         } else {
             return false;
@@ -123,10 +125,10 @@
 
     public void onDismiss() {
         mPopup = null;
-        if (mTreeObserver != null) {
-            mTreeObserver.removeGlobalOnLayoutListener(MenuPopupHelper.this);
-            mTreeObserver = null;
+        if (mTreeObserver != null && mTreeObserver.isAlive()) {
+            mTreeObserver.removeGlobalOnLayoutListener(this);
         }
+        mTreeObserver = null;
     }
 
     public boolean isShowing() {
@@ -134,6 +136,8 @@
     }
 
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+        if (!isShowing()) return;
+
         MenuItem item = null;
         if (mOverflowOnly) {
             item = mMenu.getOverflowItem(position);
@@ -184,13 +188,15 @@
     @Override
     public void onGlobalLayout() {
         if (!isShowing()) {
-            mTreeObserver.removeGlobalOnLayoutListener(this);
+            if (mTreeObserver.isAlive()) {
+                mTreeObserver.removeGlobalOnLayoutListener(this);
+            }
             mTreeObserver = null;
         } else {
             final View anchor = mAnchorView != null ? mAnchorView.get() : null;
-            if (anchor != null && !anchor.isShown()) {
+            if (anchor == null || !anchor.isShown()) {
                 dismiss();
-            } else {
+            } else if (isShowing()) {
                 // Recompute window size and position
                 mPopup.show();
             }
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp
index 58b5686..fc806a5 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_Wifi.cpp
@@ -31,25 +31,6 @@
 
 static jboolean sScanModeActive = false;
 
-//TODO: check general errors in addition to overflow on snprintf
-
-/*
- * The following remembers the jfieldID's of the fields
- * of the DhcpInfo Java object, so that we don't have
- * to look them up every time.
- */
-static struct fieldIds {
-    jclass dhcpInfoClass;
-    jmethodID constructorId;
-    jfieldID ipaddress;
-    jfieldID gateway;
-    jfieldID netmask;
-    jfieldID dns1;
-    jfieldID dns2;
-    jfieldID serverAddress;
-    jfieldID leaseDuration;
-} dhcpInfoFieldIds;
-
 static int doCommand(const char *cmd, char *replybuf, int replybuflen)
 {
     size_t reply_len = replybuflen - 1;
@@ -575,29 +556,6 @@
     return doBooleanCommand(cmdstr, "OK");
 }
 
-
-static jboolean android_net_wifi_doDhcpRequest(JNIEnv* env, jobject clazz, jobject info)
-{
-    jint ipaddr, gateway, mask, dns1, dns2, server, lease;
-    jboolean succeeded = ((jboolean)::do_dhcp_request(&ipaddr, &gateway, &mask,
-                                        &dns1, &dns2, &server, &lease) == 0);
-    if (succeeded && dhcpInfoFieldIds.dhcpInfoClass != NULL) {
-        env->SetIntField(info, dhcpInfoFieldIds.ipaddress, ipaddr);
-        env->SetIntField(info, dhcpInfoFieldIds.gateway, gateway);
-        env->SetIntField(info, dhcpInfoFieldIds.netmask, mask);
-        env->SetIntField(info, dhcpInfoFieldIds.dns1, dns1);
-        env->SetIntField(info, dhcpInfoFieldIds.dns2, dns2);
-        env->SetIntField(info, dhcpInfoFieldIds.serverAddress, server);
-        env->SetIntField(info, dhcpInfoFieldIds.leaseDuration, lease);
-    }
-    return succeeded;
-}
-
-static jstring android_net_wifi_getDhcpError(JNIEnv* env, jobject clazz)
-{
-    return env->NewStringUTF(::get_dhcp_error_string());
-}
-
 // ----------------------------------------------------------------------------
 
 /*
@@ -665,8 +623,6 @@
         (void*) android_net_wifi_setSuspendOptimizationsCommand},
     { "setCountryCodeCommand", "(Ljava/lang/String;)Z",
         (void*) android_net_wifi_setCountryCodeCommand},
-    { "doDhcpRequest", "(Landroid/net/DhcpInfo;)Z", (void*) android_net_wifi_doDhcpRequest },
-    { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_wifi_getDhcpError },
 };
 
 int register_android_net_wifi_WifiManager(JNIEnv* env)
@@ -674,18 +630,6 @@
     jclass wifi = env->FindClass(WIFI_PKG_NAME);
     LOG_FATAL_IF(wifi == NULL, "Unable to find class " WIFI_PKG_NAME);
 
-    dhcpInfoFieldIds.dhcpInfoClass = env->FindClass("android/net/DhcpInfo");
-    if (dhcpInfoFieldIds.dhcpInfoClass != NULL) {
-        dhcpInfoFieldIds.constructorId = env->GetMethodID(dhcpInfoFieldIds.dhcpInfoClass, "<init>", "()V");
-        dhcpInfoFieldIds.ipaddress = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "ipAddress", "I");
-        dhcpInfoFieldIds.gateway = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "gateway", "I");
-        dhcpInfoFieldIds.netmask = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "netmask", "I");
-        dhcpInfoFieldIds.dns1 = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "dns1", "I");
-        dhcpInfoFieldIds.dns2 = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "dns2", "I");
-        dhcpInfoFieldIds.serverAddress = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "serverAddress", "I");
-        dhcpInfoFieldIds.leaseDuration = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "leaseDuration", "I");
-    }
-
     return AndroidRuntime::registerNativeMethods(env,
             WIFI_PKG_NAME, gWifiMethods, NELEM(gWifiMethods));
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 2dc0d31..1df6fe5 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -82,9 +82,9 @@
     <protected-broadcast android:name="android.bluetooth.device.action.PAIRING_REQUEST" />
     <protected-broadcast android:name="android.bluetooth.device.action.PAIRING_CANCEL" />
 
-    <protected-broadcast android:name="android.hardware.action.USB_CONNECTED" />
-    <protected-broadcast android:name="android.hardware.action.USB_DISCONNECTED" />
     <protected-broadcast android:name="android.hardware.action.USB_STATE" />
+    <protected-broadcast android:name="android.hardware.action.USB_ACCESSORY_ATTACHED" />
+    <protected-broadcast android:name="android.hardware.action.USB_ACCESSORY_ATTACHED" />
     <protected-broadcast android:name="android.hardware.action.USB_DEVICE_ATTACHED" />
     <protected-broadcast android:name="android.hardware.action.USB_DEVICE_DETACHED" />
 
@@ -343,7 +343,7 @@
         android:description="@string/permdesc_bluetooth"
         android:label="@string/permlab_bluetooth" />
 
-    <!-- Allows applications to directly communicate over NFC -->
+    <!-- Allows applications to perform I/O operations over NFC -->
     <permission android:name="android.permission.NFC"
         android:permissionGroup="android.permission-group.NETWORK"
         android:protectionLevel="dangerous"
diff --git a/core/res/res/drawable-hdpi/text_cursor_holo_dark.9.png b/core/res/res/drawable-hdpi/text_cursor_holo_dark.9.png
new file mode 100644
index 0000000..b9435b6
--- /dev/null
+++ b/core/res/res/drawable-hdpi/text_cursor_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_cursor_holo_light.9.png b/core/res/res/drawable-hdpi/text_cursor_holo_light.9.png
new file mode 100644
index 0000000..477d820
--- /dev/null
+++ b/core/res/res/drawable-hdpi/text_cursor_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_cursor_holo_dark.9.png b/core/res/res/drawable-mdpi/text_cursor_holo_dark.9.png
new file mode 100644
index 0000000..b9435b6
--- /dev/null
+++ b/core/res/res/drawable-mdpi/text_cursor_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_cursor_holo_light.9.png b/core/res/res/drawable-mdpi/text_cursor_holo_light.9.png
new file mode 100644
index 0000000..477d820
--- /dev/null
+++ b/core/res/res/drawable-mdpi/text_cursor_holo_light.9.png
Binary files differ
diff --git a/core/res/res/raw-es/incognito_mode_start_page.html b/core/res/res/raw-es/incognito_mode_start_page.html
new file mode 100644
index 0000000..43fd37f
--- /dev/null
+++ b/core/res/res/raw-es/incognito_mode_start_page.html
@@ -0,0 +1,26 @@
+<html>
+  <head>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
+    <title>Nueva ventana de incógnito</title>
+  </head>
+  <body>
+    <p><strong>Has entrado en el modo &quot;Navegar de incógnito&quot;</strong>. Las páginas
+    que consultes a través de esta ventana no quedarán registradas en el historial del navegador
+    ni en el historial de búsquedas, y tampoco dejarán otros rastros en el equipo (como cookies)
+    una vez cerrada. Aunque sí quedarán almacenados los archivos que descargues y los marcadores
+    que guardes durante la sesión.</p>
+
+    <p><strong>La función &quot;Navegar de incógnito&quot; no afecta al comportamiento de
+    otros usuarios, servidores o programas. Atención con:</strong></p>
+
+    <ul>
+      <li>sitios web que recopilan o comparten información personal,</li>
+      <li>proveedores de servicios de Internet o trabajadores de estas empresas que
+      supervisan las páginas que visita el usuario,</li>
+      <li>software malicioso que realiza un seguimiento de las teclas que pulsa el usuario a
+      cambio de unos emoticones gratuitos,</li>
+      <li>el seguimiento por parte de detectives privados,</li>
+      <li>personas merodeando cerca de tu equipo.</li>
+    </ul>
+  </body>
+</html>
diff --git a/core/res/res/raw/incognito_mode_start_page.html b/core/res/res/raw/incognito_mode_start_page.html
new file mode 100644
index 0000000..5d7a3fb
--- /dev/null
+++ b/core/res/res/raw/incognito_mode_start_page.html
@@ -0,0 +1,24 @@
+<html>
+  <head>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
+    <title>New incognito window</title>
+  </head>
+  <body>
+    <p><strong>You've gone incognito</strong>. Pages you view in this window
+      won't appear in your browser history or search history, and they won't
+      leave other traces, like cookies, on your device after you close the
+      incognito window. Any files you download or bookmarks you create will be
+      preserved, however.</p>
+
+    <p><strong>Going incognito doesn't affect the behavior of other people,
+      servers, or software. Be wary of:</strong></p>
+
+    <ul>
+      <li>Websites that collect or share information about you</li>
+      <li>Internet service providers or employers that track the pages you visit</li>
+      <li>Malicious software that tracks your keystrokes in exchange for free smileys</li>
+      <li>Surveillance by secret agents</li>
+      <li>People standing behind you</li>
+    </ul>
+  </body>
+</html>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 8802003..6f37dc0 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -778,6 +778,9 @@
     <!-- Color of link text (URLs). -->
     <attr name="textColorLink" format="reference|color" />
 
+    <!-- Reference to a drawable that will be drawn under the insertion cursor. -->
+    <attr name="textCursorDrawable" format="reference" />
+
     <!-- Indicates that the content of a non-editable TextView can be selected.
      Default value is false. EditText content is always selectable. -->
     <attr name="textIsSelectable" format="boolean" />
@@ -2783,6 +2786,9 @@
         <!-- Variation of textEditSidePasteWindowLayout displayed when the clipboard is empty. -->
         <attr name="textEditSideNoPasteWindowLayout" />
 
+        <!-- Reference to a drawable that will be drawn under the insertion cursor. -->
+        <attr name="textCursorDrawable" />
+
         <!-- Indicates that the content of a non-editable text can be selected. -->
         <attr name="textIsSelectable" />
     </declare-styleable>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index aaf071b..4542575 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1642,4 +1642,7 @@
   <!-- Default icon for applications that don't specify an icon. -->
   <public type="mipmap" name="sym_def_app_icon" id="0x010d0000" />
 
+  <!--  Theme attribute used to customize the text insertion cursor -->
+  <!--  Commented out for HC MR1 to prevent an API change -->
+  <!--  <public type="attr" name="textCursorDrawable" id="0x01010362" /> -->
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index d09210e..361bb6c 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1413,10 +1413,10 @@
         to be used while policy is enabled. Only the first device admin
         sets the effective global proxy.</string>
     <!-- Title of policy access to enforce password expiration [CHAR LIMIT=30]-->
-    <string name="policylab_expirePassword">Set password expiration</string>
+    <string name="policylab_expirePassword">Set lock-screen password expiration</string>
     <!-- Description of policy access to enforce password expiration [CHAR LIMIT=110]-->
-    <string name="policydesc_expirePassword">Control how long before lockscreen password needs to be
-    changed</string>
+    <string name="policydesc_expirePassword">Control how frequently the lock-screen password must be
+  changed</string>
     <!-- Title of policy access to require encrypted storage [CHAR LIMIT=30]-->
     <string name="policylab_encryptedStorage">Set storage encryption</string>
     <!-- Description of policy access to require encrypted storage [CHAR LIMIT=110]-->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 5700641..8cc5944 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -426,6 +426,7 @@
         <item name="android:textEditNoPasteWindowLayout">?android:attr/textEditNoPasteWindowLayout</item>
         <item name="android:textEditSidePasteWindowLayout">?android:attr/textEditSidePasteWindowLayout</item>
         <item name="android:textEditSideNoPasteWindowLayout">?android:attr/textEditSideNoPasteWindowLayout</item>
+        <item name="android:textCursorDrawable">?android:attr/textCursorDrawable</item>
     </style>
     
     <style name="Widget.TextView.ListSeparator">
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 6d5b482..927a668 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -180,6 +180,7 @@
         <item name="textEditNoPasteWindowLayout">@android:layout/text_edit_no_paste_window</item>
         <item name="textEditSidePasteWindowLayout">@android:layout/text_edit_side_paste_window</item>
         <item name="textEditSideNoPasteWindowLayout">@android:layout/text_edit_side_no_paste_window</item>
+        <item name="textCursorDrawable">@null</item>
 
         <!-- Widget styles -->
         <item name="absListViewStyle">@android:style/Widget.AbsListView</item>
@@ -906,6 +907,7 @@
         <item name="textSelectHandleRight">@android:drawable/text_select_handle_right</item>
         <item name="textSelectHandle">@android:drawable/text_select_handle_middle</item>
         <item name="textSelectHandleWindowStyle">@android:style/Widget.Holo.TextSelectHandle</item>
+        <item name="textCursorDrawable">@android:drawable/text_cursor_holo_dark</item>
 
         <!-- Widget styles -->
         <item name="absListViewStyle">@android:style/Widget.Holo.AbsListView</item>
@@ -1181,6 +1183,7 @@
         <item name="textSelectHandleRight">@android:drawable/text_select_handle_right</item>
         <item name="textSelectHandle">@android:drawable/text_select_handle_middle</item>
         <item name="textSelectHandleWindowStyle">@android:style/Widget.Holo.TextSelectHandle</item>
+        <item name="textCursorDrawable">@android:drawable/text_cursor_holo_light</item>
 
         <!-- Widget styles -->
         <item name="absListViewStyle">@android:style/Widget.Holo.Light.AbsListView</item>
diff --git a/docs/html/guide/developing/building/building-cmdline.jd b/docs/html/guide/developing/building/building-cmdline.jd
index a5ab07d..81c1178 100644
--- a/docs/html/guide/developing/building/building-cmdline.jd
+++ b/docs/html/guide/developing/building/building-cmdline.jd
@@ -1,4 +1,6 @@
 page.title=Building and Running from the Command Line
+parent.title=Building and Running
+parent.link=index.html
 @jd:body
 
  <div id="qv-wrapper">
diff --git a/docs/html/guide/developing/building/building-eclipse.jd b/docs/html/guide/developing/building/building-eclipse.jd
index 85c82a9..6ebc49e 100644
--- a/docs/html/guide/developing/building/building-eclipse.jd
+++ b/docs/html/guide/developing/building/building-eclipse.jd
@@ -1,4 +1,6 @@
 page.title=Building and Running from Eclipse with ADT
+parent.title=Building and Running
+parent.link=index.html
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/developing/debugging/ddms.jd b/docs/html/guide/developing/debugging/ddms.jd
index 8f5e706..0d47ae5 100644
--- a/docs/html/guide/developing/debugging/ddms.jd
+++ b/docs/html/guide/developing/debugging/ddms.jd
@@ -1,4 +1,6 @@
 page.title=Using DDMS
+parent.title=Debugging
+parent.link=index.html
 @jd:body
 
  <div id="qv-wrapper">
diff --git a/docs/html/guide/developing/debugging/debugging-devtools.jd b/docs/html/guide/developing/debugging/debugging-devtools.jd
index 67605ae..157d62e 100644
--- a/docs/html/guide/developing/debugging/debugging-devtools.jd
+++ b/docs/html/guide/developing/debugging/debugging-devtools.jd
@@ -1,4 +1,6 @@
 page.title=Using the Dev Tools App
+parent.title=Debugging
+parent.link=index.html
 @jd:body
 
 <p>The Dev Tools application is installed by default on all system images included with the SDK,
diff --git a/docs/html/guide/developing/debugging/debugging-log.jd b/docs/html/guide/developing/debugging/debugging-log.jd
index ff73c17..295772d 100644
--- a/docs/html/guide/developing/debugging/debugging-log.jd
+++ b/docs/html/guide/developing/debugging/debugging-log.jd
@@ -1,4 +1,6 @@
 page.title=Reading and Writing Logs
+parent.title=Debugging
+parent.link=index.html
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/developing/debugging/debugging-projects-cmdline.jd b/docs/html/guide/developing/debugging/debugging-projects-cmdline.jd
index 6800a5d..3b5ceab 100644
--- a/docs/html/guide/developing/debugging/debugging-projects-cmdline.jd
+++ b/docs/html/guide/developing/debugging/debugging-projects-cmdline.jd
@@ -1,4 +1,6 @@
-page.title=Debugging from other IDEs
+page.title=Debugging from Other IDEs
+parent.title=Debugging
+parent.link=index.html
 @jd:body
 
 
diff --git a/docs/html/guide/developing/debugging/debugging-projects.jd b/docs/html/guide/developing/debugging/debugging-projects.jd
index deb4341..2283f8b 100644
--- a/docs/html/guide/developing/debugging/debugging-projects.jd
+++ b/docs/html/guide/developing/debugging/debugging-projects.jd
@@ -1,4 +1,6 @@
 page.title=Debugging from Eclipse with ADT
+parent.title=Debugging
+parent.link=index.html
 @jd:body
 
  <div id="qv-wrapper">
diff --git a/docs/html/guide/developing/debugging/debugging-tracing.jd b/docs/html/guide/developing/debugging/debugging-tracing.jd
index 0401966..72f6498 100644
--- a/docs/html/guide/developing/debugging/debugging-tracing.jd
+++ b/docs/html/guide/developing/debugging/debugging-tracing.jd
@@ -1,4 +1,6 @@
 page.title=Profiling with Traceview and dmtracedump
+parent.title=Debugging
+parent.link=index.html
 @jd:body
 
  <div id="qv-wrapper">
diff --git a/docs/html/guide/developing/debugging/debugging-ui.jd b/docs/html/guide/developing/debugging/debugging-ui.jd
index 9b02d34..d2c42d5 100644
--- a/docs/html/guide/developing/debugging/debugging-ui.jd
+++ b/docs/html/guide/developing/debugging/debugging-ui.jd
@@ -1,4 +1,6 @@
 page.title=Debugging and Profiling User Interfaces
+parent.title=Debugging
+parent.link=index.html
 @jd:body
 
  <div id="qv-wrapper">
@@ -7,162 +9,498 @@
 
       <ol>
         <li>
-          <a href="#hierarchyViewer">Debugging and Optimizing User Interfaces with Hierarchy
-          Viewer</a>
-          <ol>
-            <li><a href="#layoutview">Layout View</a></li>
-            <li><a href="#pixelperfect">Pixel Perfect View</a></li>
-          </ol>       
+            <a href="#HierarchyViewer">
+                Debugging and Optimizing User Interfaces with Hierarchy Viewer
+            </a>
+            <ol>
+                <li><a href="#runhv">Running Hierarchy Viewer and choosing a window</a></li>
+                <li><a href="#viewhierarchy">About the View Hierarchy window</a></li>
+                <li><a href="#indiView">Working with an individual View in Tree View</a></li>
+                <li><a href="#hvdebugging">Debugging with View Hierarchy</a></li>
+                <li><a href="#hvoptimize">Optimizing with View Hierarchy</a></li>
+            </ol>
         </li>
-
+        <li>
+            <a href="#pixelperfect">
+                Examining and Designing User Interfaces with Pixel Perfect
+            </a>
+            <ol>
+                <li><a href="#aboutpixelperfect">About the Pixel Perfect window</a></li>
+                <li><a href="#overlays">Working with Pixel Perfect overlays</a></li>
+            </ol>
+        </li>
         <li><a href="#layoutopt">Optimizing Layouts with <code>layoutopt</code></a></li>
       </ol>
     </div>
   </div>
 
-  <p>Sometimes your application's layout can slow down your application. 
-  To help debug issues in your layout, the Android SDK provides the Hierarchy Viewer and 
+  <p>Sometimes your application's layout can slow down your application.
+  To help debug issues in your layout, the Android SDK provides the Hierarchy Viewer and
   <code>layoutopt</code> tools.
   </p>
-  
+
   <p>The Hierarchy Viewer application allows you to debug and optimize your user interface. It
-  provides a visual representation of the layout's View hierarchy (the Layout View) and a magnified
-  inspector of the display (the Pixel Perfect View).</p>
+  provides a visual representation of the layout's View hierarchy (the View Hierarchy window)
+  and a magnified view of the display (the Pixel Perfect window).</p>
 
   <p><code>layoutopt</code> is a command-line tool that helps you optimize the layouts and layout
   hierarchies of your applications. You can run it against your layout files or resource
   directories to quickly check for inefficiencies or other types of problems that could be
   affecting the performance of your application.</p>
 
-  <h2 id="hierarchyViewer">Debugging and Optimizing User Interfaces with Hierarchy Viewer</h2>
+<h2 id="HierarchyViewer">Debugging and Optimizing User Interfaces with Hierarchy Viewer</h2>
 
-  <p>To get the Hierarchy Viewer started:</p>
-
-  <ol>
-    <li>Connect your device or launch an emulator.</li>
-
-    <li>From a terminal, launch <code>hierarchyviewer</code> from the <code>&lt;sdk&gt;/tools/</code>
-    directory.</li>
-
-    <li>In the window that opens, you'll see a list of <strong>Devices</strong>. When a device is
-    selected, a list of currently active <strong>Windows</strong> is displayed on the right. The
-    <em>&lt;Focused Window&gt;</em> is the window currently in the foreground, and also the default
-    window loaded if you do not select another.</li>
-
-    <li>Select the window that you'd like to inspect and click <strong>Load View
-    Hierarchy</strong>. The Layout View will be loaded. You can then load the Pixel Perfect View by
-    clicking the second icon at the bottom-left of the window.</li>
-  </ol>
-
-  <p>If you've navigated to a different window on the device, press <strong>Refresh
-  Windows</strong> to refresh the list of available windows on the right.</p>
-
-
-  <h3 id="layoutview">Layout View</h3>
-
-  <p>The Layout View offers a look at the View layout and properties. It has three views:</p>
-
-  <ul>
-    <li>Tree View: a hierarchy diagram of the Views, on the left.</li>
-
-    <li>Properties View: a list of the selected View's properties, on the top-right.</li>
-
-    <li>Wire-frame View: a wire-frame drawing of the layout, on the bottom-right.</li>
-  </ul><br />
-  <img src="{@docRoot}images/hierarchyviewer-layout.png"
+<h3 id="runhv">Running Hierarchy Viewer and choosing a window</h3>
+<p>
+    To run Hierarchy Viewer, follow these steps:</p>
+<ol>
+    <li>
+        Connect your device or launch an emulator.
+        <p>
+            To preserve security, Hierarchy Viewer can only connect to devices running a
+            developer version of the Android system.
+        </p>
+    </li>
+    <li>
+        If you have not done so already, install the application you want to work with.
+    </li>
+    <li>
+        Run the application, and ensure that its UI is visible.
+    </li>
+    <li>
+        From a terminal, launch <code>hierarchyviewer</code> from the
+        <code>&lt;sdk&gt;/tools/</code>
+        directory.
+    </li>
+    <li>
+        The first window you see displays a list of devices and emulators. To expand the list
+        of Activity objects for a device or emulator, click the arrow on the left. This displays a
+        list of the Activity objects whose UI is currently visible on the device or emulator. The
+        objects are listed by their Android component name. The list includes both your application
+        Activity and system Activity objects. A screenshot of this window appears in
+        figure 1.
+    </li>
+    <li>
+        Select the name of your Activity from the list. You can now look at its view
+        hierarchy using the View Hierarchy window, or look at a magnified image of the UI using
+        the Pixel Perfect window.
+    </li>
+</ol>
+<p>
+    To learn how to use the View Hierarchy window, go to
+    <a href="#viewhierarchy">About the View Hierarchy window</a>. To learn how to use the
+    Pixel Perfect window, go to <a href="#pixelperfect">About the Pixel Perfect window</a>.
+</p>
+<img id="Fig1" src="{@docRoot}images/developing/hv_device_window.png" alt="" height="600"/>
+<p class="img-caption"><strong>Figure 1.</strong> Hierarchy Viewer device window</p>
+<h3 id="viewhierarchy">About the View Hierarchy window</h3>
+<p>
+    The View Hierarchy window displays the View objects that form the UI of the
+    Activity that is running on your device or emulator. You use it to look at individual
+    View objects within the context of the entire View tree. For each View object, the View
+    Hierarchy window also displays rendering performance data.
+</p>
+<p>
+    To see the View Hierarchy window, run Hierarchy Viewer as described in
+    the section <a href="#runhv">Running Hierarchy Viewer and choosing a window</a>. Next, click
+    <strong>View Hierarchy</strong> at the top of the device window.
+</p>
+<p>
+    You should see four panes:
+</p>
+<ul>
+    <li>
+        <strong>Tree View</strong>: The left-hand pane displays the Tree View,
+        a diagram of the Activity object's hierarchy of views. Use Tree View to examine individual
+        View objects and see the relationships between View objects in your UI.
+        <p>
+            To zoom in on the pane, use the slider at the bottom of the pane, or use your mouse
+            scroll wheel. To move around in the pane or reveal View objects that are not currently
+            visible, click and drag the pane.
+        </p>
+        <p>
+            To highlight the nodes in the tree whose class or ID match a search string, enter the
+            string in the <strong>Filter by class or id:</strong> edit box at the bottom of the
+            window. The background of nodes that match the search string will change from gray to
+            bright blue.
+        </p>
+        <p>
+            To save a screenshot of Tree View to a PNG file, click <strong>Save As PNG</strong> at
+            the top of the View Hierarchy window. This displays a dialog in which you can choose
+            a directory and file name.
+        </p>
+        <p>
+            To save a layered screenshot of your device or emulator to an Adobe Photoshop (PSD)
+            file, click <strong>Capture Layers</strong> at the top of the View Hierarchy window.
+            This displays a dialog in which you can choose a directory or file name.
+            Each View in the UI is saved as a separate Photoshop layer.
+        </p>
+        <p>
+            In Photoshop (or similar program that accepts .psd files), you can hide, show or edit a
+            layer independently of others. When you save a layered screenshot, you can examine and
+            modify the image of an individual View object. This helps you experiment with design
+            changes.
+        </p>
+    </li>
+    <li>
+        The upper right-hand pane displays the <strong>Tree Overview</strong>, a smaller map
+        representation of the entire Tree View window. Use Tree Overview to identify the part of the
+        view tree that is being displayed in Tree View.
+        <p>
+            You can also use Tree Overview to move around in the Tree View pane. Click and drag
+            the shaded rectangle over an area to reveal it in Tree View.
+        </p>
+    </li>
+    <li>
+        The middle right-hand pane displays the <strong>Properties View</strong>,
+        a list of the properties for a selected View object. With Properties View, you can
+        examine all the properties without having to look at your application source.
+        <p>
+            The properties are organized by category. To find an individual property, expand
+            a category name by clicking the arrow on its left. This reveals all the properties
+            in that category.
+        </p>
+    </li>
+    <li>
+        The lower right-hand pane displays the <strong>Layout View</strong>,
+        a block representation of the UI. Layout View is another way to navigate through your UI.
+        When you click on a View object in Tree View, its position in the UI is highlighted.
+        Conversely, when you click in an area of Layout View, the View object for that area is
+        highlighted in Tree View.
+        <p>
+            The outline colors of blocks in Layout View provide additional information:
+        </p>
+            <ul>
+                <li>
+                    Bold red: The block represents the the View that is currently selected in
+                    Tree View.
+                </li>
+                <li>
+                    Light red: The block represents the parent of the block outlined in bold red.
+                </li>
+                <li>
+                    White: The block represents a visible View that is not a parent or child of the
+                    View that is currently selected in Tree View.
+                </li>
+            </ul>
+    </li>
+</ul>
+<p>
+    When the UI of the current Activity changes, the View Hierarchy window is not automatically
+    updated. To update it, click <strong>Load View Hierarchy</strong> at the top of the window.
+</p>
+<p>
+    Also, the window is not updated if you switch to a new Activity. To update it, start by
+    clicking the window selection icon in the bottom left-hand corner of the window. This
+    navigates back to the Window Selection window. From this window, click the Android
+    component name of the new Activity and then click <strong>Load View Hierarchy</strong>
+    at the top of the window.
+</p>
+<p>
+    A screenshot of the View Hierarchy window appears in figure 2.
+</p>
+<img id="Fig2" src="{@docRoot}images/developing/hv_view_hierarchy_window.png" alt="" height="600"/>
+<p class="img-caption"><strong>Figure 2.</strong> The View Hierarchy window</p>
+<h3 id="indiView">Working with an individual View in Tree View</h3>
+<p>
+    Each node in Tree View represents a single View. Some information is always visible. Starting
+    at the top of the node, you see the following:
+</p>
+<ol>
+    <li>
+        View class: The View object's class.
+    </li>
+    <li>
+        View object address: A pointer to View object.
+    </li>
+    <li>
+        View object ID: The value of the
+        <code><a href="{@docRoot}guide/topics/resources/layout-resource.html#idvalue">android:id</a>
+        </code> attribute.
+    </li>
+    <li>
+        Performance indicators: A set of three colored dots that indicate the rendering
+        speed of this View relative to other View objects in the tree. The three dots
+        represent (from left to right) the measure, layout, and draw times of the rendering.
+        <p>
+            The colors indicate the following relative performance:
+        </p>
+        <ul>
+            <li>
+                Green: For this part of the render time, this View is in the faster 50% of all
+                the View objects in the tree. For example, a green dot for the measure time means
+                that this View has a faster measure time than 50% of the View objects in the tree.
+            </li>
+            <li>
+                Yellow: For this part of the render time, this View is in the slower 50% of all
+                the View objects in the tree. For example, a yellow dot for the layout time means
+                that this View has a slower layout time than 50% of the View objects in the tree.
+            </li>
+            <li>
+                Red: For this part of the render time, this View is the slowest one in the tree.
+                For example, a red dot for the draw time means that this View takes the most
+                time to draw of all the View objects in the tree.
+            </li>
+        </ul>
+    </li>
+    <li>
+        View index: The zero-based index of the View in its parent View. If it is the only child,
+        this is 0.
+    </li>
+</ol>
+<p>
+    When you select a node, additional information for the View appears in a small window above
+    the node. When you click one of the nodes, you see the following:
+</p>
+<ul>
+    <li>
+        Image: The actual image of the View, as it would appear in the emulator. If the View has
+        children, these are also displayed.
+    </li>
+    <li>
+        View count: The number of View objects represented by this node. This includes the View
+        itself and a count of its children. For example, this value is 4 for a View that has 3
+        children.
+    </li>
+    <li>
+        Render times: The actual measure, layout, and draw times for the View rendering, in
+        milliseconds. These represent the same values as the performance indicators mentioned in
+        the preceding section.
+    </li>
+</ul>
+<p>
+    An annotated screenshot of an individual node in the Tree View window appears in figure 3.
+</p>
+<img id="Fig3" src="{@docRoot}images/developing/hv_treeview_screenshot.png" alt="" height="600"/>
+<p class="img-caption"><strong>Figure 3.</strong> An annotated node in Tree View</p>
+<h3 id="hvdebugging">Debugging with View Hierarchy</h3>
+<p>
+    The View Hierarchy window helps you debug an application by providing a static display
+    of the UI. The display starts with your application's opening screen. As you step through
+    your application, the display remains unchanged until you redraw it by invalidating and
+    then requesting layout for a View.
+</p>
+<p>
+    To redraw a View in the display:
+</p>
+    <ul>
+        <li>
+            Select a View in Tree View. As you move up towards the root of the tree (to the
+            left in the Tree View), you see the highest-level View objects. Redrawing a high-level
+            object usually forces the lower-level objects to redraw as well.
+        </li>
+        <li>
+            Click <strong>Invalidate</strong> at the top of the window. This marks the View as
+            invalid, and schedules it for a redraw at the next point that a layout is requested.
+        </li>
+        <li>
+            Click <strong>Request Layout</strong> to request a layout. The View and its children
+            are redrawn, as well as any other View objects that need to be redrawn.
+        </li>
+    </ul>
+<p>
+    Manually redrawing a View allows you to watch the View object tree and examine the properties of
+    individual View objects one step at a time as you go through breakpoints in your code.
+</p>
+<h3 id="hvoptimize">Optimizing with View Hierarchy</h3>
+<p>
+    View Hierarchy also helps you identify slow render performance. You start by looking at the
+    View nodes with red or yellow performance indicators to identify the slower View objects. As you
+    step through your application, you can judge if a View is consistently slow or slow only in
+    certain circumstances.
+</p>
+<p>
+    Remember that slow performance is not necessarily evidence of a problem, especially for
+    ViewGroup objects. View objects that have more children and more complex View objects render
+    more slowly.
+</p>
+<p>
+    The View Hierarchy window also helps you find performance issues. Just by looking at the
+    performance indicators (the dots) for each View node, you can see which View objects are the
+    slowest to measure, layout, and draw. From that, you can quickly identify the problems you
+    should look at first.
+</p>
+<h2 id="pixelperfect">Examining and Designing User Interfaces with Pixel Perfect</h2>
+<p>
+    Pixel Perfect is a tool for examining pixel properties and laying out UIs from a design drawing.
+</p>
+<h3 id="aboutpixelperfect">About the Pixel Perfect window</h3>
+<p>
+    The Pixel Perfect window displays a magnified image of the screen that is currently
+    visible on the emulator or device. In it, you can examine the properties
+    of individual pixels in the screen image. You can also use the Pixel Perfect window
+    to help you lay out your application UI based on a bitmap design.
+</p>
+<p>
+    To see the Pixel Perfect window, run Hierarchy Viewer, as described in
+    the section <a href="#runhv">Running Hierarchy Viewer and choosing a window</a>. Next, click
+    <strong>Inspect Screenshot</strong> at the top of the device window. The Pixel Perfect window
+    appears.
+</p>
+<p>
+    In it, you see three panes:
+</p>
+<ul>
+    <li>
+        View Object pane: This is a hierarchical list of the View objects that are currently
+        visible on the device or emulator screen, including both the ones in your application and
+        the ones generated by the system. The objects are listed by their View class.
+        To see the class names of a View object's children, expand the View by clicking the
+        arrow to its left. When you click a View, its position is highlighted in the Pixel Perfect
+        pane on the right.
+    </li>
+    <li>
+        Pixel Perfect Loupe pane: This is the magnified screen image. It is overlaid by a grid in
+        which each square represents one pixel. To look at the information for a pixel, click in its
+        square. Its color and X,Y coordinates appear at the bottom of the pane.
+        <p>
+            The magenta crosshair in the pane corresponds to the positioning
+            crosshair in the next pane. It only moves when you move the crosshair in the next pane.
+        </p>
+        <p>
+            To zoom in or out on the image, use the <strong>Zoom</strong> slider at the bottom of
+            the pane, or use your mouse's scroll wheel.
+        </p>
+        <p>
+            When you select a pixel in the Loupe pane, you see the following information at the
+            bottom of the pane:
+        </p>
+        <ul>
+            <li>
+                Pixel swatch: A rectangle filled with the same color as the pixel.
+            </li>
+            <li>
+                HTML color code: The hexadecimal RGB code corresponding to the pixel color
+            </li>
+            <li>
+                RGB color values: A list of the (R), green (G), and blue (B) color values of the
+                pixel color. Each value is in the range 0-255.
+            </li>
+            <li>
+                X and Y coordinates: The pixel's coordinates, in device-specific pixel units.
+                The values are 0-based, with X=0 at the left of the screen and Y=0 at the top.
+            </li>
+        </ul>
+    </li>
+    <li>
+        Pixel Perfect pane: This displays the currently visible screen as it would appear in the
+        emulator.
+        <p>
+            You use the cyan crosshair to do coarse positioning. Drag the crosshair in the image,
+            and the Loupe crosshair will move accordingly. You can also click on a point in the
+            Pixel Perfect pane, and the crosshair will move to that point.
+        </p>
+        <p>
+            The image corresponding to the View object selected in the View Object pane is
+            outlined in a box that indicates the View object's position on the screen. For the
+            selected object, the box is bold red. Sibling and parent View objects have a light
+            red box. View objects that are neither parents nor siblings are in white.
+        </p>
+        <p>
+            The layout box may have other rectangles either inside or outside it, each of which
+            indicates part of the View. A purple or green rectangle indicates the View bounding box.
+            A white or black box inside the layout box represents the <strong>padding</strong>, the
+            defined distance between the View object's content and its bounding box. An outer white
+            or black rectangle represents the <strong>margins</strong>, the distance between the
+            View bounding box and adjacent View objects. The padding and margin boxes are white if
+            the layout background is black, and vice versa.
+        </p>
+        <p>
+            You can save the screen image being displayed in the Pixel Perfect pane as a PNG file.
+            This produces a screenshot of the current screen. To do this, click
+            <strong>Save as PNG</strong> at the top of the window. This displays a dialog,
+            in which you can choose a directory and filename for the file.
+        </p>
+    </li>
+</ul>
+<p>
+    The panes are not automatically refreshed when you change one of the View objects or go to
+    another Activity. To refresh the Pixel Perfect pane and the Loupe pane, click
+    <strong>Refresh Screenshot</strong> at the top of the window. This will change the panes
+    to reflect the current screen image. You still may need to refresh the View Object pane;
+    to do this, click <strong>Refresh Tree</strong> at the top of the window.
+</p>
+<p>
+    To automatically refresh the panes while you are debugging, set
+    <strong>Auto Refresh</strong> at the top of the window, and then set a refresh rate
+    with the <strong>Refresh Rate</strong> slider at the bottom of the Loupe pane.
+</p>
+<h3 id="overlays">Working with Pixel Perfect overlays</h3>
+<p>
+    You often construct a UI based on a design done as a bitmap image. The Pixel Perfect window
+    helps you match up your View layout to a bitmap image by allowing you to load the bitmap as an
+    <strong>overlay</strong> on the screen image.
+</p>
+<p>
+    To use a bitmap image as an overlay:
+</p>
+<ul>
+    <li>
+        Start your application in a device or emulator and navigate to the Activity whose UI you
+        want to work with.
+    </li>
+    <li>
+        Start Hierarchy Viewer and navigate to the Pixel Perfect window.
+    </li>
+    <li>
+        At the top of the window, click <strong>Load Overlay</strong>. A dialog opens, prompting
+        for the image file to load. Load the image file.
+    </li>
+    <li>
+        Pixel Perfect displays the overlay over the screen image in the Pixel Perfect pane. The
+        lower left corner of the bitmap image (X=0, Y=<em>max value</em>) is anchored on the lower
+        leftmost pixel (X=0, Y=<em>max screen</em>) of the screen.
+        <p>
+            By default, the overlay has a 50% transparency, which allows you to see the screen
+            image underneath. You can adjust this with the <strong>Overlay:</strong> slider at the
+            bottom of the Loupe pane.
+        </p>
+        <p>
+            Also by default, the overlay is not displayed in the Loupe pane. To display it,
+            set <strong>Show in Loupe</strong> at the top of the window.
+        </p>
+    </li>
+</ul>
+<p>
+    The overlay is not saved as part of the screenshot when you save the screen image as a PNG
+    file.
+</p>
+<p>
+    A screenshot of the Pixel Perfect window appears in figure 4.
+</p>
+<img id="Fig4" src="{@docRoot}images/developing/hv_pixelperfect.png"
         alt=""
-        height="509"
-        width="700" />
-  <p class="img-caption"><strong>Figure 1.</strong> Screenshot of Hierarchy Viewer</p>
+        height="600"/>
+<p class="img-caption"><strong>Figure 4.</strong> The Pixel Perfect window</p>
+<h2 id="layoutopt">Optimizing layouts with layoutopt</h2>
+<p>
+    The <code>layoutopt</code> tool lets you analyze the XML files that define your
+    application's UI to find inefficiencies in the view hierarchy.</p>
 
-  <p>Select a node in the Tree View to display the properties of that element in the Properties
-  View. When a node is selected, the Wire-frame View also indicates the bounds of the element with
-  a red rectangle. Double click a node in the tree (or select it, and click <strong>Display
-  View</strong>) to open a new window with a rendering of that element.</p>
-
-  <p>The Layout View includes a couple other helpful features for debugging your layout:
-  <strong>Invalidate</strong> and <strong>Request Layout</strong>. These buttons execute the
-  respective View calls, {@link android.view.View#invalidate()} and {@link
-  android.view.View#requestLayout()}, on the View element currently selected in the tree. Calling
-  these methods on any View can be very useful when simultaneously running a debugger on your
-  application.</p>
-
-  <p>The Tree View can be resized by adjusting the zoom slider, below the diagram. The number of
-  View elements in the window is also given here. You should look for ways to minimize the number
-  of Views. The fewer View elements there are in a window, the faster it will perform.</p>
-
-  <p>If you interact with the device and change the focused View, the diagram will not
-  automatically refresh. You must reload the Layout View by clicking <strong>Load View
-  Hierarchy</strong>.</p>
-
-  <h3 id="pixelperfect">Pixel Perfect View</h3>
-
-  <p>The Pixel Perfect View provides a magnified look at the current device window. It helps you
-  design your UI better by giving you a closer look at your UI's image quality, alignment, and other
-  aesthetic qualities. It has three views:</p>
-
-  <ul>
-    <li>Explorer View: shows the View hierarchy as a list, on the left.</li>
-
-    <li>Normal View: a normal view of the device window, in the middle.</li>
-
-    <li>Loupe View: a magnified, pixel-grid view of the device window, on the right.</li>
-  </ul><br />
-  <img src="{@docRoot}images/hierarchyviewer-pixelperfect.png"
-        alt=""
-        height="509"
-        width="700" />
-
-  <p>Click on an element in the Explorer View and a "layout box" will be drawn in the Normal View
-  to indicate the layout position of that element. The layout box uses multiple rectangles, to
-  indicate the normal bounds, the padding and the margin (as needed). The purple or green rectangle
-  indicates the normal bounds of the element (the height and width). The inner white or black
-  rectangle indicates the content bounds, when padding is present. A black or white rectangle
-  outside the normal purple/green rectangle indicates any present margins. (There are two colors
-  for each rectangle, in order to provide the best contrast based on the colors currently in the
-  background.)</p>
-
-  <p>A very handy feature for designing your UI is the ability to overlay an image in the Normal
-  and Loupe Views. For example, you might have a mock-up image of how you'd like to layout your
-  interface. By selecting <strong>Load...</strong> from the controls in the Normal View, you can
-  choose the image from your computer and it will be placed atop the preview. Your chosen image
-  will anchor at the bottom left corner of the screen. You can then adjust the opacity of the
-  overlay and begin fine-tuning your layout to match the mock-up.</p>
-
-  <p>The Normal View and Loupe View refresh at regular intervals (5 seconds by default), but the
-  Explorer View does not. If you navigate away and focus on a different View, then you should
-  refresh the Explorer's hierarchy by clicking <strong>Load View Hierarchy</strong>. This is even
-  true when you're working in a window that holds multiple Views that are not always visible. If
-  you do not, although the previews will refresh, clicking a View in the Explorer will not provide
-  the proper layout box in the Normal View, because the hierarchy believes you are still focused on
-  the prior View.</p>
-
-  <p>Optional controls include:</p>
-
-  <ul>
-    <li><strong>Overlay</strong>: Load an overlay image onto the view and adjust its opacity.</li>
-
-    <li><strong>Refresh Rate</strong>: Adjust how often the Normal and Loupe View refresh their
-    display.</li>
-
-    <li><strong>Zoom</strong>: Adjust the zoom level of the Loupe View.</li>
-  </ul>
-
-  <h2 id="layoutopt">Optimizing layouts with layoutopt</h2>
-  <p>The <code>layoutopt</code> tool lets you analyze the XML files that represent your application's layout
-  and finds ineffiencies in the view hierarchy.</p>
-  
-  <p>To run the tool, open a terminal and launch <code>layoutopt &lt;resources&gt;</code> from your
-  SDK <code>tools/</code> directory. In the command, supply a list of uncompiled resource xml files
-  or directories that you want to analyze.</p>
-
-  <p>When run, the tool loads the specified XML files and analyzes their layout structures and
-  hierarchies according to a set of predefined rules. If it detects issues, it outputs information
-  about the issues, giving filename, line numbers, description of issue, and for some types of
-  issues a suggested resolution.</p>
-
-  <p>Here's an example of the output:</p>
-  <pre>
+<p>
+    To run the tool, open a terminal and launch <code>layoutopt &lt;xmlfiles&gt;</code>
+    from your SDK <code>tools/</code> directory. The &lt;xmlfiles&gt; argument is a space-
+    delimited list of resources you want to analyze, either uncompiled resource xml files or
+    directories of such files.
+</p>
+<p>
+    The tool loads the specified XML files and analyzes their definitions and
+    hierarchies according to a set of predefined rules. For every issue it detects, it
+    displays the following information:
+</p>
+<ul>
+    <li>
+        The filename in which the issue was detected.
+    </li>
+    <li>
+        The line number for the issue.
+    </li>
+    <li>
+        A description of the issue, and for some types of issues it also suggests a resolution.
+    </li>
+</ul>
+<p>The following is a sample of the output from the tool:</p>
+<pre>
 $ layoutopt samples/
 samples/compound.xml
    7:23 The root-level &lt;FrameLayout/&gt; can be replaced with &lt;merge/&gt;
@@ -188,15 +526,3 @@
    7:19 The root-level &lt;FrameLayout/&gt; can be replaced with &lt;merge/&gt;
    11:17 This LinearLayout layout or its FrameLayout parent is useless
 </pre>
-
-<p>
-For more information on running the tool, see the
-<a href="${@docRoot}guide/developing/debugging/debugging-ui.html#layoutopt">layoutopt</a> reference.</p>
-  
-    
-
-
-
-
-
-
diff --git a/docs/html/guide/developing/devices/emulator.jd b/docs/html/guide/developing/devices/emulator.jd
index f61a437..fe00531 100644
--- a/docs/html/guide/developing/devices/emulator.jd
+++ b/docs/html/guide/developing/devices/emulator.jd
@@ -1,4 +1,6 @@
 page.title=Using the Android Emulator
+parent.title=Managing Virtual Devices
+parent.link=index.html
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/developing/devices/managing-avds-cmdline.jd b/docs/html/guide/developing/devices/managing-avds-cmdline.jd
index 02fd750..6feeeb6 100644
--- a/docs/html/guide/developing/devices/managing-avds-cmdline.jd
+++ b/docs/html/guide/developing/devices/managing-avds-cmdline.jd
@@ -1,4 +1,6 @@
 page.title=Managing AVDs from the Command Line
+parent.title=Managing Virtual Devices
+parent.link=index.html
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/developing/devices/managing-avds.jd b/docs/html/guide/developing/devices/managing-avds.jd
index 2913ac9..1817ce7 100644
--- a/docs/html/guide/developing/devices/managing-avds.jd
+++ b/docs/html/guide/developing/devices/managing-avds.jd
@@ -1,4 +1,6 @@
 page.title=Managing AVDs with AVD Manager
+parent.title=Managing Virtual Devices
+parent.link=index.html
 @jd:body
 
   <div id="qv-wrapper">
diff --git a/docs/html/guide/developing/projects/projects-cmdline.jd b/docs/html/guide/developing/projects/projects-cmdline.jd
index b12864e..7c3e40e 100644
--- a/docs/html/guide/developing/projects/projects-cmdline.jd
+++ b/docs/html/guide/developing/projects/projects-cmdline.jd
@@ -1,4 +1,6 @@
 page.title=Managing Projects from the Command Line
+parent.title=Managing Projects
+parent.link=index.html
 @jd:body
 
   <div id="qv-wrapper">
diff --git a/docs/html/guide/developing/projects/projects-eclipse.jd b/docs/html/guide/developing/projects/projects-eclipse.jd
index aa49663..40c17ed 100644
--- a/docs/html/guide/developing/projects/projects-eclipse.jd
+++ b/docs/html/guide/developing/projects/projects-eclipse.jd
@@ -1,4 +1,6 @@
 page.title=Managing Projects from Eclipse with ADT
+parent.title=Managing Projects
+parent.link=index.html
 @jd:body
 
  <div id="qv-wrapper">
diff --git a/docs/html/guide/developing/testing/testing_eclipse.jd b/docs/html/guide/developing/testing/testing_eclipse.jd
index 2a5b771..4e9ecca 100644
--- a/docs/html/guide/developing/testing/testing_eclipse.jd
+++ b/docs/html/guide/developing/testing/testing_eclipse.jd
@@ -1,4 +1,6 @@
 page.title=Testing from Eclipse with ADT
+parent.title=Testing
+parent.link=index.html
 @jd:body
 <div id="qv-wrapper">
     <div id="qv">
@@ -16,8 +18,8 @@
     basic processes for creating and running applications with ADT, as described in
     <a href="{@docRoot}guide/developing/projects/projects-eclipse.html">Managing Projects from
 Eclipse</a>
-    and <a href="guide/developing/building/building-eclipse.html">Building and Running from
-Eclipse</a>.
+    and <a href="{@docRoot}guide/developing/building/building-eclipse.html">Building and Running
+from Eclipse</a>.
     You may also want to read
     <a href="{@docRoot}guide/topics/testing/testing_android.html">Testing Fundamentals</a>,
     which provides an overview of the Android testing framework.
diff --git a/docs/html/guide/developing/testing/testing_otheride.jd b/docs/html/guide/developing/testing/testing_otheride.jd
index 50cc4fa..93af979 100644
--- a/docs/html/guide/developing/testing/testing_otheride.jd
+++ b/docs/html/guide/developing/testing/testing_otheride.jd
@@ -1,4 +1,6 @@
 page.title=Testing from Other IDEs
+parent.title=Testing
+parent.link=index.html
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/developing/tools/MonkeyDevice.jd b/docs/html/guide/developing/tools/MonkeyDevice.jd
index 34bbba9..abcf8fd 100644
--- a/docs/html/guide/developing/tools/MonkeyDevice.jd
+++ b/docs/html/guide/developing/tools/MonkeyDevice.jd
@@ -1,4 +1,6 @@
 page.title=MonkeyDevice
+parent.title=monkeyrunner
+parent.link=index.html
 @jd:body
 <style>
     h4.jd-details-title {background-color: #DEE8F1;}
diff --git a/docs/html/guide/developing/tools/MonkeyImage.jd b/docs/html/guide/developing/tools/MonkeyImage.jd
index ae85cb5..2efc373 100644
--- a/docs/html/guide/developing/tools/MonkeyImage.jd
+++ b/docs/html/guide/developing/tools/MonkeyImage.jd
@@ -1,4 +1,6 @@
 page.title=MonkeyImage
+parent.title=monkeyrunner
+parent.link=index.html
 @jd:body
 <style>
     h4.jd-details-title {background-color: #DEE8F1;}
diff --git a/docs/html/guide/developing/tools/MonkeyRunner.jd b/docs/html/guide/developing/tools/MonkeyRunner.jd
index 871e06d..ea8d69e 100644
--- a/docs/html/guide/developing/tools/MonkeyRunner.jd
+++ b/docs/html/guide/developing/tools/MonkeyRunner.jd
@@ -1,5 +1,8 @@
 page.title=MonkeyRunner
+parent.title=monkeyrunner
+parent.link=index.html
 @jd:body
+
 <style>
     h4.jd-details-title {background-color: #DEE8F1;}
 </style>
diff --git a/docs/html/guide/developing/tools/adb.jd b/docs/html/guide/developing/tools/adb.jd
index 26839a1..e891ccd 100644
--- a/docs/html/guide/developing/tools/adb.jd
+++ b/docs/html/guide/developing/tools/adb.jd
@@ -1,4 +1,6 @@
 page.title=Android Debug Bridge
+parent.title=Tools
+parent.link=index.html
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/developing/tools/android.jd b/docs/html/guide/developing/tools/android.jd
index 15cf8e0..a67012f 100644
--- a/docs/html/guide/developing/tools/android.jd
+++ b/docs/html/guide/developing/tools/android.jd
@@ -1,4 +1,6 @@
 page.title=android
+parent.title=Tools
+parent.link=index.html
 @jd:body
 
 <p>{@code android} is an important development tool that lets you:</p>
diff --git a/docs/html/guide/developing/tools/bmgr.jd b/docs/html/guide/developing/tools/bmgr.jd
index 57deb25..d63dcf2 100644
--- a/docs/html/guide/developing/tools/bmgr.jd
+++ b/docs/html/guide/developing/tools/bmgr.jd
@@ -1,4 +1,6 @@
 page.title=bmgr
+parent.title=Tools
+parent.link=index.html
 @jd:body
 
 <!-- quickview box content here -->
diff --git a/docs/html/guide/developing/tools/dmtracedump.jd b/docs/html/guide/developing/tools/dmtracedump.jd
index 492a049..cb9ad26 100644
--- a/docs/html/guide/developing/tools/dmtracedump.jd
+++ b/docs/html/guide/developing/tools/dmtracedump.jd
@@ -1,4 +1,6 @@
 page.title=dmtracedump
+parent.title=Tools
+parent.link=index.html
 @jd:body
 
 
diff --git a/docs/html/guide/developing/tools/draw9patch.jd b/docs/html/guide/developing/tools/draw9patch.jd
index 4d8043b..1d9de4f 100644
--- a/docs/html/guide/developing/tools/draw9patch.jd
+++ b/docs/html/guide/developing/tools/draw9patch.jd
@@ -1,4 +1,6 @@
 page.title=Draw 9-patch
+parent.title=Tools
+parent.link=index.html
 @jd:body
 
 <p>The Draw 9-patch tool allows you to easily create a 
diff --git a/docs/html/guide/developing/tools/emulator.jd b/docs/html/guide/developing/tools/emulator.jd
index 748a8b1..ff667f2 100644
--- a/docs/html/guide/developing/tools/emulator.jd
+++ b/docs/html/guide/developing/tools/emulator.jd
@@ -1,6 +1,8 @@
 page.title=Android Emulator
+parent.title=Tools
+parent.link=index.html
 @jd:body
-<p>
+
 <p>The Android SDK includes a mobile device emulator &mdash; a virtual mobile device 
 that runs on your computer. The emulator lets you develop and test
 Android applications without using a physical device.</p>
diff --git a/docs/html/guide/developing/tools/hierarchy-viewer.jd b/docs/html/guide/developing/tools/hierarchy-viewer.jd
index ce660fc..3d3191b 100644
--- a/docs/html/guide/developing/tools/hierarchy-viewer.jd
+++ b/docs/html/guide/developing/tools/hierarchy-viewer.jd
@@ -1,4 +1,6 @@
 page.title=Hierarchy Viewer
+parent.title=Tools
+parent.link=index.html
 @jd:body
 
 <p>Hierarchy Viewer allows you to debug and optimize your user 
diff --git a/docs/html/guide/developing/tools/hprof-conv.jd b/docs/html/guide/developing/tools/hprof-conv.jd
index 27000b4..f96def2 100644
--- a/docs/html/guide/developing/tools/hprof-conv.jd
+++ b/docs/html/guide/developing/tools/hprof-conv.jd
@@ -1,4 +1,6 @@
 page.title=HPROF Converter
+parent.title=Tools
+parent.link=index.html
 @jd:body
 
 <p>
diff --git a/docs/html/guide/developing/tools/layoutopt.jd b/docs/html/guide/developing/tools/layoutopt.jd
index e8f623d..cb0b505 100644
--- a/docs/html/guide/developing/tools/layoutopt.jd
+++ b/docs/html/guide/developing/tools/layoutopt.jd
@@ -1,4 +1,6 @@
 page.title=layoutopt
+parent.title=Tools
+parent.link=index.html
 @jd:body
 
 <p><code>layoutopt</code> is a command-line tool that helps you optimize the
diff --git a/docs/html/guide/developing/tools/logcat.jd b/docs/html/guide/developing/tools/logcat.jd
index 9603b9f..d4ee68a 100644
--- a/docs/html/guide/developing/tools/logcat.jd
+++ b/docs/html/guide/developing/tools/logcat.jd
@@ -1,4 +1,6 @@
 page.title=logcat
+parent.title=Tools
+parent.link=index.html
 @jd:body
 <div></div>
 
diff --git a/docs/html/guide/developing/tools/mksdcard.jd b/docs/html/guide/developing/tools/mksdcard.jd
index 0ec69d2..0a80454 100644
--- a/docs/html/guide/developing/tools/mksdcard.jd
+++ b/docs/html/guide/developing/tools/mksdcard.jd
@@ -1,4 +1,6 @@
 page.title=mksdcard
+parent.title=Tools
+parent.link=index.html
 @jd:body
 
  <p>The <code>mksdcard</code> tool lets you quickly create a FAT32 disk image that you can load in the
diff --git a/docs/html/guide/developing/tools/monkey.jd b/docs/html/guide/developing/tools/monkey.jd
index 6c05934..a7e539c 100644
--- a/docs/html/guide/developing/tools/monkey.jd
+++ b/docs/html/guide/developing/tools/monkey.jd
@@ -1,4 +1,6 @@
 page.title=UI/Application Exerciser Monkey
+parent.title=Tools
+parent.link=index.html
 @jd:body
 
 <p>The Monkey is a program that runs on your 
diff --git a/docs/html/guide/developing/tools/monkeyrunner_concepts.jd b/docs/html/guide/developing/tools/monkeyrunner_concepts.jd
index 658ff75..97c7c1f 100644
--- a/docs/html/guide/developing/tools/monkeyrunner_concepts.jd
+++ b/docs/html/guide/developing/tools/monkeyrunner_concepts.jd
@@ -1,4 +1,6 @@
 page.title=monkeyrunner
+parent.title=Tools
+parent.link=index.html
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/developing/tools/proguard.jd b/docs/html/guide/developing/tools/proguard.jd
index e75a8cd..b97babe 100644
--- a/docs/html/guide/developing/tools/proguard.jd
+++ b/docs/html/guide/developing/tools/proguard.jd
@@ -1,4 +1,6 @@
 page.title=ProGuard
+parent.title=Tools
+parent.link=index.html
 @jd:body
 
  <div id="qv-wrapper">
diff --git a/docs/html/guide/developing/tools/sqlite3.jd b/docs/html/guide/developing/tools/sqlite3.jd
index 71e614f..9cc7e98 100644
--- a/docs/html/guide/developing/tools/sqlite3.jd
+++ b/docs/html/guide/developing/tools/sqlite3.jd
@@ -1,4 +1,6 @@
 page.title=sqlite3
+parent.title=Tools
+parent.link=index.html
 @jd:body
 
  <p>From a remote shell to your device or from your host machine, you can use the <a href= 
diff --git a/docs/html/guide/developing/tools/traceview.jd b/docs/html/guide/developing/tools/traceview.jd
index 422fe00..aa37481 100644
--- a/docs/html/guide/developing/tools/traceview.jd
+++ b/docs/html/guide/developing/tools/traceview.jd
@@ -1,4 +1,6 @@
 page.title=Traceview
+parent.title=Tools
+parent.link=index.html
 @jd:body
 
 <p>Traceview is a graphical viewer for execution logs saved by your application. 
diff --git a/docs/html/guide/developing/tools/zipalign.jd b/docs/html/guide/developing/tools/zipalign.jd
index 6231798..ebf177b 100644
--- a/docs/html/guide/developing/tools/zipalign.jd
+++ b/docs/html/guide/developing/tools/zipalign.jd
@@ -1,4 +1,6 @@
 page.title=zipalign
+parent.title=Tools
+parent.link=index.html
 @jd:body
 
 <p>zipalign is an archive alignment tool that provides important
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index 24ccfdb..92230a9 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -60,27 +60,27 @@
       <li class="toggle-list">
         <div><a href="<?cs var:toroot ?>guide/topics/fundamentals/activities.html">
           <span class="en">Activities</span>
-        </a></div>
+        </a> <span class="new">new!</span></div>
         <ul>
           <li><a href="<?cs var:toroot ?>guide/topics/fundamentals/fragments.html">
             <span class="en">Fragments</span>
           </a> <span class="new">new!</span></li>
-          <li><a href="<?cs var:toroot ?>guide/topics/providers/loaders.html">
+          <li><a href="<?cs var:toroot ?>guide/topics/fundamentals/loaders.html">
             <span class="en">Loaders</span>
-          </a><span class="new">new!</span></li>
+          </a> <span class="new">new!</span></li>
           <li><a href="<?cs var:toroot ?>guide/topics/fundamentals/tasks-and-back-stack.html">
             <span class="en">Tasks and Back Stack</span>
-          </a></li>
+          </a> <span class="new">new!</span></li>
         </ul>
       </li>
       <li class="toggle-list">
         <div><a href="<?cs var:toroot ?>guide/topics/fundamentals/services.html">
           <span class="en">Services</span>
-        </a></div>
+        </a> <span class="new">new!</span></div>
         <ul>
           <li><a href="<?cs var:toroot ?>guide/topics/fundamentals/bound-services.html">
             <span class="en">Bound Services</span>
-          </a></li>
+          </a> <span class="new">new!</span></li>
         </ul>
       </li>
       <li><a href="<?cs var:toroot ?>guide/topics/providers/content-providers.html">
@@ -91,7 +91,7 @@
           </a></li>
       <li><a href="<?cs var:toroot ?>guide/topics/fundamentals/processes-and-threads.html">
             <span class="en">Processes and Threads</span>
-          </a></li>
+          </a> <span class="new">new!</span></li>
     </ul>
 
 
@@ -419,7 +419,7 @@
       <li class="toggle-list">
         <div>
            <a href="<?cs var:toroot ?>guide/developing/devices/index.html">
-                <span class="en">Creating and Managing Virtual Devices</span>
+                <span class="en">Managing Virtual Devices</span>
             </a>
         </div>
         <ul>
@@ -430,7 +430,7 @@
           </li>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/devices/managing-avds-cmdline.html">
-              <span class="en">On the Command Line</span>
+              <span class="en">From the Command Line</span>
             </a>
           </li>
           <li>
@@ -460,7 +460,7 @@
           </li>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/projects/projects-cmdline.html">
-                <span class="en">On the Command Line</span>
+                <span class="en">From the Command Line</span>
             </a>
           </li>
         </ul>
@@ -490,12 +490,12 @@
         <ul>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/debugging/debugging-projects.html">
-                <span class="en">In Eclipse with ADT</span>
+                <span class="en">From Eclipse with ADT</span>
             </a>
           </li>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/debugging/debugging-projects-cmdline.html">
-                <span class="en">In Other IDEs</span>
+                <span class="en">From Other IDEs</span>
             </a>
           </li>
           <li>
@@ -505,7 +505,7 @@
           </li>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/debugging/debugging-log.html">
-                <span class="en">Reading and Writing Log Messages</span>
+                <span class="en">Reading and Writing Logs</span>
             </a>
           </li>
           <li>
diff --git a/docs/html/guide/market/billing/billing_about.jd b/docs/html/guide/market/billing/billing_about.jd
index 9c027ca..dac9738 100755
--- a/docs/html/guide/market/billing/billing_about.jd
+++ b/docs/html/guide/market/billing/billing_about.jd
@@ -1,4 +1,6 @@
 page.title=About this Release
+parent.title=In-app Billing
+parent.link=index.html
 @jd:body
 
 <style type="text/css">
diff --git a/docs/html/guide/market/billing/billing_admin.jd b/docs/html/guide/market/billing/billing_admin.jd
index cc5cb59..cd8f960 100755
--- a/docs/html/guide/market/billing/billing_admin.jd
+++ b/docs/html/guide/market/billing/billing_admin.jd
@@ -1,4 +1,6 @@
 page.title=Administering In-app Billing
+parent.title=In-app Billing
+parent.link=index.html
 @jd:body
 
 <style type="text/css">
diff --git a/docs/html/guide/market/billing/billing_best_practices.jd b/docs/html/guide/market/billing/billing_best_practices.jd
index fd67e80..4743e88 100755
--- a/docs/html/guide/market/billing/billing_best_practices.jd
+++ b/docs/html/guide/market/billing/billing_best_practices.jd
@@ -1,4 +1,6 @@
 page.title=Security and Design
+parent.title=In-app Billing
+parent.link=index.html
 @jd:body
 
 <style type="text/css">
diff --git a/docs/html/guide/market/billing/billing_integrate.jd b/docs/html/guide/market/billing/billing_integrate.jd
index 0f081a5..0cac2eb 100755
--- a/docs/html/guide/market/billing/billing_integrate.jd
+++ b/docs/html/guide/market/billing/billing_integrate.jd
@@ -1,4 +1,6 @@
 page.title=Implementing In-app Billing
+parent.title=In-app Billing
+parent.link=index.html
 @jd:body
 
 <style type="text/css">
diff --git a/docs/html/guide/market/billing/billing_overview.jd b/docs/html/guide/market/billing/billing_overview.jd
index 675fe2a..b899b9b 100755
--- a/docs/html/guide/market/billing/billing_overview.jd
+++ b/docs/html/guide/market/billing/billing_overview.jd
@@ -1,4 +1,6 @@
-page.title=Overview of In-app Billing
+page.title=In-app Billing Overview
+parent.title=In-app Billing
+parent.link=index.html
 @jd:body
 
 <style type="text/css">
diff --git a/docs/html/guide/market/billing/billing_reference.jd b/docs/html/guide/market/billing/billing_reference.jd
index c91ca89..2e5c9c6 100755
--- a/docs/html/guide/market/billing/billing_reference.jd
+++ b/docs/html/guide/market/billing/billing_reference.jd
@@ -1,4 +1,6 @@
 page.title=In-app Billing Reference
+parent.title=In-app Billing
+parent.link=index.html
 @jd:body
 
 <style type="text/css">
diff --git a/docs/html/guide/market/billing/billing_testing.jd b/docs/html/guide/market/billing/billing_testing.jd
index 4a36588..5ced9c7 100755
--- a/docs/html/guide/market/billing/billing_testing.jd
+++ b/docs/html/guide/market/billing/billing_testing.jd
@@ -1,4 +1,6 @@
 page.title=Testing In-app Billing
+parent.title=In-app Billing
+parent.link=index.html
 @jd:body
 
 <style type="text/css">
diff --git a/docs/html/guide/market/billing/index.jd b/docs/html/guide/market/billing/index.jd
index f5d001d..6985179 100755
--- a/docs/html/guide/market/billing/index.jd
+++ b/docs/html/guide/market/billing/index.jd
@@ -1,4 +1,4 @@
-page.title=Adding In-app Billing to Your Applications
+page.title=In-app Billing
 @jd:body
 
 <style type="text/css">
diff --git a/docs/html/guide/publishing/licensing.jd b/docs/html/guide/publishing/licensing.jd
index 5551384..4184ecb 100644
--- a/docs/html/guide/publishing/licensing.jd
+++ b/docs/html/guide/publishing/licensing.jd
@@ -1,4 +1,4 @@
-page.title=Licensing Your Applications
+page.title=Application Licensing
 @jd:body
 
 <div id="qv-wrapper">
@@ -518,7 +518,7 @@
 </ol>
 
 <p>If you are not familiar with AVDs or how to use them, see <a
-href="{@docRoot}guide/developing/devices/index.html">Creating and Managing Virtual Devices</a>.</p>
+href="{@docRoot}guide/developing/devices/index.html">Managing Virtual Devices</a>.</p>
 
 <h4 id="project-update">Updating your project configuration</h4>
 
@@ -629,7 +629,7 @@
 
 <p style="margin-top:.5em;">If you aren't familiar with library projects or how
 to use them, see <a href="{@docRoot}guide/developing/projects/index.html#LibraryProjects">
-Creating and Managing Projects</a>.
+Managing Projects</a>.
 </p>
 </div>
 </div>
@@ -666,8 +666,9 @@
 no further configuration is needed. </p>
 
 <p>For more information about how to create an application project or work with
-library projects in Eclipse, see <a href="{@docRoot}guide/developing/projects/projects-eclipse.html">
-Creating and Managing Projects in Eclipse</a></p>.
+library projects in Eclipse, see <a
+href="{@docRoot}guide/developing/projects/projects-eclipse.html">Managing Projects from
+Eclipse with ADT</a></p>.
 
 <h4>Copying the LVL sources to your application</h4>
 
@@ -698,8 +699,8 @@
 Select the "Android" properties group and click <strong>Add</strong>, then
 choose the LVL library project (com_android_vending_licensing) and click
 <strong>OK</strong>. For more information, see 
-<a href="{@docRoot}developing/projects/projects-eclipse.html#SettingUpLibraryProject">
-Creating and Managing Projects in Eclipse</a></p>.
+<a href="{@docRoot}guide/developing/projects/projects-eclipse.html#SettingUpLibraryProject">
+Managing Projects from Eclipse with ADT</a></p>.
 
 <div style="margin-bottom:2em;">
 
@@ -727,8 +728,8 @@
 </pre>
 
 <p>For more information about working with library projects, 
-see <a href="{@docRoot}developing/projects/projects-cmdline.html#SettingUpLibraryProject">
-Creating and Managing Projects on the Command Line</a></p>.
+see <a href="{@docRoot}guide/developing/projects/projects-cmdline.html#SettingUpLibraryProject">
+Managing Projects from the Command Line</a></p>.
 
 
 <h2 id="app-integration">Integrating the LVL with Your Application</h2>
diff --git a/docs/html/guide/topics/advanced/aidl.jd b/docs/html/guide/topics/advanced/aidl.jd
index fef46ec..419048a 100644
--- a/docs/html/guide/topics/advanced/aidl.jd
+++ b/docs/html/guide/topics/advanced/aidl.jd
@@ -14,9 +14,11 @@
 <p class="note"><strong>Note:</strong> Using AIDL is necessary only if you allow clients from
 different applications to access your service for IPC and want to handle multithreading in your
 service. If you do not need to perform IPC across
-different applications, you should create your interface <a href="Binder">implementing a
+different applications, you should create your interface <a
+href="{@docRoot}guide/topics/fundamentals/bound-services.html#Binder">implementing a
 Binder</a> or, if you want to perform IPC, but do not need to handle multithreading, then you
-should implement your interface <a href="#Messenger">using a Messenger</a>.</p>
+should implement your interface <a
+href="{@docRoot}guide/topics/fundamentals/bound-services.html#Messenger">using a Messenger</a>.</p>
 
 <p>Before you begin designing your AIDL interface, be aware that calls on to an AIDL interface are
 direct function calls.  You can not generally make assumptions about the thread in which the call
diff --git a/docs/html/guide/topics/fundamentals.jd b/docs/html/guide/topics/fundamentals.jd
index 3fdbd95..661f5cb 100644
--- a/docs/html/guide/topics/fundamentals.jd
+++ b/docs/html/guide/topics/fundamentals.jd
@@ -422,7 +422,7 @@
 resources. However, you should create specialized layouts for certain screen sizes and provide
 specialized images for certain densities, using alternative layout resources, and by declaring in
 your manifest exactly which screen sizes your application supports with the <a
-href="{@docRoot}guide/topics/manifest/supports-screens.html">{@code
+href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
 &lt;supports-screens&gt;}</a> element.</p>
 <p>For more information, see the <a
 href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>
@@ -453,7 +453,8 @@
 href="{@docRoot}guide/appendix/api-levels.html">API Level</a> (for example, Android 1.0 is API Level
 1 and Android 2.3 is API Level 9). If you use any APIs that were added to the platform after
 version 1.0, you should declare the minimum API Level in which those APIs were introduced using the
-<a href="{@docRoot}guide/topics/manifest/uses-sdk.html">{@code &lt;uses-sdk&gt;}</a> element.</dd>
+<a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code &lt;uses-sdk&gt;}</a>
+element.</dd>
 </dl>
 
 <p>It's important that you declare all such requirements for your application, because, when you
diff --git a/docs/html/guide/topics/fundamentals/activities.jd b/docs/html/guide/topics/fundamentals/activities.jd
index 9079ef6..5cc1b45 100644
--- a/docs/html/guide/topics/fundamentals/activities.jd
+++ b/docs/html/guide/topics/fundamentals/activities.jd
@@ -40,7 +40,7 @@
 <h2>See also</h2>
 <ol>
   <li><a href="{@docRoot}resources/tutorials/hello-world.html">Hello World Tutorial</a></li>
-  <li><a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack">Tasks and Back
+  <li><a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back
 Stack</a></li>
 </ol>
 
@@ -594,13 +594,14 @@
 definition in table 1 might still be killed by the system&mdash;but that would happen only in
 extreme circumstances when there is no other recourse. When an activity might be killed is
 discussed more in the <a
-href="{@docRoot}guide/topics/fundamentals/processes-and-threading.html">Processes and
+href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html">Processes and
 Threading</a> document.</p>
 
 
 <h3 id="SavingActivityState">Saving activity state</h3>
 
-<p>The introduction to <a href="Lifecycle">Managing the Activity Lifecycle</a> briefly mentions that
+<p>The introduction to <a href="#Lifecycle">Managing the Activity Lifecycle</a> briefly mentions
+that
 when an activity is paused or stopped, the state of the activity is retained. This is true because
 the {@link android.app.Activity} object is still held in memory when it is paused or
 stopped&mdash;all information about its members and current state is still alive. Thus, any changes
diff --git a/docs/html/guide/topics/fundamentals/fragments.jd b/docs/html/guide/topics/fundamentals/fragments.jd
index 7ca990e..f780960 100644
--- a/docs/html/guide/topics/fundamentals/fragments.jd
+++ b/docs/html/guide/topics/fundamentals/fragments.jd
@@ -743,7 +743,8 @@
 based on the screen configuration.</p>
 
 <p class="note"><strong>Note:</strong> The complete source code for this activity is available in
-<a href="resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.html">{@code
+<a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.html">{@code
 FragmentLayout.java}</a>.</p>
 
 <p>The main activity applies a layout in the usual way, during {@link
diff --git a/docs/html/guide/topics/providers/loaders.jd b/docs/html/guide/topics/fundamentals/loaders.jd
similarity index 97%
rename from docs/html/guide/topics/providers/loaders.jd
rename to docs/html/guide/topics/fundamentals/loaders.jd
index c54656c..d31f090 100644
--- a/docs/html/guide/topics/providers/loaders.jd
+++ b/docs/html/guide/topics/fundamentals/loaders.jd
@@ -1,4 +1,6 @@
-page.title=Using Loaders
+page.title=Loaders
+parent.title=Activities
+parent.link=activities.html
 @jd:body
 <div id="qv-wrapper">
 <div id="qv">
@@ -29,8 +31,11 @@
     
     <h2>Related samples</h2>
    <ol>
-     <li> <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentCursorLoader.html"> FragmentCursorLoader</a></li>
-     <li> <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> LoaderThrottle</a></li>
+     <li> <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentListCursorLoader.html">FragmentListCursorLoader</a></li>
+     <li> <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html">
+LoaderThrottle</a></li>
    </ol>
   </div>
 </div>
@@ -480,7 +485,7 @@
 <p>There are a few different samples in <strong>ApiDemos</strong> that
 illustrate how to use loaders:</p>
 <ul>
-  <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentCursorLoader.html"> FragmentCursorLoader</a> &#8212; A complete version of the
+  <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentListCursorLoader.html">FragmentListCursorLoader</a> &#8212; A complete version of the
 snippet shown above.</li>
   <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html"> LoaderThrottle</a> &#8212; An example of how to use throttling to
 reduce the number of queries a content provider does then its data changes.</li>
diff --git a/docs/html/guide/topics/fundamentals/services.jd b/docs/html/guide/topics/fundamentals/services.jd
index d0c924a..a9dd315 100644
--- a/docs/html/guide/topics/fundamentals/services.jd
+++ b/docs/html/guide/topics/fundamentals/services.jd
@@ -121,7 +121,7 @@
 android.app.Activity#onStart onStart()}, then stop it in {@link android.app.Activity#onStop
 onStop()}. Also consider using {@link android.os.AsyncTask} or {@link android.os.HandlerThread},
 instead of the traditional {@link java.lang.Thread} class. See the <a
-href="{@docRoot}guide/topics/fundamentals/processes-and-threading.html#Threads">Processes and
+href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes and
 Threading</a> document for more information about threads.</p>
   <p>Remember that if you do use a service, it still runs in your application's main thread by
 default, so you should still create a new thread within the service if it performs intensive or
@@ -183,7 +183,7 @@
 available again (though this also depends on the value you return from {@link
 android.app.Service#onStartCommand onStartCommand()}, as discussed later). For more information
 about when the system might destroy a service, see the <a
-href="{@docRoot}guide/topics/fundamentals/processes-and-threading.html">Processes and Threading</a>
+href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html">Processes and Threading</a>
 document.</p>
 
 <p>In the following sections, you'll see how you can create each type of service and how to use
diff --git a/docs/html/guide/topics/graphics/2d-graphics.jd b/docs/html/guide/topics/graphics/2d-graphics.jd
index 6594568..618cdf8 100644
--- a/docs/html/guide/topics/graphics/2d-graphics.jd
+++ b/docs/html/guide/topics/graphics/2d-graphics.jd
@@ -1,5 +1,5 @@
 page.title=2D Graphics
-parent.title=2D and 3D Graphics
+parent.title=Graphics
 parent.link=index.html
 @jd:body
 
diff --git a/docs/html/guide/topics/graphics/animation.jd b/docs/html/guide/topics/graphics/animation.jd
index cd74efa..3b1716c 100644
--- a/docs/html/guide/topics/graphics/animation.jd
+++ b/docs/html/guide/topics/graphics/animation.jd
@@ -1,4 +1,6 @@
 page.title=Property Animation
+parent.title=Graphics
+parent.link=index.html
 @jd:body
 
   <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/graphics/opengl.jd b/docs/html/guide/topics/graphics/opengl.jd
index 4d0b223..1f51c2d 100644
--- a/docs/html/guide/topics/graphics/opengl.jd
+++ b/docs/html/guide/topics/graphics/opengl.jd
@@ -1,5 +1,5 @@
 page.title=3D with OpenGL
-parent.title=2D and 3D Graphics
+parent.title=Graphics
 parent.link=index.html
 @jd:body
 
diff --git a/docs/html/guide/topics/graphics/renderscript.jd b/docs/html/guide/topics/graphics/renderscript.jd
index 0ef8a22..54737ad 100644
--- a/docs/html/guide/topics/graphics/renderscript.jd
+++ b/docs/html/guide/topics/graphics/renderscript.jd
@@ -1,4 +1,6 @@
 page.title=3D Rendering and Computation with Renderscript
+parent.title=Graphics
+parent.link=index.html
 @jd:body
 
   <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/graphics/view-animation.jd b/docs/html/guide/topics/graphics/view-animation.jd
index ad27e1c..eff6f70 100644
--- a/docs/html/guide/topics/graphics/view-animation.jd
+++ b/docs/html/guide/topics/graphics/view-animation.jd
@@ -1,4 +1,6 @@
 page.title=View Animation
+parent.title=Graphics
+parent.link=index.html
 @jd:body
 
   <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/nfc/index.jd b/docs/html/guide/topics/nfc/index.jd
index 3992099..c4917b4 100644
--- a/docs/html/guide/topics/nfc/index.jd
+++ b/docs/html/guide/topics/nfc/index.jd
@@ -31,29 +31,33 @@
     </div>
   </div>
 
-  <p>Near Field Communication (NFC) is a set of short-range wireless technologies, similar to RFID.
-  It typically requires a distance of 4 cm or less and operates at 13.56mhz and at rates ranging
-  from 106 kbit/s to 848 kbit/s. NFC communication always involves an initiator and a target. The
-  initiator actively generates an RF field that can power a passive target. This enables NFC
-  targets to take very simple form factors such as tags, stickers or cards that do not require
-  power. NFC peer-to-peer communication is also possible, where both devices are powered.</p>
-
-  <p>Compared to other wireless technologies such as Bluetooth or WiFi, NFC provides much lower
-  bandwidth and range, but provides low-cost, un-powered targets and do not require discovery or
-  pairing. Users interact with NFC tags with just a tap. Targets can range in complexity. Simple
-  tags just offer read and write capabilities, sometimes with one-time programmable areas to make
-  the card read-only. More complex tags offer math operations, and have cryptographic hardware to
-  authenticate access to a sector. The most sophisticated tags contain operating environments,
-  allowing complex interactions with applets that are running on the tag.</p>
-
-  <p>An Android device with NFC hardware typically acts as an initiator. This mode is also known as
-  NFC reader/writer. The device actively looks for NFC tags and starts activities to handle them in
-  this mode. In Android 2.3.3, devices also have some limited peer-to-peer support.</p>
+  <p>Near Field Communication (NFC) is a set of short-range wireless technologies, typically
+  requiring a distance of 4cm or less. NFC operates at 13.56mhz, and at rates ranging
+  from 106 kbit/s to 848 kbit/s. NFC communication always involves an initiator and a target.
+  The initiator actively generates an RF field that can power a passive target. This
+  enables NFC targets to take very simple form factors such as tags, stickers or cards that do
+  not require power. NFC peer-to-peer communication is also possible, where both devices
+  are powered.
+  <p>
+  Compared to other wireless technologies such as Bluetooth or WiFi, NFC provides much lower
+  bandwidth and range, but enables low-cost, un-powered targets
+  and does not require discovery or pairing. Interactions can be initiated with just a tap.
+  <p>
+  An Android device with NFC hardware will typically act as an initiator when the screen is
+  on. This mode is also known as NFC reader/writer. It will actively look for NFC tags and start
+  activities to handle them. Android 2.3.3 also has some limited P2P support.
+  <p>
+  Tags can range in complexity, simple tags just offer read/write semantics, sometimes
+  with one-time-programmable areas to make the card read-only. More complex tags offer
+  math operations, and have cryptographic hardware to authenticate access to a sector.
+  The most sophisticated tags contain operating environments, allowing
+  complex interactions with code executing on the tag.
 
   <h2 id="api">API Overview</h2>
 
-  <p>The {@link android.nfc} package contain the high-level classes to interact with the local
-  device's NFC adapter, to represent discovered tags, and to use the NDEF data format.</p>
+  <p>The {@link android.nfc} package contains the high-level classes to interact
+  with the local device's NFC adapter, to represent discovered tags, and to use
+  the NDEF data format.
 
   <table>
     <tr>
@@ -65,44 +69,52 @@
     <tr>
       <td>{@link android.nfc.NfcManager}</td>
 
-      <td>A high level manager class that enumerates the NFC adapters on this Android device. Since
-      most Android devices only have one NFC adapter, you can just use the static helper {@link
-      android.nfc.NfcAdapter#getDefaultAdapter()} for most situations.</td>
+
+      <td>A high level manager class that enumerates the NFC adapters on this Android device.
+      Since most Android devices only have one NFC adapter, you can just use the static helper
+      {@link android.nfc.NfcAdapter#getDefaultAdapter(Context)} for most situations.</td>
     </tr>
 
     <tr>
       <td>{@link android.nfc.NfcAdapter}</td>
 
-      <td>Represents the local NFC adapter and defines the Intents that are used in the tag
-      dispatch system. It provides methods to register for foreground tag dispatching and
-      foreground NDEF pushing. Foreground NDEF push is the only peer-to-peer support that is
-      currently provided in Android.</td>
+      <td>Represents the local NFC adapter. Defines the intent's used to request
+      tag dispatch to your activity, and provides methods to register for foreground
+      tag dispatch and foreground NDEF push. Foreground NDEF push is the only
+      peer-to-peer support that is currently provided in Android.</td>
     </tr>
 
     <tr>
       <td>{@link android.nfc.NdefMessage} and {@link android.nfc.NdefRecord}</td>
 
-      <td>NDEF is an NFC Forum defined data structure, designed to efficiently store data on NFC
-      tags, such as Text, URLs, and other MIME types. An {@link android.nfc.NdefMessage} acts as a
+      <td>NDEF is an NFC Forum defined data structure, designed to efficiently
+      store data on NFC tags, such as text, URL's, and other MIME types. A
+      {@link android.nfc.NdefMessage} acts as a
       container for the data that you want to transmit or read. One {@link android.nfc.NdefMessage}
-      object contains zero or more {@link android.nfc.NdefRecord}s. Each NDEF Record has a type
-      such as Text, URL, Smart Poster, or any MIME type. The type of the first NDEF Record in the
-      NDEF message is used to dispatch a tag to an Activity.</td>
+      object contains zero or more {@link android.nfc.NdefRecord}s. Each NDEF record
+      has a type such as text, URL, smart poster, or any MIME data. The type of the
+      first NDEF record in the NDEF message is used to dispatch a tag to an activity
+      on Android.</td>
     </tr>
 
     <tr>
       <td>{@link android.nfc.Tag}</td>
 
-      <td>Represents a passive NFC target. These can come in many form factors such as a tag, card,
-      FOB, or an even more complex device doing card emulation. When a tag is discovered, a {@link
-      android.nfc.Tag} object is created and wrapped inside an Intent. The dispatch system sends
-      the Intent to a compatible Activity <code>startActivity()</code>. You can use the {@link
+      <td>Represents a passive NFC target. These can come in many form factors such as
+      a tag, card, key fob, or even a phone doing card emulation. When a tag is
+      discovered, a {@link android.nfc.Tag} object is created and wrapped inside an
+      Intent. The NFC dispatch system sends the intent to a compatible actvitiy
+      using <code>startActivity()</code>. You can use the {@link
       android.nfc.Tag#getTechList getTechList()} method to determine the technologies supported by
       this tag and create the corresponding {@link android.nfc.tech.TagTechnology} object with one
       of classes provided by {@link android.nfc.tech}.</td>
     </tr>
   </table>
 
+  <p>The {@link android.nfc.tech} package contains classes to query properties
+  and perform I/O operations on a tag. The classes are divided to represent different
+  NFC technologies that can be available on a tag.
+
   <p>The {@link android.nfc.tech} package contains classes to query properties and perform I/O
   operations on a tag. The classes are divided to represent different NFC technologies that can be
   available on a Tag:</p>
@@ -117,7 +129,7 @@
     <tr>
       <td>{@link android.nfc.tech.TagTechnology}</td>
 
-      <td>The interface that all Tag Technology classes must implement.</td>
+      <td>The interface that all tag technology classes must implement.</td>
     </tr>
 
     <tr>
@@ -153,8 +165,8 @@
     <tr>
       <td>{@link android.nfc.tech.Ndef}</td>
 
-      <td>Provides access to NDEF data and operations on NFC Tags that have been formatted as
-      NDEF.</td>
+      <td>Provides access to NDEF data and operations on NFC tags that have been formatted as NDEF.
+      </td>
     </tr>
 
     <tr>
@@ -166,15 +178,15 @@
     <tr>
       <td>{@link android.nfc.tech.MifareClassic}</td>
 
-      <td>Provides access to MIFARE Classic properties and I/O operations. Not all Android devices
-      provide implementations for this class.</td>
+      <td>Provides access to MIFARE Classic properties and I/O operations, if this
+      Android device supports MIFARE.</td>
     </tr>
 
     <tr>
       <td>{@link android.nfc.tech.MifareUltralight}</td>
 
-      <td>Provides access to MIFARE Ultralight properties and I/O operations. Not all Android
-      devices provide implementations for this class.</td>
+      <td>Provides access to MIFARE Ultralight properties and I/O operations, if this
+      Android device supports MIFARE.</td>
     </tr>
   </table>
 
@@ -191,12 +203,13 @@
     </li>
 
     <li>The minimum SDK version that your application can support. API level 9 only supports
-    limited tag dispatching with {@link android.nfc.NfcAdapter#ACTION_TAG_DISCOVERED}, and only
-    gives access to NDEF messages via the {@link android.nfc.NfcAdapter#EXTRA_NDEF_MESSAGES} extra.
-    No other tag properties or I/O operations are accessible. API level 10 adds comprehensive
-    reader/writer support, so you probably want to use this for more functionality.
-      <pre class="pretty-print">
-&lt;uses-sdk android:minSdkVersion="9|10"/&gt;
+    limited tag dispatch via {@link android.nfc.NfcAdapter#ACTION_TAG_DISCOVERED},
+    and only gives access to NDEF messages via the {@link android.nfc.NfcAdapter#EXTRA_NDEF_MESSAGES}
+    extra. No other tag properties or I/O operations are accessible. You probably want
+    to use API level 10 which includes comprehensive reader/writer support.
+
+<pre class="pretty-print">
+&lt;uses-sdk android:minSdkVersion="10"/&gt;
 </pre>
     </li>
 
diff --git a/docs/html/guide/topics/testing/activity_testing.jd b/docs/html/guide/topics/testing/activity_testing.jd
index 6392ad7..51121f4 100644
--- a/docs/html/guide/topics/testing/activity_testing.jd
+++ b/docs/html/guide/topics/testing/activity_testing.jd
@@ -1,4 +1,6 @@
 page.title=Activity Testing
+parent.title=Testing
+parent.link=index.html
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/testing/contentprovider_testing.jd b/docs/html/guide/topics/testing/contentprovider_testing.jd
index e42e631..edaae8c 100644
--- a/docs/html/guide/topics/testing/contentprovider_testing.jd
+++ b/docs/html/guide/topics/testing/contentprovider_testing.jd
@@ -1,4 +1,6 @@
 page.title=Content Provider Testing
+parent.title=Testing
+parent.link=index.html
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/testing/service_testing.jd b/docs/html/guide/topics/testing/service_testing.jd
index 77884779..eae8607 100644
--- a/docs/html/guide/topics/testing/service_testing.jd
+++ b/docs/html/guide/topics/testing/service_testing.jd
@@ -1,4 +1,6 @@
 page.title=Service Testing
+parent.title=Testing
+parent.link=index.html
 @jd:body
 
 <div id="qv-wrapper">
diff --git a/docs/html/guide/topics/testing/testing_android.jd b/docs/html/guide/topics/testing/testing_android.jd
index 6f3048c..c8a3f6e 100755
--- a/docs/html/guide/topics/testing/testing_android.jd
+++ b/docs/html/guide/topics/testing/testing_android.jd
@@ -1,4 +1,6 @@
 page.title=Testing Fundamentals
+parent.title=Testing
+parent.link=index.html
 @jd:body
 
 <div id="qv-wrapper">
@@ -653,10 +655,12 @@
         It guides you through a more complex testing scenario that you develop against a
         more realistic application.
     </li>
+    <!-- sample is not available
     <li>
-        The sample test package <a href="{@docRoot}resources/samples/AlarmServiceTest"}>
+        The sample test package <a href="{@docRoot}resources/samples/AlarmServiceTest/index.html">
         Alarm Service Test</a> is an example of testing a {@link android.app.Service}. It contains
         a set of unit tests for the Alarm Service sample application's {@link android.app.Service}.
     </li>
+    -->
 </ul>
 
diff --git a/docs/html/guide/topics/testing/what_to_test.jd b/docs/html/guide/topics/testing/what_to_test.jd
index e8a27da..99061df 100644
--- a/docs/html/guide/topics/testing/what_to_test.jd
+++ b/docs/html/guide/topics/testing/what_to_test.jd
@@ -1,4 +1,6 @@
 page.title=What To Test
+parent.title=Testing
+parent.link=index.html
 @jd:body
 <p>
     As you develop Android applications, knowing what to test is as important as knowing how to
diff --git a/docs/html/guide/topics/ui/actionbar.jd b/docs/html/guide/topics/ui/actionbar.jd
index b8d1928..065f95a 100644
--- a/docs/html/guide/topics/ui/actionbar.jd
+++ b/docs/html/guide/topics/ui/actionbar.jd
@@ -38,7 +38,15 @@
     <li>{@link android.app.ActionBar}</li>
     <li>{@link android.view.Menu}</li>
   </ol>
-
+  
+  <h2>Related samples</h2>
+  <ol>
+    <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/index.html#ActionBar">API
+        Demos</a></li>
+    <li><a
+href="{@docRoot}resources/samples/HoneycombGallery/index.html">Honeycomb Gallery</a></li>
+  </ol>
+  
   <h2>See also</h2>
   <ol>
     <li><a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a></li>
@@ -363,7 +371,7 @@
 in the overflow menu as a normal menu item and you must respond to it from the {@link
 android.app.Activity#onOptionsItemSelected onOptionsItemSelected()} callback method. (For a
 guide to providing search functionality, see the <a
-href="{@docRoot}gudie/topics/search/index.html">Search</a> documentation.)</p>
+href="{@docRoot}guide/topics/search/index.html">Search</a> documentation.)</p>
 
 <p>When the activity first starts, the system populates the Action Bar and overflow menu by calling
 {@link android.app.Activity#onCreateOptionsMenu onCreateOptionsMenu()}.
@@ -397,7 +405,7 @@
   <img src="{@docRoot}images/ui/actionbar-tabs.png" alt="" />
   <p class="img-caption"><strong>Figure 6.</strong> Screenshot of tabs in the
 Action Bar, from the <a
-href="{@docRoot}resources/samples/Honeycomb-Gallery/index.html">Honeycomb Gallery</a> sample
+href="{@docRoot}resources/samples/HoneycombGallery/index.html">Honeycomb Gallery</a> sample
 application.</p>
 </div>
 
diff --git a/docs/html/guide/topics/ui/drag-drop.jd b/docs/html/guide/topics/ui/drag-drop.jd
index 46ccdf8..c33c507 100644
--- a/docs/html/guide/topics/ui/drag-drop.jd
+++ b/docs/html/guide/topics/ui/drag-drop.jd
@@ -289,14 +289,14 @@
 <p>
     To get the action type, a listener calls {@link android.view.DragEvent#getAction()}. There
     are six possible values, defined by constants in the {@link android.view.DragEvent} class. These
-    are listed in <a href="table1">table 1</a>.
+    are listed in <a href="#table1">table 1</a>.
 </p>
 <p>
     The {@link android.view.DragEvent} object also contains the data that your application provided
     to the system in the call to
     {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}.
     Some of the data is valid only for certain action types. The data that is valid for each action
-    type is summarized in <a href="table2">table 2</a>. It is also described in detail with
+    type is summarized in <a href="#table2">table 2</a>. It is also described in detail with
     the event for which it is valid in the section
     <a href="#DesignDragOperation">Designing a Drag and Drop Operation</a>.
 </p>
diff --git a/docs/html/images/developing/hv_device_window.png b/docs/html/images/developing/hv_device_window.png
new file mode 100644
index 0000000..2bb80a8
--- /dev/null
+++ b/docs/html/images/developing/hv_device_window.png
Binary files differ
diff --git a/docs/html/images/developing/hv_pixelperfect.png b/docs/html/images/developing/hv_pixelperfect.png
new file mode 100644
index 0000000..6d19119
--- /dev/null
+++ b/docs/html/images/developing/hv_pixelperfect.png
Binary files differ
diff --git a/docs/html/images/developing/hv_treeview_screenshot.png b/docs/html/images/developing/hv_treeview_screenshot.png
new file mode 100644
index 0000000..c0e7ac5
--- /dev/null
+++ b/docs/html/images/developing/hv_treeview_screenshot.png
Binary files differ
diff --git a/docs/html/images/developing/hv_view_hierarchy_window.png b/docs/html/images/developing/hv_view_hierarchy_window.png
new file mode 100644
index 0000000..0d8b263
--- /dev/null
+++ b/docs/html/images/developing/hv_view_hierarchy_window.png
Binary files differ
diff --git a/docs/html/index.jd b/docs/html/index.jd
index 0c57527..2248752 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -129,16 +129,17 @@
     'sdk': {
       'layout':"imgLeft",
       'icon':"sdk-small.png",
-      'name':"Android 2.3.3",
-      'img':"gingerdroid.png",
-      'title':"Android 2.3.3, more NFC!",
-      'desc': "<p>Android 2.3.3 is now available for the Android SDK. "
-+ "This update adds new NFC capabilities for developers, including advanced tag dispatching APIs "
-+ "and the ability to write to tags.</p>"
-+ "<p>The new APIs enable exciting new applications, such as for ticketing, "
-+ "ratings, check-ins, advertising, and data exchange with other devices. "
-+ "For more information about Android 2.3.3, read the "
-+ "<a href='/sdk/android-2.3.3.html'>version notes</a>.</p>"
+      'name':"Android 3.0",
+      'img':"honeycomb-android.png",
+      'title':"Android 3.0 is here!",
+      'desc': "<p>Android 3.0 is now available for the Android SDK. It offers a redesigned UI and "
++ "all new developer APIs for an optimized experience on tablets and similar devices. "
++ "For more information about what's in Android 3.0, read the "
++ "<a href='{@docRoot}sdk/android-3.0.html'>version notes</a>.</p>"
++ "<p>If you have an existing SDK, add Android 3.0 as an "
++ "<a href='{@docRoot}sdk/adding-components.html'>SDK "
++ "component</a>. If you're new to Android, install the "
++ "<a href='{@docRoot}sdk/index.html'>SDK starter package</a>."
     },
 
     'tv': {
diff --git a/docs/html/resources/articles/avoiding-memory-leaks.jd b/docs/html/resources/articles/avoiding-memory-leaks.jd
index 3361bc1..395f590 100644
--- a/docs/html/resources/articles/avoiding-memory-leaks.jd
+++ b/docs/html/resources/articles/avoiding-memory-leaks.jd
@@ -1,4 +1,6 @@
 page.title=Avoiding Memory Leaks
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 
diff --git a/docs/html/resources/articles/backward-compatibility.jd b/docs/html/resources/articles/backward-compatibility.jd
index ad64dfc..f96d587 100644
--- a/docs/html/resources/articles/backward-compatibility.jd
+++ b/docs/html/resources/articles/backward-compatibility.jd
@@ -1,4 +1,6 @@
 page.title=Backward Compatibility for Applications
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 
diff --git a/docs/html/resources/articles/can-i-use-this-intent.jd b/docs/html/resources/articles/can-i-use-this-intent.jd
index a726189..c527331 100644
--- a/docs/html/resources/articles/can-i-use-this-intent.jd
+++ b/docs/html/resources/articles/can-i-use-this-intent.jd
@@ -1,4 +1,6 @@
 page.title=Can I Use this Intent?
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <p>Android offers a very powerful and yet easy-to-use message type called 
diff --git a/docs/html/resources/articles/contacts.jd b/docs/html/resources/articles/contacts.jd
index c837dc3..8365d29 100644
--- a/docs/html/resources/articles/contacts.jd
+++ b/docs/html/resources/articles/contacts.jd
@@ -1,4 +1,6 @@
 page.title=Using the Contacts API
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <p>Starting from Android 2.0 (API Level 5), the Android platform provides an
diff --git a/docs/html/resources/articles/creating-input-method.jd b/docs/html/resources/articles/creating-input-method.jd
index 6f932df..e4b77f4 100644
--- a/docs/html/resources/articles/creating-input-method.jd
+++ b/docs/html/resources/articles/creating-input-method.jd
@@ -1,4 +1,6 @@
 page.title=Creating an Input Method
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 
diff --git a/docs/html/resources/articles/drawable-mutations.jd b/docs/html/resources/articles/drawable-mutations.jd
index f979829..c5818fc 100644
--- a/docs/html/resources/articles/drawable-mutations.jd
+++ b/docs/html/resources/articles/drawable-mutations.jd
@@ -1,4 +1,6 @@
 page.title=Drawable Mutations
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <p>Android's drawables are extremely useful to easily build applications. A
diff --git a/docs/html/resources/articles/faster-screen-orientation-change.jd b/docs/html/resources/articles/faster-screen-orientation-change.jd
index f82e592..52531bb 100644
--- a/docs/html/resources/articles/faster-screen-orientation-change.jd
+++ b/docs/html/resources/articles/faster-screen-orientation-change.jd
@@ -1,4 +1,6 @@
 page.title=Faster Screen Orientation Change
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 
diff --git a/docs/html/resources/articles/future-proofing.jd b/docs/html/resources/articles/future-proofing.jd
index ee98186..b8aeedf 100644
--- a/docs/html/resources/articles/future-proofing.jd
+++ b/docs/html/resources/articles/future-proofing.jd
@@ -1,4 +1,6 @@
 page.title=Future-Proofing Your Apps
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <p>It's important to implement your application so that it will not break as new
diff --git a/docs/html/resources/articles/gestures.jd b/docs/html/resources/articles/gestures.jd
index 8711645..5b8d760 100644
--- a/docs/html/resources/articles/gestures.jd
+++ b/docs/html/resources/articles/gestures.jd
@@ -1,4 +1,6 @@
 page.title=Gestures
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <p>Touch screens are a great way to interact with applications on
diff --git a/docs/html/resources/articles/glsurfaceview.jd b/docs/html/resources/articles/glsurfaceview.jd
index 57403ea..45407a9 100644
--- a/docs/html/resources/articles/glsurfaceview.jd
+++ b/docs/html/resources/articles/glsurfaceview.jd
@@ -1,4 +1,6 @@
 page.title=Introducing GLSurfaceView
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 
diff --git a/docs/html/resources/articles/index.jd b/docs/html/resources/articles/index.jd
index d2b7645..220a4ed 100644
--- a/docs/html/resources/articles/index.jd
+++ b/docs/html/resources/articles/index.jd
@@ -1,4 +1,6 @@
 page.title=Technical Articles
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <dl>
diff --git a/docs/html/resources/articles/layout-tricks-efficiency.jd b/docs/html/resources/articles/layout-tricks-efficiency.jd
index b7b5761..00b4147 100644
--- a/docs/html/resources/articles/layout-tricks-efficiency.jd
+++ b/docs/html/resources/articles/layout-tricks-efficiency.jd
@@ -1,4 +1,6 @@
 page.title=Layout Tricks: Creating Efficient Layouts
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <p>The Android UI toolkit offers several layout managers that are
diff --git a/docs/html/resources/articles/layout-tricks-merge.jd b/docs/html/resources/articles/layout-tricks-merge.jd
index 95409e4..0ca0317 100644
--- a/docs/html/resources/articles/layout-tricks-merge.jd
+++ b/docs/html/resources/articles/layout-tricks-merge.jd
@@ -1,4 +1,6 @@
 page.title=Layout Tricks: Merging Layouts
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <p>The articles showed you how to use the <code>&lt;include /&gt;</code> tag in XML layouts, to
diff --git a/docs/html/resources/articles/layout-tricks-reuse.jd b/docs/html/resources/articles/layout-tricks-reuse.jd
index 396e212..179c1d8 100644
--- a/docs/html/resources/articles/layout-tricks-reuse.jd
+++ b/docs/html/resources/articles/layout-tricks-reuse.jd
@@ -1,4 +1,6 @@
 page.title=Layout Tricks: Creating Reusable UI Components
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <p>The Android platform offers a wide variety of UI <em>widgets</em>, small
diff --git a/docs/html/resources/articles/layout-tricks-stubs.jd b/docs/html/resources/articles/layout-tricks-stubs.jd
index 88bcb78..64f07f9 100644
--- a/docs/html/resources/articles/layout-tricks-stubs.jd
+++ b/docs/html/resources/articles/layout-tricks-stubs.jd
@@ -1,4 +1,6 @@
 page.title=Layout Tricks: Using ViewStubs
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <p>Sharing and reusing UI components is very easy with Android, thanks to the <a
diff --git a/docs/html/resources/articles/listview-backgrounds.jd b/docs/html/resources/articles/listview-backgrounds.jd
index f4c6998..c4037ba 100644
--- a/docs/html/resources/articles/listview-backgrounds.jd
+++ b/docs/html/resources/articles/listview-backgrounds.jd
@@ -1,4 +1,6 @@
 page.title=ListView Backgrounds: An Optimization
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <p>{@link android.widget.ListView} is one of Android's most widely used widgets.
diff --git a/docs/html/resources/articles/live-folders.jd b/docs/html/resources/articles/live-folders.jd
index be974f4..aeab997 100644
--- a/docs/html/resources/articles/live-folders.jd
+++ b/docs/html/resources/articles/live-folders.jd
@@ -1,4 +1,6 @@
 page.title=Live Folders
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <p>Live folders, introduced in Android 1.5 (API Level 3), let you display any source of data
diff --git a/docs/html/resources/articles/live-wallpapers.jd b/docs/html/resources/articles/live-wallpapers.jd
index ea67fed..bfbbb34 100644
--- a/docs/html/resources/articles/live-wallpapers.jd
+++ b/docs/html/resources/articles/live-wallpapers.jd
@@ -1,4 +1,6 @@
 page.title=Live Wallpapers
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 
@@ -27,35 +29,36 @@
 <img src="images/live_wallpapers_small.png" style="align:center" />
 
 <p>Creating your own live wallpaper is easy, especially if you have had
-previous experience with <a
-href="../../../reference/android/view/SurfaceView.html"><code>SurfaceView</code></a> or <a
-href="../../../reference/android/graphics/Canvas.html"><code>Canvas</code></a>. 
+previous experience with {@link android.view.SurfaceView} or {@link
+android.graphics.Canvas}. 
 To learn how to create a live wallpaper, you should check out the <a 
 href="../samples/CubeLiveWallpaper/index.html">CubeLiveWallpaper sample code</a>.</p>
 
-<p>In terms of implementation, a live wallpaper is very similar to a regular
-Android <a href="../../../reference/android/app/Service.html">service</a>. The
-only difference is the addition of a new method, <a
-href="../../../reference/android/service/wallpaper/WallpaperService.html#onCreateEngine()">{@code
-onCreateEngine()}</a>, whose goal is to create a <a
-href="../../../reference/android/service/wallpaper/WallpaperService.Engine.html">
-<code>WallpaperService.Engine</code></a>. The engine is responsible for
+<p>In terms of implementation, a live wallpaper is very similar to a {@link android.app.Service}.
+The only difference is the addition of a new method, {@link
+android.service.wallpaper.WallpaperService#onCreateEngine()}, whose goal is to create a {@link
+android.service.wallpaper.WallpaperService.Engine}. The engine is responsible for
 handling the lifecycle and drawing of a wallpaper. The system provides a surface
-on which you can draw, just like you would with a <code>SurfaceView</code></a>.
+on which you can draw, just like you would with a {@link android.view.SurfaceView}.
 Drawing a wallpaper can be very expensive so you should optimize your code
 as much as possible to avoid using too much CPU, not only for battery life
 but also to avoid slowing down the rest of the system. That is also why the
-most important part of the lifecycle of a wallpaper is <a href="../../../reference/android/service/wallpaper/WallpaperService.Engine.html#onVisibilityChanged%28boolean%29">when it becomes invisible</a>. 
+most important part of the lifecycle of a wallpaper is when it becomes visible, as indicated
+by a call to {@link android.service.wallpaper.WallpaperService.Engine#onVisibilityChanged
+onVisibilityChanged()}. 
 When invisible, such as when the user launches an application that covers
 the home screen, a wallpaper must stop all activity.</p>
 
 <p>The engine can also implement several methods to interact with the user
 or the home application. For instance, if you want your wallpaper to scroll
-along when the user swipes from one home screen to another, you can use <a href="../../../reference/android/service/wallpaper/WallpaperService.Engine.html#onOffsetsChanged%28float,%20float,%20float,%20float,%20int,%20int%29"><code>onOffsetsChanged()</code></a>.
-To react to touch events, simply implement <a href="../../../reference/android/service/wallpaper/WallpaperService.Engine.html#onTouchEvent%28android.view.MotionEvent%29"><code>onTouchEvent(MotionEvent)</code></a>.
+along when the user swipes from one home screen to another, you can use
+{@link android.service.wallpaper.WallpaperService.Engine#onOffsetsChanged
+onOffsetsChanged()}.
+To react to touch events, simply implement {@link
+android.service.wallpaper.WallpaperService.Engine#onTouchEvent onTouchEvent()}.
 Finally, applications can send arbitrary commands to the live wallpaper.
-Currently, only the standard home application sends commands to the <a
-href="../../../reference/android/service/wallpaper/WallpaperService.Engine.html#onCommand%28java.lang.String,%20int,%20int,%20int,%20android.os.Bundle,%20boolean%29"><code>onCommand()</code></a>
+Currently, only the standard home application sends commands to the
+{@link android.service.wallpaper.WallpaperService.Engine#onCommand onCommand()}
 method of the live wallpaper:</p>
 
 <ul>
@@ -78,9 +81,9 @@
 <ul>
 <li><code>&lt;uses-sdk android:minSdkVersion="7" /&gt;</code>, which indicates
 to Android Market and the platform that your application requires Android 2.1 or
-higher. For more information, see the <a href="../../../guide/appendix/api-levels.html">API
+higher. For more information, see the <a href="{@docRoot}guide/appendix/api-levels.html">API
 Levels</a> and the documentation for the
-<a href="../../../guide/topics/manifest/uses-sdk-element.html"><code>&lt;uses-sdk&gt;</code></a>
+<a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><code>&lt;uses-sdk&gt;</code></a>
 element.</li>
 <li><code>&lt;uses-feature android:name="android.software.live_wallpaper" /&gt;</code>,
 which tells Android Market that your application includes a live wallpaper
@@ -89,7 +92,9 @@
 displays your application only to users whose devices support live wallpapers,
 while hiding it from other devices on which it would not be able to run. For
 more information, see the documentation for the
-<a href="../../../guide/topics/manifest/uses-feature-element.html"><code>&lt;uses-feature&gt;</code></a>
+<a
+href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code
+&lt;uses-feature&gt;</a>
 element.</li>
 </ul>
 
diff --git a/docs/html/resources/articles/on-screen-inputs.jd b/docs/html/resources/articles/on-screen-inputs.jd
index 30b4c84..6a028c8 100644
--- a/docs/html/resources/articles/on-screen-inputs.jd
+++ b/docs/html/resources/articles/on-screen-inputs.jd
@@ -1,4 +1,6 @@
 page.title=Onscreen Input Methods
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 
diff --git a/docs/html/resources/articles/painless-threading.jd b/docs/html/resources/articles/painless-threading.jd
index 17cec35..fea7ee2 100644
--- a/docs/html/resources/articles/painless-threading.jd
+++ b/docs/html/resources/articles/painless-threading.jd
@@ -1,4 +1,6 @@
 page.title=Painless Threading
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <p>This article discusses the threading model used by Android applications and how applications can ensure best UI performance by spawning worker threads to handle long-running operations, rather than handling them in the main thread. The article also explains the API that your application can use to interact with Android UI toolkit components running on the main thread and spawn managed worker threads.  </p>
diff --git a/docs/html/resources/articles/qsb.jd b/docs/html/resources/articles/qsb.jd
index d47ba54..01fb115 100644
--- a/docs/html/resources/articles/qsb.jd
+++ b/docs/html/resources/articles/qsb.jd
@@ -1,4 +1,6 @@
 page.title=Quick Search Box
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 
diff --git a/docs/html/resources/articles/speech-input.jd b/docs/html/resources/articles/speech-input.jd
index 282b619..d42bd59 100644
--- a/docs/html/resources/articles/speech-input.jd
+++ b/docs/html/resources/articles/speech-input.jd
@@ -1,4 +1,6 @@
 page.title=Speech Input
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <p> People love their mobile phones because they can stay in touch wherever they
diff --git a/docs/html/resources/articles/timed-ui-updates.jd b/docs/html/resources/articles/timed-ui-updates.jd
index 863387c..7a0804f 100644
--- a/docs/html/resources/articles/timed-ui-updates.jd
+++ b/docs/html/resources/articles/timed-ui-updates.jd
@@ -1,4 +1,6 @@
 page.title=Updating the UI from a Timer
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <img style="margin: 1.5em; float: right;" src="images/JFlubber.png" alt="" id="BLOGGER_PHOTO_ID_5135098660116808706" border="0">
diff --git a/docs/html/resources/articles/touch-mode.jd b/docs/html/resources/articles/touch-mode.jd
index e340062..5eae9b9 100644
--- a/docs/html/resources/articles/touch-mode.jd
+++ b/docs/html/resources/articles/touch-mode.jd
@@ -1,4 +1,6 @@
 page.title=Touch Mode
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <p>This article explains the <em>touch mode</em>, one of the most 
diff --git a/docs/html/resources/articles/track-mem.jd b/docs/html/resources/articles/track-mem.jd
index d580e82..c4184b5 100644
--- a/docs/html/resources/articles/track-mem.jd
+++ b/docs/html/resources/articles/track-mem.jd
@@ -1,4 +1,6 @@
 page.title=Tracking Memory Allocations
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <p>Writing efficient mobile applications is not always straightforward. In
diff --git a/docs/html/resources/articles/tts.jd b/docs/html/resources/articles/tts.jd
index e3fad91..7d07a89 100644
--- a/docs/html/resources/articles/tts.jd
+++ b/docs/html/resources/articles/tts.jd
@@ -1,4 +1,6 @@
 page.title=Using Text-to-Speech
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <p>Starting with Android 1.6 (API Level 4), the Android platform includes a new
diff --git a/docs/html/resources/articles/ui-1.5.jd b/docs/html/resources/articles/ui-1.5.jd
index c10cf52..2edaa2e 100644
--- a/docs/html/resources/articles/ui-1.5.jd
+++ b/docs/html/resources/articles/ui-1.5.jd
@@ -1,4 +1,6 @@
 page.title=UI Framework Changes in Android 1.5
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 
diff --git a/docs/html/resources/articles/ui-1.6.jd b/docs/html/resources/articles/ui-1.6.jd
index 10cb524..09108dd 100644
--- a/docs/html/resources/articles/ui-1.6.jd
+++ b/docs/html/resources/articles/ui-1.6.jd
@@ -1,4 +1,6 @@
 page.title=UI Framework Changes in Android 1.6
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <p>Android 1.6 introduces numerous enhancements and bug fixes in the UI
diff --git a/docs/html/resources/articles/using-webviews.jd b/docs/html/resources/articles/using-webviews.jd
index 3a1f34c..3a2430b 100644
--- a/docs/html/resources/articles/using-webviews.jd
+++ b/docs/html/resources/articles/using-webviews.jd
@@ -1,4 +1,6 @@
 page.title=Using WebViews
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <p>A small application called <a title="WebViewDemo"
diff --git a/docs/html/resources/articles/wikinotes-intents.jd b/docs/html/resources/articles/wikinotes-intents.jd
index bc64544..78fe62e 100644
--- a/docs/html/resources/articles/wikinotes-intents.jd
+++ b/docs/html/resources/articles/wikinotes-intents.jd
@@ -1,4 +1,6 @@
 page.title=WikiNotes: Routing Intents
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 
diff --git a/docs/html/resources/articles/wikinotes-linkify.jd b/docs/html/resources/articles/wikinotes-linkify.jd
index 21b1f13..fb49f86 100644
--- a/docs/html/resources/articles/wikinotes-linkify.jd
+++ b/docs/html/resources/articles/wikinotes-linkify.jd
@@ -1,4 +1,6 @@
 page.title=WikiNotes: Linkify your Text!
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <img style="margin-left: 1.5em; margin-bottom:1.5em; float: right;" 
diff --git a/docs/html/resources/articles/window-bg-speed.jd b/docs/html/resources/articles/window-bg-speed.jd
index bd7a303..c5e5e90 100644
--- a/docs/html/resources/articles/window-bg-speed.jd
+++ b/docs/html/resources/articles/window-bg-speed.jd
@@ -1,4 +1,6 @@
 page.title=Window Backgrounds &amp; UI Speed
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <p>Some Android applications require to squeeze every bit of performance out of
diff --git a/docs/html/resources/articles/zipalign.jd b/docs/html/resources/articles/zipalign.jd
index 013d0fe..9e767aa 100644
--- a/docs/html/resources/articles/zipalign.jd
+++ b/docs/html/resources/articles/zipalign.jd
@@ -1,4 +1,6 @@
 page.title=Zipalign: an Easy Optimization
+parent.title=Articles
+parent.link=../browser.html?tag=article
 @jd:body
 
 <p>The Android SDK includes a tool called <a
diff --git a/docs/html/resources/resources-data.js b/docs/html/resources/resources-data.js
index febdb9a..5839064 100644
--- a/docs/html/resources/resources-data.js
+++ b/docs/html/resources/resources-data.js
@@ -569,7 +569,7 @@
     tags: ['sample', 'new', 'newfeature', 'widgets'],
     path: 'samples/StackWidget/index.html',
     title: {
-      en: 'StackView App Widget'
+      en: 'StackView Widget'
     },
     description: {
       en: 'Demonstrates how to create a simple collection widget containing a StackView.'
@@ -619,7 +619,7 @@
     tags: ['sample', 'widgets', 'newfeature', 'new'],
     path: 'samples/WeatherListWidget/index.html',
     title: {
-      en: 'Weather List Widget Sample'
+      en: 'Weather List Widget'
     },
     description: {
       en: 'A more complex collection-widget example which uses a ContentProvider as its data source.'
diff --git a/docs/html/resources/samples/get.jd b/docs/html/resources/samples/get.jd
index 1b6d137..86ec836 100644
--- a/docs/html/resources/samples/get.jd
+++ b/docs/html/resources/samples/get.jd
@@ -1,4 +1,6 @@
 page.title=Getting the Samples
+parent.title=Sample Code
+parent.link=../browser.html?tag=sample
 
 @jd:body
 
diff --git a/docs/html/resources/tutorials/hello-world.jd b/docs/html/resources/tutorials/hello-world.jd
index 67c2521..020c738 100644
--- a/docs/html/resources/tutorials/hello-world.jd
+++ b/docs/html/resources/tutorials/hello-world.jd
@@ -1,4 +1,6 @@
 page.title=Hello, World
+parent.title=Tutorials
+parent.link=../browser.html?tag=tutorial
 @jd:body
 <div id="qv-wrapper">
 <div id="qv">
diff --git a/docs/html/resources/tutorials/localization/index.jd b/docs/html/resources/tutorials/localization/index.jd
index 8a60814..de4433b 100755
--- a/docs/html/resources/tutorials/localization/index.jd
+++ b/docs/html/resources/tutorials/localization/index.jd
@@ -1,4 +1,6 @@
 page.title=Hello, L10N

+parent.title=Tutorials

+parent.link=../../browser.html?tag=tutorial

 @jd:body

 

 <div id="qv-wrapper">

diff --git a/docs/html/resources/tutorials/notepad/index.jd b/docs/html/resources/tutorials/notepad/index.jd
index f569314..dd92184 100644
--- a/docs/html/resources/tutorials/notepad/index.jd
+++ b/docs/html/resources/tutorials/notepad/index.jd
@@ -1,4 +1,6 @@
 page.title=Notepad Tutorial
+parent.title=Tutorials
+parent.link=../../browser.html?tag=tutorial
 @jd:body
 
 
diff --git a/docs/html/resources/tutorials/testing/activity_test.jd b/docs/html/resources/tutorials/testing/activity_test.jd
index c94e8ab..4b861e2 100644
--- a/docs/html/resources/tutorials/testing/activity_test.jd
+++ b/docs/html/resources/tutorials/testing/activity_test.jd
@@ -1,4 +1,6 @@
 page.title=Activity Testing
+parent.title=Tutorials
+parent.link=../../browser.html?tag=tutorial
 @jd:body
  <div id="qv-wrapper">
   <div id="qv">
diff --git a/docs/html/resources/tutorials/testing/helloandroid_test.jd b/docs/html/resources/tutorials/testing/helloandroid_test.jd
index b47c334..4d949c8 100644
--- a/docs/html/resources/tutorials/testing/helloandroid_test.jd
+++ b/docs/html/resources/tutorials/testing/helloandroid_test.jd
@@ -1,4 +1,6 @@
 page.title=Hello, Testing
+parent.title=Tutorials
+parent.link=../../browser.html?tag=tutorial
 @jd:body
  <div id="qv-wrapper">
   <div id="qv">
diff --git a/docs/html/resources/tutorials/views/index.jd b/docs/html/resources/tutorials/views/index.jd
index 6ea7683..bba8330 100644
--- a/docs/html/resources/tutorials/views/index.jd
+++ b/docs/html/resources/tutorials/views/index.jd
@@ -1,4 +1,6 @@
 page.title=Hello, Views
+parent.title=Tutorials
+parent.link=../../browser.html?tag=tutorial
 @jd:body
 
 <style>
diff --git a/docs/html/sdk/android-3.0.jd b/docs/html/sdk/android-3.0.jd
index 6842c82..8088e32 100644
--- a/docs/html/sdk/android-3.0.jd
+++ b/docs/html/sdk/android-3.0.jd
@@ -294,8 +294,8 @@
 android.widget.ListView}, and {@link android.widget.StackView} that are backed by remote data,
 such as from a content provider.</p>
 
-<p>The {@link android.appwidget.AppWidgetProviderInfo} class (defined with an {@code
-&lt;appwidget-provider&gt; XML file) also supports two new fields: {@link
+<p>The {@link android.appwidget.AppWidgetProviderInfo} class (defined in XML with an {@code
+&lt;appwidget-provider&gt;} element) also supports two new fields: {@link
 android.appwidget.AppWidgetProviderInfo#autoAdvanceViewId} and {@link
 android.appwidget.AppWidgetProviderInfo#previewImage}. The {@link
 android.appwidget.AppWidgetProviderInfo#autoAdvanceViewId} field lets you specify the view ID of the
@@ -351,10 +351,10 @@
 loader for your activity or fragment.</p>
 
 <p>For more information, read the <a
-href="{@docRoot}guide/topics/providers/loaders.html">Loaders</a> documentation. You can also see
+href="{@docRoot}guide/topics/fundamentals/loaders.html">Loaders</a> documentation. You can also see
 example code using loaders in the <a
-href="{@docRoot}samples/ApiDemos/src/com/example/android/apis/app/FragmentListCursorLoader.html">
-FragmentListCursorLoader</a> and <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentListCursorLoader.html">FragmentListCursorLoader</a>
+and <a
 href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LoaderThrottle.html">
 LoaderThrottle</a> samples.</p>
 
diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd
index c283167..355465b 100644
--- a/docs/html/sdk/eclipse-adt.jd
+++ b/docs/html/sdk/eclipse-adt.jd
@@ -116,22 +116,27 @@
   <ul>
   <li>The tools now automatically generate Java Programming Language source files (in the <code>gen/</code> directory) and
     bytecode (in the <code>res/raw/</code> directory) from your <code>.rs</code> files.</li>
-  <li>A Binary XML editor has been added.</li>
+  <li>A Binary XML editor has been added (<a href="http://tools.android.com/recent/binaryxmleditor">details</a>).</li>
   <li>Traceview is now integrated into the Eclipse UI (<a href="http://tools.android.com/recent/traceviewineclipse">details</a>).</li>
   <li>The "Go To Declaration" feature for XML and <code>.java</code> files quickly show all the matches in the project
-  and allows you jump to specific items such as string translations or <code>onClick</code> handlers.</li>
-  <li>The Resource Chooser can create items such as dimensions, integers, ids, and booleans.</li>
+  and allows you jump to specific items such as string translations or <code>onClick</code> handlers
+  (<a href="http://tools.android.com/recent/gotodeclarationimprovements">details</a>).</li>
+  <li>The Resource Chooser can create items such as dimensions, integers, ids, and booleans
+  (<a href="http://tools.android.com/recent/resourcechoosercannowcreatearbitraryvalues">details</a>).</li>
   <li>Improvements to the Visual Layout Editor:
       <ul>
         <li>A new Palette with categories and rendering previews
         (<a href="http://tools.android.com/recent/newpalette">details</a>).</li>
-        <li>A Layout action bar.</li>
+        <li>A Layout Actions bar that provides quick access to common layout operations
+        (<a href="http://tools.android.com/recent/layoutactionsbar">details</a>).</li>
         <li>When the Android 3.0 rendering library is selected, layouts render more like they do on devices.
         This includes rendering of status and title bars to more accurately reflect the actual
-        screen space available to applications.</li>
+        screen space available to applications
+        (<a href="http://tools.android.com/recent/systembarandactionbar">details</a>).</li>
         <li>Zoom improvements such as fit to view, persistent scale, and keyboard access.
         (<a href="http://tools.android.com/recent/zoomimprovements">details</a>).</li>
-        <li>Further improvements to <code>&lt;merge&gt;</code> layouts, as well as layouts with gesture overlays.</li>
+        <li>Further improvements to <code>&lt;merge&gt;</code> layouts, as well as layouts with gesture overlays
+        (<a href="http://tools.android.com/recent/improvedsupportformergetags">details</a>).</li>
         <li>Improved rendering error diagnostics.</li>
       </ul>
     </li>    
diff --git a/docs/html/sdk/preview/start.jd b/docs/html/sdk/preview/start.jd
index 3bf70b3..d6e442e 100644
--- a/docs/html/sdk/preview/start.jd
+++ b/docs/html/sdk/preview/start.jd
@@ -46,7 +46,7 @@
 the samples are located in <code>&lt;sdk_root&gt;/samples/android-Honeycomb</code>. The list of links
 below helps you find samples for the features you are interested in:</p>
 <ul>
-  <li><a href="{@docRoot}resources/samples/Honeycomb-Gallery/index.html">Honeycomb Gallery</a> -
+  <li><a href="{@docRoot}resources/samples/HoneycombGallery/index.html">Honeycomb Gallery</a> -
   A demo application highlighting how to use some of the new APIs in Honeycomb, including fragments, the action bar,
   drag and drop, transition animations, and a stack widget.</li>
   <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/index.html#Fragment">Fragments</a>
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index b2f4379..12dc93c 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -19,7 +19,6 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.DisplayMetrics;
-
 import java.io.OutputStream;
 import java.nio.Buffer;
 import java.nio.ByteBuffer;
@@ -342,7 +341,7 @@
         }
 
         long bufferSize = (long)elements << shift;
-        long pixelSize = (long)getRowBytes() * getHeight();
+        long pixelSize = getByteCount();
 
         if (bufferSize < pixelSize) {
             throw new RuntimeException("Buffer not large enough for pixels");
@@ -378,7 +377,7 @@
         }
 
         long bufferBytes = (long)elements << shift;
-        long bitmapBytes = (long)getRowBytes() * getHeight();
+        long bitmapBytes = getByteCount();
 
         if (bufferBytes < bitmapBytes) {
             throw new RuntimeException("Buffer not large enough for pixels");
@@ -822,6 +821,14 @@
     }
 
     /**
+     * Returns the number of bytes used to store this bitmap's pixels.
+     */
+    public final int getByteCount() {
+        // int result permits bitmaps up to 46,340 x 46,340
+        return getRowBytes() * getHeight();
+    }
+
+    /**
      * If the bitmap's internal config is in one of the public formats, return
      * that config, otherwise return null.
      */
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index d8a7f9d..0a23bae 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1254,9 +1254,7 @@
      * @param text  The text to measure
      * @param index The offset into text to begin measuring at
      * @param count The number of maximum number of entries to measure. If count
-     *              is negative, then the characters before index are measured
-     *              in reverse order. This allows for measuring the end of
-     *              string.
+     *              is negative, then the characters are measured in reverse order.
      * @param maxWidth The maximum width to accumulate.
      * @param measuredWidth Optional. If not null, returns the actual width
      *                     measured.
diff --git a/graphics/tests/graphicstests/src/android/graphics/BitmapTest.java b/graphics/tests/graphicstests/src/android/graphics/BitmapTest.java
index 6734bb7..685a998 100644
--- a/graphics/tests/graphicstests/src/android/graphics/BitmapTest.java
+++ b/graphics/tests/graphicstests/src/android/graphics/BitmapTest.java
@@ -16,8 +16,6 @@
 
 package android.graphics;
 
-import android.graphics.Bitmap;
-import android.graphics.Color;
 import android.test.suitebuilder.annotation.SmallTest;
 import junit.framework.TestCase;
 
@@ -42,6 +40,10 @@
         assertEquals("rowbytes", 200, bm2.getRowBytes());
         assertEquals("rowbytes", 200, bm3.getRowBytes());
         
+        assertEquals("byteCount", 80000, bm1.getByteCount());
+        assertEquals("byteCount", 40000, bm2.getByteCount());
+        assertEquals("byteCount", 40000, bm3.getByteCount());
+
         assertEquals("height", 200, bm1.getHeight());
         assertEquals("height", 200, bm2.getHeight());
         assertEquals("height", 200, bm3.getHeight());
diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h
index d484d60..b35a6e6 100644
--- a/include/media/stagefright/AudioSource.h
+++ b/include/media/stagefright/AudioSource.h
@@ -18,15 +18,17 @@
 
 #define AUDIO_SOURCE_H_
 
+#include <media/AudioRecord.h>
 #include <media/AudioSystem.h>
 #include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <utils/List.h>
 
 namespace android {
 
 class AudioRecord;
-struct MediaBufferGroup;
 
-struct AudioSource : public MediaSource {
+struct AudioSource : public MediaSource, public MediaBufferObserver {
     // Note that the "channels" parameter is _not_ the number of channels,
     // but a bitmask of AudioSystem::audio_channels constants.
     AudioSource(
@@ -45,6 +47,9 @@
     virtual status_t read(
             MediaBuffer **buffer, const ReadOptions *options = NULL);
 
+    status_t dataCallbackTimestamp(const AudioRecord::Buffer& buffer, int64_t timeUs);
+    virtual void signalBufferReturned(MediaBuffer *buffer);
+
 protected:
     virtual ~AudioSource();
 
@@ -61,20 +66,24 @@
         kAutoRampStartUs = 1000000,
       };
 
+    Mutex mLock;
+    Condition mFrameAvailableCondition;
+    Condition mFrameEncodingCompletionCondition;
+
     AudioRecord *mRecord;
     status_t mInitCheck;
     bool mStarted;
+    int32_t mSampleRate;
 
-    bool mCollectStats;
     bool mTrackMaxAmplitude;
     int64_t mStartTimeUs;
     int16_t mMaxAmplitude;
     int64_t mPrevSampleTimeUs;
-    int64_t mTotalLostFrames;
-    int64_t mPrevLostBytes;
     int64_t mInitialReadTimeUs;
+    int64_t mNumFramesReceived;
+    int64_t mNumClientOwnedBuffers;
 
-    MediaBufferGroup *mGroup;
+    List<MediaBuffer * > mBuffersReceived;
 
     void trackMaxAmplitude(int16_t *data, int nSamples);
 
@@ -84,6 +93,9 @@
         int32_t startFrame, int32_t rampDurationFrames,
         uint8_t *data,   size_t bytes);
 
+    void releaseQueuedFrames_l();
+    void waitOutstandingEncodingFrames_l();
+
     AudioSource(const AudioSource &);
     AudioSource &operator=(const AudioSource &);
 };
diff --git a/include/media/stagefright/MediaDefs.h b/include/media/stagefright/MediaDefs.h
index 31a549c..66dfff6 100644
--- a/include/media/stagefright/MediaDefs.h
+++ b/include/media/stagefright/MediaDefs.h
@@ -38,6 +38,7 @@
 extern const char *MEDIA_MIMETYPE_AUDIO_G711_MLAW;
 extern const char *MEDIA_MIMETYPE_AUDIO_RAW;
 extern const char *MEDIA_MIMETYPE_AUDIO_FLAC;
+extern const char *MEDIA_MIMETYPE_AUDIO_AAC_ADTS;
 
 extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG4;
 extern const char *MEDIA_MIMETYPE_CONTAINER_WAV;
diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp
index 624f7eb..9f501e2 100644
--- a/libs/binder/MemoryHeapBase.cpp
+++ b/libs/binder/MemoryHeapBase.cpp
@@ -31,7 +31,7 @@
 
 #include <binder/MemoryHeapBase.h>
 
-#if HAVE_ANDROID_OS
+#ifdef HAVE_ANDROID_OS
 #include <linux/android_pmem.h>
 #endif
 
@@ -108,7 +108,7 @@
 {
     if (size == 0) {
         // try to figure out the size automatically
-#if HAVE_ANDROID_OS
+#ifdef HAVE_ANDROID_OS
         // first try the PMEM ioctl
         pmem_region reg;
         int err = ioctl(fd, PMEM_GET_TOTAL_SIZE, &reg);
diff --git a/libs/binder/MemoryHeapPmem.cpp b/libs/binder/MemoryHeapPmem.cpp
index 16e92f9..03322ea 100644
--- a/libs/binder/MemoryHeapPmem.cpp
+++ b/libs/binder/MemoryHeapPmem.cpp
@@ -30,7 +30,7 @@
 #include <binder/MemoryHeapPmem.h>
 #include <binder/MemoryHeapBase.h>
 
-#if HAVE_ANDROID_OS
+#ifdef HAVE_ANDROID_OS
 #include <linux/android_pmem.h>
 #endif
 
@@ -72,7 +72,7 @@
     memset(start_ptr, 0xda, size);
 #endif
 
-#if HAVE_ANDROID_OS
+#ifdef HAVE_ANDROID_OS
     if (size > 0) {
         const size_t pagesize = getpagesize();
         size = (size + pagesize-1) & ~(pagesize-1);
@@ -107,7 +107,7 @@
     // which means MemoryHeapPmem::revoke() wouldn't have been able to 
     // promote() it.
     
-#if HAVE_ANDROID_OS
+#ifdef HAVE_ANDROID_OS
     if (mSize != 0) {
         const sp<MemoryHeapPmem>& heap(getHeap());
         int our_fd = heap->heapID();
@@ -130,7 +130,7 @@
     : MemoryHeapBase()
 {
     char const * const device = pmemHeap->getDevice();
-#if HAVE_ANDROID_OS
+#ifdef HAVE_ANDROID_OS
     if (device) {
         int fd = open(device, O_RDWR | (flags & NO_CACHING ? O_SYNC : 0));
         LOGE_IF(fd<0, "couldn't open %s (%s)", device, strerror(errno));
@@ -187,7 +187,7 @@
 
 status_t MemoryHeapPmem::slap()
 {
-#if HAVE_ANDROID_OS
+#ifdef HAVE_ANDROID_OS
     size_t size = getSize();
     const size_t pagesize = getpagesize();
     size = (size + pagesize-1) & ~(pagesize-1);
@@ -205,7 +205,7 @@
 
 status_t MemoryHeapPmem::unslap()
 {
-#if HAVE_ANDROID_OS
+#ifdef HAVE_ANDROID_OS
     size_t size = getSize();
     const size_t pagesize = getpagesize();
     size = (size + pagesize-1) & ~(pagesize-1);
diff --git a/libs/surfaceflinger_client/ISurfaceComposerClient.cpp b/libs/surfaceflinger_client/ISurfaceComposerClient.cpp
index 2cc1f8e..7730eb1 100644
--- a/libs/surfaceflinger_client/ISurfaceComposerClient.cpp
+++ b/libs/surfaceflinger_client/ISurfaceComposerClient.cpp
@@ -157,7 +157,7 @@
      const int pid = ipc->getCallingPid();
      const int uid = ipc->getCallingUid();
      const int self_pid = getpid();
-     if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS)) {
+     if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != 0)) {
          // we're called from a different process, do the real check
          if (!checkCallingPermission(
                  String16("android.permission.ACCESS_SURFACE_FLINGER")))
diff --git a/libs/utils/SystemClock.cpp b/libs/utils/SystemClock.cpp
index 2bdc0ce..062e6d7 100644
--- a/libs/utils/SystemClock.cpp
+++ b/libs/utils/SystemClock.cpp
@@ -19,7 +19,7 @@
  * System clock functions.
  */
 
-#if HAVE_ANDROID_OS
+#ifdef HAVE_ANDROID_OS
 #include <linux/ioctl.h>
 #include <linux/rtc.h>
 #include <utils/Atomic.h>
@@ -50,7 +50,7 @@
     return -1;
 #else
     struct timeval tv;
-#if HAVE_ANDROID_OS
+#ifdef HAVE_ANDROID_OS
     struct timespec ts;
     int fd;
     int res;
@@ -66,7 +66,7 @@
 
     LOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec);
 
-#if HAVE_ANDROID_OS
+#ifdef HAVE_ANDROID_OS
     fd = open("/dev/alarm", O_RDWR);
     if(fd < 0) {
         LOGW("Unable to open alarm driver: %s\n", strerror(errno));
@@ -106,7 +106,7 @@
  */
 int64_t elapsedRealtime()
 {
-#if HAVE_ANDROID_OS
+#ifdef HAVE_ANDROID_OS
     static int s_fd = -1;
 
     if (s_fd == -1) {
diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp
index b1bd828..35dcbcb 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -739,7 +739,7 @@
     wp<Thread> weak(strong);
     self->mHoldSelf.clear();
 
-#if HAVE_ANDROID_OS
+#ifdef HAVE_ANDROID_OS
     // this is very useful for debugging with gdb
     self->mTid = gettid();
 #endif
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
index 8214e7f..8c78d60 100644
--- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
+++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
@@ -786,92 +786,92 @@
 
     /** Defines video profiles and levels. */
     public final class VideoProfile {
-        /** MPEG4, Simple Profile, Level 0. */
-        public static final int MPEG4_SP_LEVEL_0 = 0;
-
-        /** MPEG4, Simple Profile, Level 0B. */
-        public static final int MPEG4_SP_LEVEL_0B = 1;
-
-        /** MPEG4, Simple Profile, Level 1. */
-        public static final int MPEG4_SP_LEVEL_1 = 2;
-
-        /** MPEG4, Simple Profile, Level 2. */
-        public static final int MPEG4_SP_LEVEL_2 = 3;
-
-        /** MPEG4, Simple Profile, Level 3. */
-        public static final int MPEG4_SP_LEVEL_3 = 4;
-
         /** H263, Profile 0, Level 10. */
-        public static final int H263_PROFILE_0_LEVEL_10 = 5;
+        public static final int H263_PROFILE_0_LEVEL_10 = MediaProperties.H263_PROFILE_0_LEVEL_10;
 
         /** H263, Profile 0, Level 20. */
-        public static final int H263_PROFILE_0_LEVEL_20 = 6;
+        public static final int H263_PROFILE_0_LEVEL_20 = MediaProperties.H263_PROFILE_0_LEVEL_20;
 
         /** H263, Profile 0, Level 30. */
-        public static final int H263_PROFILE_0_LEVEL_30 = 7;
+        public static final int H263_PROFILE_0_LEVEL_30 = MediaProperties.H263_PROFILE_0_LEVEL_30;
 
         /** H263, Profile 0, Level 40. */
-        public static final int H263_PROFILE_0_LEVEL_40 = 8;
+        public static final int H263_PROFILE_0_LEVEL_40 = MediaProperties.H263_PROFILE_0_LEVEL_40;
 
         /** H263, Profile 0, Level 45. */
-        public static final int H263_PROFILE_0_LEVEL_45 = 9;
-
-        /** MPEG4, Simple Profile, Level 4A. */
-        public static final int MPEG4_SP_LEVEL_4A = 10;
+        public static final int H263_PROFILE_0_LEVEL_45 = MediaProperties.H263_PROFILE_0_LEVEL_45;
 
         /** MPEG4, Simple Profile, Level 0. */
-        public static final int MPEG4_SP_LEVEL_5 = 11;
+        public static final int MPEG4_SP_LEVEL_0 = MediaProperties.MPEG4_SP_LEVEL_0;
+
+        /** MPEG4, Simple Profile, Level 0B. */
+        public static final int MPEG4_SP_LEVEL_0B = MediaProperties.MPEG4_SP_LEVEL_0B;
+
+        /** MPEG4, Simple Profile, Level 1. */
+        public static final int MPEG4_SP_LEVEL_1 = MediaProperties.MPEG4_SP_LEVEL_1;
+
+        /** MPEG4, Simple Profile, Level 2. */
+        public static final int MPEG4_SP_LEVEL_2 = MediaProperties.MPEG4_SP_LEVEL_2;
+
+        /** MPEG4, Simple Profile, Level 3. */
+        public static final int MPEG4_SP_LEVEL_3 = MediaProperties.MPEG4_SP_LEVEL_3;
+
+        /** MPEG4, Simple Profile, Level 4A. */
+        public static final int MPEG4_SP_LEVEL_4A = MediaProperties.MPEG4_SP_LEVEL_4A;
+
+        /** MPEG4, Simple Profile, Level 0. */
+        public static final int MPEG4_SP_LEVEL_5 = MediaProperties.MPEG4_SP_LEVEL_5;
 
         /** H264, Profile 0, Level 1. */
-        public static final int H264_PROFILE_0_LEVEL_1 = 12;
+        public static final int H264_PROFILE_0_LEVEL_1 = MediaProperties.H264_PROFILE_0_LEVEL_1;
 
         /** H264, Profile 0, Level 1b. */
-        public static final int H264_PROFILE_0_LEVEL_1b = 13;
+        public static final int H264_PROFILE_0_LEVEL_1b = MediaProperties.H264_PROFILE_0_LEVEL_1B;
 
         /** H264, Profile 0, Level 1.1 */
-        public static final int H264_PROFILE_0_LEVEL_1_1 = 14;
+        public static final int H264_PROFILE_0_LEVEL_1_1 = MediaProperties.H264_PROFILE_0_LEVEL_1_1;
 
         /** H264, Profile 0, Level 1.2 */
-        public static final int H264_PROFILE_0_LEVEL_1_2 = 15;
+        public static final int H264_PROFILE_0_LEVEL_1_2 = MediaProperties.H264_PROFILE_0_LEVEL_1_2;
 
         /** H264, Profile 0, Level 1.3 */
-        public static final int H264_PROFILE_0_LEVEL_1_3 = 16;
+        public static final int H264_PROFILE_0_LEVEL_1_3 = MediaProperties.H264_PROFILE_0_LEVEL_1_3;
 
         /** H264, Profile 0, Level 2. */
-        public static final int H264_PROFILE_0_LEVEL_2 = 17;
+        public static final int H264_PROFILE_0_LEVEL_2 = MediaProperties.H264_PROFILE_0_LEVEL_2;
 
         /** H264, Profile 0, Level 2.1 */
-        public static final int H264_PROFILE_0_LEVEL_2_1 = 18;
+        public static final int H264_PROFILE_0_LEVEL_2_1 = MediaProperties.H264_PROFILE_0_LEVEL_2_1;
 
         /** H264, Profile 0, Level 2.2 */
-        public static final int H264_PROFILE_0_LEVEL_2_2 = 19;
+        public static final int H264_PROFILE_0_LEVEL_2_2 = MediaProperties.H264_PROFILE_0_LEVEL_2_2;
 
         /** H264, Profile 0, Level 3. */
-        public static final int H264_PROFILE_0_LEVEL_3 = 20;
+        public static final int H264_PROFILE_0_LEVEL_3 = MediaProperties.H264_PROFILE_0_LEVEL_3;
 
         /** H264, Profile 0, Level 3.1 */
-        public static final int H264_PROFILE_0_LEVEL_3_1 = 21;
+        public static final int H264_PROFILE_0_LEVEL_3_1 = MediaProperties.H264_PROFILE_0_LEVEL_3_1;
 
         /** H264, Profile 0, Level 3.2 */
-        public static final int H264_PROFILE_0_LEVEL_3_2 = 22;
+        public static final int H264_PROFILE_0_LEVEL_3_2 = MediaProperties.H264_PROFILE_0_LEVEL_3_2;
 
         /** H264, Profile 0, Level 4. */
-        public static final int H264_PROFILE_0_LEVEL_4 = 23;
+        public static final int H264_PROFILE_0_LEVEL_4 = MediaProperties.H264_PROFILE_0_LEVEL_4;
 
         /** H264, Profile 0, Level 4.1 */
-        public static final int H264_PROFILE_0_LEVEL_4_1 = 24;
+        public static final int H264_PROFILE_0_LEVEL_4_1 = MediaProperties.H264_PROFILE_0_LEVEL_4_1;
 
         /** H264, Profile 0, Level 4.2 */
-        public static final int H264_PROFILE_0_LEVEL_4_2 = 25;
+        public static final int H264_PROFILE_0_LEVEL_4_2 = MediaProperties.H264_PROFILE_0_LEVEL_4_2;
 
         /** H264, Profile 0, Level 5. */
-        public static final int H264_PROFILE_0_LEVEL_5 = 26;
+        public static final int H264_PROFILE_0_LEVEL_5 = MediaProperties.H264_PROFILE_0_LEVEL_5;
 
         /** H264, Profile 0, Level 5.1 */
-        public static final int H264_PROFILE_0_LEVEL_5_1 = 27;
+        public static final int H264_PROFILE_0_LEVEL_5_1 = MediaProperties.H264_PROFILE_0_LEVEL_5_1;
 
         /** Profile out of range. */
-        public static final int OUT_OF_RANGE = 255;
+        public static final int OUT_OF_RANGE = MediaProperties.UNSUPPORTED_PROFILE_LEVEL;
     }
 
     /** Defines video frame sizes. */
diff --git a/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp b/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
index 014cd95..73a7c9c 100755
--- a/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
+++ b/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
@@ -122,12 +122,26 @@
             &gotten, pEnv, file, NULL, M4OSA_NULL);
 
     result = M4OSA_fileReadOpen(&context, (M4OSA_Void*)pFile, M4OSA_kFileRead);
+
+    if(M4NO_ERROR != result) {
+        // Free the file path.
+        videoEditOsal_free(pFile);
+        pFile = M4OSA_NULL;
+    }
+
     videoEditJava_checkAndThrowIllegalArgumentException(&gotten, pEnv,
         (M4NO_ERROR != result), "file not found");
-    if(M4NO_ERROR != result)
-        return(properties);
-    result = M4OSA_fileReadClose(context);
-    context = M4OSA_NULL;
+
+    // Close the file and free the file context
+    if (context != NULL) {
+        result = M4OSA_fileReadClose(context);
+        context = M4OSA_NULL;
+    }
+
+    // Return if Error
+    if (M4NO_ERROR != result) {
+        return (properties); // NULL
+    }
 
     // Check if the file path is valid.
     if (gotten)
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 439e4ce..60bdd62 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -732,18 +732,14 @@
         return TEST_PLAYER;
     }
 
-    char value[PROPERTY_VALUE_MAX];
-    if (!property_get("media.httplive.disable-nuplayer", value, NULL)
-            || (strcasecmp(value, "true") && strcmp(value, "1"))) {
-        if (!strncasecmp("http://", url, 7)) {
-            size_t len = strlen(url);
-            if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
-                return NU_PLAYER;
-            }
+    if (!strncasecmp("http://", url, 7)) {
+        size_t len = strlen(url);
+        if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
+            return NU_PLAYER;
+        }
 
-            if (strstr(url,"m3u8")) {
-                return NU_PLAYER;
-            }
+        if (strstr(url,"m3u8")) {
+            return NU_PLAYER;
         }
     }
 
diff --git a/media/libstagefright/AACExtractor.cpp b/media/libstagefright/AACExtractor.cpp
new file mode 100644
index 0000000..4203b6e
--- /dev/null
+++ b/media/libstagefright/AACExtractor.cpp
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AACExtractor"
+#include <utils/Log.h>
+
+#include "include/AACExtractor.h"
+#include "include/avc_utils.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <utils/String8.h>
+
+namespace android {
+
+#define ADTS_HEADER_LENGTH 7
+
+class AACSource : public MediaSource {
+public:
+    AACSource(const sp<DataSource> &source,
+              const sp<MetaData> &meta,
+              const Vector<uint64_t> &offset_vector,
+              int64_t frame_duration_us);
+
+    virtual status_t start(MetaData *params = NULL);
+    virtual status_t stop();
+
+    virtual sp<MetaData> getFormat();
+
+    virtual status_t read(
+            MediaBuffer **buffer, const ReadOptions *options = NULL);
+
+protected:
+    virtual ~AACSource();
+
+private:
+    static const size_t kMaxFrameSize;
+    sp<DataSource> mDataSource;
+    sp<MetaData> mMeta;
+
+    off64_t mOffset;
+    int64_t mCurrentTimeUs;
+    bool mStarted;
+    MediaBufferGroup *mGroup;
+
+    Vector<uint64_t> mOffsetVector;
+    int64_t mFrameDurationUs;
+
+    AACSource(const AACSource &);
+    AACSource &operator=(const AACSource &);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Returns the sample rate based on the sampling frequency index
+uint32_t get_sample_rate(const uint8_t sf_index)
+{
+    static const uint32_t sample_rates[] =
+    {
+        96000, 88200, 64000, 48000, 44100, 32000,
+        24000, 22050, 16000, 12000, 11025, 8000
+    };
+
+    if (sf_index < sizeof(sample_rates) / sizeof(sample_rates[0])) {
+        return sample_rates[sf_index];
+    }
+
+    return 0;
+}
+
+static size_t getFrameSize(const sp<DataSource> &source, off64_t offset) {
+    size_t frameSize = 0;
+
+    uint8_t syncword[2];
+    if (source->readAt(0, &syncword, 2) != 2) {
+        return 0;
+    }
+    if ((syncword[0] != 0xff) || ((syncword[1] & 0xf6) != 0xf0)) {
+        return 0;
+    }
+
+    uint8_t protectionAbsent;
+    if (source->readAt(offset + 1, &protectionAbsent, 1) < 1) {
+        return 0;
+    }
+    protectionAbsent &= 0x1;
+
+    uint8_t header[3];
+    if (source->readAt(offset + 3, &header, 3) < 3) {
+        return 0;
+    }
+
+    frameSize = (header[0] & 0x3) << 11 | header[1] << 3 | header[2] >> 5;
+    frameSize += ADTS_HEADER_LENGTH + protectionAbsent ? 0 : 2;
+
+    return frameSize;
+}
+
+AACExtractor::AACExtractor(const sp<DataSource> &source)
+    : mDataSource(source),
+      mInitCheck(NO_INIT),
+      mFrameDurationUs(0) {
+    String8 mimeType;
+    float confidence;
+    if (!SniffAAC(mDataSource, &mimeType, &confidence, NULL)) {
+        return;
+    }
+
+    uint8_t profile, sf_index, channel, header[2];
+    if (mDataSource->readAt(2, &header, 2) < 2) {
+        return;
+    }
+
+    profile = (header[0] >> 6) & 0x3;
+    sf_index = (header[0] >> 2) & 0xf;
+    uint32_t sr = get_sample_rate(sf_index);
+    if (sr == 0) {
+        return;
+    }
+    channel = (header[0] & 0x1) << 2 | (header[1] >> 6);
+
+    mMeta = MakeAACCodecSpecificData(profile, sf_index, channel);
+
+    off64_t offset = 0;
+    off64_t streamSize, numFrames = 0;
+    size_t frameSize = 0;
+    int64_t duration = 0;
+
+    if (mDataSource->getSize(&streamSize) == OK) {
+         while (offset < streamSize) {
+            if ((frameSize = getFrameSize(source, offset)) == 0) {
+                return;
+            }
+
+            mOffsetVector.push(offset);
+
+            offset += frameSize;
+            numFrames ++;
+        }
+
+        // Round up and get the duration
+        mFrameDurationUs = (1024 * 1000000ll + (sr - 1)) / sr;
+        duration = numFrames * mFrameDurationUs;
+        mMeta->setInt64(kKeyDuration, duration);
+    }
+
+    mInitCheck = OK;
+}
+
+AACExtractor::~AACExtractor() {
+}
+
+sp<MetaData> AACExtractor::getMetaData() {
+    sp<MetaData> meta = new MetaData;
+
+    if (mInitCheck != OK) {
+        return meta;
+    }
+
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC_ADTS);
+
+    return meta;
+}
+
+size_t AACExtractor::countTracks() {
+    return mInitCheck == OK ? 1 : 0;
+}
+
+sp<MediaSource> AACExtractor::getTrack(size_t index) {
+    if (mInitCheck != OK || index != 0) {
+        return NULL;
+    }
+
+    return new AACSource(mDataSource, mMeta, mOffsetVector, mFrameDurationUs);
+}
+
+sp<MetaData> AACExtractor::getTrackMetaData(size_t index, uint32_t flags) {
+    if (mInitCheck != OK || index != 0) {
+        return NULL;
+    }
+
+    return mMeta;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+// 8192 = 2^13, 13bit AAC frame size (in bytes)
+const size_t AACSource::kMaxFrameSize = 8192;
+
+AACSource::AACSource(
+        const sp<DataSource> &source, const sp<MetaData> &meta,
+        const Vector<uint64_t> &offset_vector,
+        int64_t frame_duration_us)
+    : mDataSource(source),
+      mMeta(meta),
+      mOffset(0),
+      mCurrentTimeUs(0),
+      mStarted(false),
+      mGroup(NULL),
+      mOffsetVector(offset_vector),
+      mFrameDurationUs(frame_duration_us) {
+}
+
+AACSource::~AACSource() {
+    if (mStarted) {
+        stop();
+    }
+}
+
+status_t AACSource::start(MetaData *params) {
+    CHECK(!mStarted);
+
+    mOffset = 0;
+    mCurrentTimeUs = 0;
+    mGroup = new MediaBufferGroup;
+    mGroup->add_buffer(new MediaBuffer(kMaxFrameSize));
+    mStarted = true;
+
+    return OK;
+}
+
+status_t AACSource::stop() {
+    CHECK(mStarted);
+
+    delete mGroup;
+    mGroup = NULL;
+
+    mStarted = false;
+    return OK;
+}
+
+sp<MetaData> AACSource::getFormat() {
+    return mMeta;
+}
+
+status_t AACSource::read(
+        MediaBuffer **out, const ReadOptions *options) {
+    *out = NULL;
+
+    int64_t seekTimeUs;
+    ReadOptions::SeekMode mode;
+    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
+        if (mFrameDurationUs > 0) {
+            int64_t seekFrame = seekTimeUs / mFrameDurationUs;
+            mCurrentTimeUs = seekFrame * mFrameDurationUs;
+
+            mOffset = mOffsetVector.itemAt(seekFrame);
+        }
+    }
+
+    size_t frameSize, frameSizeWithoutHeader;
+    if ((frameSize = getFrameSize(mDataSource, mOffset)) == 0) {
+        return ERROR_END_OF_STREAM;
+    }
+
+    MediaBuffer *buffer;
+    status_t err = mGroup->acquire_buffer(&buffer);
+    if (err != OK) {
+        return err;
+    }
+
+    frameSizeWithoutHeader = frameSize - ADTS_HEADER_LENGTH;
+    if (mDataSource->readAt(mOffset + ADTS_HEADER_LENGTH, buffer->data(),
+                frameSizeWithoutHeader) != (ssize_t)frameSizeWithoutHeader) {
+        buffer->release();
+        buffer = NULL;
+
+        return ERROR_IO;
+    }
+
+    buffer->set_range(0, frameSizeWithoutHeader);
+    buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs);
+    buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+
+    mOffset += frameSize;
+    mCurrentTimeUs += mFrameDurationUs;
+
+    *out = buffer;
+    return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool SniffAAC(
+        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        sp<AMessage> *) {
+    uint8_t header[2];
+
+    if (source->readAt(0, &header, 2) != 2) {
+        return false;
+    }
+
+    // ADTS syncword
+    if ((header[0] == 0xff) && ((header[1] & 0xf6) == 0xf0)) {
+        *mimeType = MEDIA_MIMETYPE_AUDIO_AAC_ADTS;
+        *confidence = 0.2;
+        return true;
+    }
+
+    return false;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 029b238..53435f8 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -5,6 +5,7 @@
 
 LOCAL_SRC_FILES:=                         \
         ACodec.cpp                        \
+        AACExtractor.cpp                  \
         AMRExtractor.cpp                  \
         AMRWriter.cpp                     \
         AudioPlayer.cpp                   \
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index 7a1d73b..cd0e021 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -18,38 +18,54 @@
 #define LOG_TAG "AudioSource"
 #include <utils/Log.h>
 
-#include <media/stagefright/AudioSource.h>
-
 #include <media/AudioRecord.h>
-#include <media/stagefright/MediaBufferGroup.h>
-#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/AudioSource.h>
+#include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
+#include <media/stagefright/foundation/ADebug.h>
 #include <cutils/properties.h>
 #include <stdlib.h>
 
 namespace android {
 
+static void AudioRecordCallbackFunction(int event, void *user, void *info) {
+    AudioSource *source = (AudioSource *) user;
+    switch (event) {
+        case AudioRecord::EVENT_MORE_DATA: {
+            source->dataCallbackTimestamp(*((AudioRecord::Buffer *) info), systemTime() / 1000);
+            break;
+        }
+        case AudioRecord::EVENT_OVERRUN: {
+            LOGW("AudioRecord reported overrun!");
+            break;
+        }
+        default:
+            // does nothing
+            break;
+    }
+}
+
 AudioSource::AudioSource(
         int inputSource, uint32_t sampleRate, uint32_t channels)
     : mStarted(false),
-      mCollectStats(false),
+      mSampleRate(sampleRate),
       mPrevSampleTimeUs(0),
-      mTotalLostFrames(0),
-      mPrevLostBytes(0),
-      mGroup(NULL) {
+      mNumFramesReceived(0),
+      mNumClientOwnedBuffers(0) {
 
     LOGV("sampleRate: %d, channels: %d", sampleRate, channels);
     CHECK(channels == 1 || channels == 2);
     uint32_t flags = AudioRecord::RECORD_AGC_ENABLE |
                      AudioRecord::RECORD_NS_ENABLE  |
                      AudioRecord::RECORD_IIR_ENABLE;
-
     mRecord = new AudioRecord(
                 inputSource, sampleRate, AudioSystem::PCM_16_BIT,
                 channels > 1? AudioSystem::CHANNEL_IN_STEREO: AudioSystem::CHANNEL_IN_MONO,
                 4 * kMaxBufferSize / sizeof(int16_t), /* Enable ping-pong buffers */
-                flags);
+                flags,
+                AudioRecordCallbackFunction,
+                this);
 
     mInitCheck = mRecord->initCheck();
 }
@@ -68,6 +84,7 @@
 }
 
 status_t AudioSource::start(MetaData *params) {
+    Mutex::Autolock autoLock(mLock);
     if (mStarted) {
         return UNKNOWN_ERROR;
     }
@@ -76,12 +93,6 @@
         return NO_INIT;
     }
 
-    char value[PROPERTY_VALUE_MAX];
-    if (property_get("media.stagefright.record-stats", value, NULL)
-        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
-        mCollectStats = true;
-    }
-
     mTrackMaxAmplitude = false;
     mMaxAmplitude = 0;
     mInitialReadTimeUs = 0;
@@ -92,9 +103,6 @@
     }
     status_t err = mRecord->start();
     if (err == OK) {
-        mGroup = new MediaBufferGroup;
-        mGroup->add_buffer(new MediaBuffer(kMaxBufferSize));
-
         mStarted = true;
     } else {
         delete mRecord;
@@ -105,7 +113,25 @@
     return err;
 }
 
+void AudioSource::releaseQueuedFrames_l() {
+    LOGV("releaseQueuedFrames_l");
+    List<MediaBuffer *>::iterator it;
+    while (!mBuffersReceived.empty()) {
+        it = mBuffersReceived.begin();
+        (*it)->release();
+        mBuffersReceived.erase(it);
+    }
+}
+
+void AudioSource::waitOutstandingEncodingFrames_l() {
+    LOGV("waitOutstandingEncodingFrames_l: %lld", mNumClientOwnedBuffers);
+    while (mNumClientOwnedBuffers > 0) {
+        mFrameEncodingCompletionCondition.wait(mLock);
+    }
+}
+
 status_t AudioSource::stop() {
+    Mutex::Autolock autoLock(mLock);
     if (!mStarted) {
         return UNKNOWN_ERROR;
     }
@@ -114,29 +140,23 @@
         return NO_INIT;
     }
 
-    mRecord->stop();
-
-    delete mGroup;
-    mGroup = NULL;
-
     mStarted = false;
-
-    if (mCollectStats) {
-        LOGI("Total lost audio frames: %lld",
-            mTotalLostFrames + (mPrevLostBytes >> 1));
-    }
+    mRecord->stop();
+    waitOutstandingEncodingFrames_l();
+    releaseQueuedFrames_l();
 
     return OK;
 }
 
 sp<MetaData> AudioSource::getFormat() {
+    Mutex::Autolock autoLock(mLock);
     if (mInitCheck != OK) {
         return 0;
     }
 
     sp<MetaData> meta = new MetaData;
     meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
-    meta->setInt32(kKeySampleRate, mRecord->getSampleRate());
+    meta->setInt32(kKeySampleRate, mSampleRate);
     meta->setInt32(kKeyChannelCount, mRecord->channelCount());
     meta->setInt32(kKeyMaxInputSize, kMaxBufferSize);
 
@@ -177,121 +197,118 @@
 
 status_t AudioSource::read(
         MediaBuffer **out, const ReadOptions *options) {
+    Mutex::Autolock autoLock(mLock);
+    *out = NULL;
 
     if (mInitCheck != OK) {
         return NO_INIT;
     }
 
-    int64_t readTimeUs = systemTime() / 1000;
-    *out = NULL;
-
-    MediaBuffer *buffer;
-    CHECK_EQ(mGroup->acquire_buffer(&buffer), OK);
-
-    int err = 0;
-    if (mStarted) {
-
-        uint32_t numFramesRecorded;
-        mRecord->getPosition(&numFramesRecorded);
-
-
-        if (numFramesRecorded == 0 && mPrevSampleTimeUs == 0) {
-            mInitialReadTimeUs = readTimeUs;
-            // Initial delay
-            if (mStartTimeUs > 0) {
-                mStartTimeUs = readTimeUs - mStartTimeUs;
-            } else {
-                // Assume latency is constant.
-                mStartTimeUs += mRecord->latency() * 1000;
-            }
-            mPrevSampleTimeUs = mStartTimeUs;
-        }
-
-        uint32_t sampleRate = mRecord->getSampleRate();
-
-        // Insert null frames when lost frames are detected.
-        int64_t timestampUs = mPrevSampleTimeUs;
-        uint32_t numLostBytes = mRecord->getInputFramesLost() << 1;
-        numLostBytes += mPrevLostBytes;
-#if 0
-        // Simulate lost frames
-        numLostBytes = ((rand() * 1.0 / RAND_MAX)) * 2 * kMaxBufferSize;
-        numLostBytes &= 0xFFFFFFFE; // Alignment requirement
-
-        // Reduce the chance to lose
-        if (rand() * 1.0 / RAND_MAX >= 0.05) {
-            numLostBytes = 0;
-        }
-#endif
-        if (numLostBytes > 0) {
-            if (numLostBytes > kMaxBufferSize) {
-                mPrevLostBytes = numLostBytes - kMaxBufferSize;
-                numLostBytes = kMaxBufferSize;
-            } else {
-                mPrevLostBytes = 0;
-            }
-
-            CHECK_EQ(numLostBytes & 1, 0);
-            timestampUs += ((1000000LL * (numLostBytes >> 1)) +
-                    (sampleRate >> 1)) / sampleRate;
-
-            if (mCollectStats) {
-                mTotalLostFrames += (numLostBytes >> 1);
-            }
-            memset(buffer->data(), 0, numLostBytes);
-            buffer->set_range(0, numLostBytes);
-            if (numFramesRecorded == 0) {
-                buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs);
-            }
-            buffer->meta_data()->setInt64(kKeyTime, mStartTimeUs + mPrevSampleTimeUs);
-            buffer->meta_data()->setInt64(kKeyDriftTime, readTimeUs - mInitialReadTimeUs);
-            mPrevSampleTimeUs = timestampUs;
-            *out = buffer;
-            return OK;
-        }
-
-        ssize_t n = mRecord->read(buffer->data(), buffer->size());
-        if (n <= 0) {
-            buffer->release();
-            LOGE("Read from AudioRecord returns %d", n);
-            return UNKNOWN_ERROR;
-        }
-
-        int64_t recordDurationUs = (1000000LL * n >> 1) / sampleRate;
-        timestampUs += recordDurationUs;
-
-        if (mPrevSampleTimeUs - mStartTimeUs < kAutoRampStartUs) {
-            // Mute the initial video recording signal
-            memset((uint8_t *) buffer->data(), 0, n);
-        } else if (mPrevSampleTimeUs - mStartTimeUs < kAutoRampStartUs + kAutoRampDurationUs) {
-            int32_t autoRampDurationFrames =
-                    (kAutoRampDurationUs * sampleRate + 500000LL) / 1000000LL;
-
-            int32_t autoRampStartFrames =
-                    (kAutoRampStartUs * sampleRate + 500000LL) / 1000000LL;
-
-            int32_t nFrames = numFramesRecorded - autoRampStartFrames;
-            rampVolume(nFrames, autoRampDurationFrames, (uint8_t *) buffer->data(), n);
-        }
-        if (mTrackMaxAmplitude) {
-            trackMaxAmplitude((int16_t *) buffer->data(), n >> 1);
-        }
-
-        if (numFramesRecorded == 0) {
-            buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs);
-        }
-
-        buffer->meta_data()->setInt64(kKeyTime, mStartTimeUs + mPrevSampleTimeUs);
-        buffer->meta_data()->setInt64(kKeyDriftTime, readTimeUs - mInitialReadTimeUs);
-        mPrevSampleTimeUs = timestampUs;
-        LOGV("initial delay: %lld, sample rate: %d, timestamp: %lld",
-                mStartTimeUs, sampleRate, timestampUs);
-
-        buffer->set_range(0, n);
-
-        *out = buffer;
+    while (mStarted && mBuffersReceived.empty()) {
+        mFrameAvailableCondition.wait(mLock);
+    }
+    if (!mStarted) {
         return OK;
     }
+    MediaBuffer *buffer = *mBuffersReceived.begin();
+    mBuffersReceived.erase(mBuffersReceived.begin());
+    ++mNumClientOwnedBuffers;
+    buffer->setObserver(this);
+    buffer->add_ref();
+
+    // Mute/suppress the recording sound
+    int64_t timeUs;
+    CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
+    int64_t elapsedTimeUs = timeUs - mStartTimeUs;
+    if (elapsedTimeUs < kAutoRampStartUs) {
+        memset((uint8_t *) buffer->data(), 0, buffer->range_length());
+    } else if (elapsedTimeUs < kAutoRampStartUs + kAutoRampDurationUs) {
+        int32_t autoRampDurationFrames =
+                    (kAutoRampDurationUs * mSampleRate + 500000LL) / 1000000LL;
+
+        int32_t autoRampStartFrames =
+                    (kAutoRampStartUs * mSampleRate + 500000LL) / 1000000LL;
+
+        int32_t nFrames = mNumFramesReceived - autoRampStartFrames;
+        rampVolume(nFrames, autoRampDurationFrames,
+                (uint8_t *) buffer->data(), buffer->range_length());
+    }
+
+    // Track the max recording signal amplitude.
+    if (mTrackMaxAmplitude) {
+        trackMaxAmplitude(
+            (int16_t *) buffer->data(), buffer->range_length() >> 1);
+    }
+
+    *out = buffer;
+    return OK;
+}
+
+void AudioSource::signalBufferReturned(MediaBuffer *buffer) {
+    LOGV("signalBufferReturned: %p", buffer->data());
+    Mutex::Autolock autoLock(mLock);
+    --mNumClientOwnedBuffers;
+    buffer->setObserver(0);
+    buffer->release();
+    mFrameEncodingCompletionCondition.signal();
+    return;
+}
+
+status_t AudioSource::dataCallbackTimestamp(
+        const AudioRecord::Buffer& audioBuffer, int64_t timeUs) {
+    LOGV("dataCallbackTimestamp: %lld us", timeUs);
+    Mutex::Autolock autoLock(mLock);
+    if (!mStarted) {
+        LOGW("Spurious callback from AudioRecord. Drop the audio data.");
+        return OK;
+    }
+
+    if (mNumFramesReceived == 0 && mPrevSampleTimeUs == 0) {
+        mInitialReadTimeUs = timeUs;
+        // Initial delay
+        if (mStartTimeUs > 0) {
+            mStartTimeUs = timeUs - mStartTimeUs;
+        } else {
+            // Assume latency is constant.
+            mStartTimeUs += mRecord->latency() * 1000;
+        }
+        mPrevSampleTimeUs = mStartTimeUs;
+    }
+
+    int64_t timestampUs = mPrevSampleTimeUs;
+
+    size_t numLostBytes = mRecord->getInputFramesLost();
+    CHECK_EQ(numLostBytes & 1, 0u);
+    CHECK_EQ(audioBuffer.size & 1, 0u);
+    size_t bufferSize = numLostBytes + audioBuffer.size;
+    MediaBuffer *buffer = new MediaBuffer(bufferSize);
+    if (numLostBytes > 0) {
+        memset(buffer->data(), 0, numLostBytes);
+        memcpy((uint8_t *) buffer->data() + numLostBytes,
+                    audioBuffer.i16, audioBuffer.size);
+    } else {
+        if (audioBuffer.size == 0) {
+            LOGW("Nothing is available from AudioRecord callback buffer");
+            buffer->release();
+            return OK;
+        }
+        memcpy((uint8_t *) buffer->data(),
+                audioBuffer.i16, audioBuffer.size);
+    }
+
+    buffer->set_range(0, bufferSize);
+    timestampUs += ((1000000LL * (bufferSize >> 1)) +
+                    (mSampleRate >> 1)) / mSampleRate;
+
+    if (mNumFramesReceived == 0) {
+        buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs);
+    }
+    buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs);
+    buffer->meta_data()->setInt64(kKeyDriftTime, timeUs - mInitialReadTimeUs);
+    mPrevSampleTimeUs = timestampUs;
+    mNumFramesReceived += buffer->range_length() / sizeof(int16_t);
+    mBuffersReceived.push_back(buffer);
+    mFrameAvailableCondition.signal();
 
     return OK;
 }
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index cb08023..8866750 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -44,7 +44,6 @@
 
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/foundation/AMessage.h>
-#include "include/LiveSession.h"
 
 #define USE_SURFACE_ALLOC 1
 #define FRAME_DROP_FREQ 7
@@ -233,17 +232,6 @@
 
     mUri = uri;
 
-    if (!strncmp("http://", uri, 7)) {
-        // Hack to support http live.
-
-        size_t len = strlen(uri);
-        if (!strcasecmp(&uri[len - 5], ".m3u8")
-                || strstr(&uri[7], "m3u8") != NULL) {
-            mUri = "httplive://";
-            mUri.append(&uri[7]);
-        }
-    }
-
     if (headers) {
         mUriHeaders = *headers;
     }
@@ -376,14 +364,11 @@
 }
 
 void AwesomePlayer::reset() {
-    LOGI("reset");
-
     Mutex::Autolock autoLock(mLock);
     reset_l();
 }
 
 void AwesomePlayer::reset_l() {
-    LOGI("reset_l");
     mDisplayWidth = 0;
     mDisplayHeight = 0;
 
@@ -411,10 +396,6 @@
         }
     }
 
-    if (mFlags & PREPARING) {
-        LOGI("waiting until preparation is completed.");
-    }
-
     while (mFlags & PREPARING) {
         mPreparedCondition.wait(mLock);
     }
@@ -438,8 +419,6 @@
     }
     mAudioSource.clear();
 
-    LOGI("audio source cleared");
-
     mTimeSource = NULL;
 
     delete mAudioPlayer;
@@ -457,11 +436,6 @@
         mRTSPController.clear();
     }
 
-    if (mLiveSession != NULL) {
-        mLiveSession->disconnect();
-        mLiveSession.clear();
-    }
-
     if (mVideoSource != NULL) {
         mVideoSource->stop();
 
@@ -476,8 +450,6 @@
         IPCThreadState::self()->flushCommands();
     }
 
-    LOGI("video source cleared");
-
     mDurationUs = -1;
     mFlags = 0;
     mExtractorFlags = 0;
@@ -494,8 +466,6 @@
     mFileSource.clear();
 
     mBitrate = -1;
-
-    LOGI("reset_l completed");
 }
 
 void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
@@ -668,35 +638,6 @@
     postBufferingEvent_l();
 }
 
-void AwesomePlayer::partial_reset_l() {
-    // Only reset the video renderer and shut down the video decoder.
-    // Then instantiate a new video decoder and resume video playback.
-
-    mVideoRenderer.clear();
-
-    if (mVideoBuffer) {
-        mVideoBuffer->release();
-        mVideoBuffer = NULL;
-    }
-
-    {
-        mVideoSource->stop();
-
-        // The following hack is necessary to ensure that the OMX
-        // component is completely released by the time we may try
-        // to instantiate it again.
-        wp<MediaSource> tmp = mVideoSource;
-        mVideoSource.clear();
-        while (tmp.promote() != NULL) {
-            usleep(1000);
-        }
-        IPCThreadState::self()->flushCommands();
-    }
-
-    CHECK_EQ((status_t)OK,
-             initVideoDecoder(OMXCodec::kIgnoreCodecSpecificData));
-}
-
 void AwesomePlayer::onStreamDone() {
     // Posted whenever any stream finishes playing.
 
@@ -706,21 +647,7 @@
     }
     mStreamDoneEventPending = false;
 
-    if (mStreamDoneStatus == INFO_DISCONTINUITY) {
-        // This special status is returned because an http live stream's
-        // video stream switched to a different bandwidth at this point
-        // and future data may have been encoded using different parameters.
-        // This requires us to shutdown the video decoder and reinstantiate
-        // a fresh one.
-
-        LOGV("INFO_DISCONTINUITY");
-
-        CHECK(mVideoSource != NULL);
-
-        partial_reset_l();
-        postVideoEvent_l();
-        return;
-    } else if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
+    if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
         LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
 
         notifyListener_l(
@@ -1606,29 +1533,6 @@
             LOGI("Prepare cancelled while waiting for initial cache fill.");
             return UNKNOWN_ERROR;
         }
-    } else if (!strncasecmp(mUri.string(), "httplive://", 11)) {
-        String8 uri("http://");
-        uri.append(mUri.string() + 11);
-
-        if (mLooper == NULL) {
-            mLooper = new ALooper;
-            mLooper->setName("httplive");
-            mLooper->start();
-        }
-
-        mLiveSession = new LiveSession;
-        mLooper->registerHandler(mLiveSession);
-
-        mLiveSession->connect(uri.string());
-        dataSource = mLiveSession->getDataSource();
-
-        sp<MediaExtractor> extractor =
-            MediaExtractor::Create(dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
-
-        static_cast<MPEG2TSExtractor *>(extractor.get())
-            ->setLiveSession(mLiveSession);
-
-        return setDataSource_l(extractor);
     } else if (!strncasecmp("rtsp://", mUri.string(), 7)) {
         if (mLooper == NULL) {
             mLooper = new ALooper;
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index e06fa81..8f9c150 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -24,6 +24,7 @@
 #include "include/NuHTTPDataSource.h"
 #include "include/DRMExtractor.h"
 #include "include/FLACExtractor.h"
+#include "include/AACExtractor.h"
 
 #include "matroska/MatroskaExtractor.h"
 
@@ -109,6 +110,7 @@
     RegisterSniffer(SniffAMR);
     RegisterSniffer(SniffMPEG2TS);
     RegisterSniffer(SniffMP3);
+    RegisterSniffer(SniffAAC);
 
     char value[PROPERTY_VALUE_MAX];
     if (property_get("drm.service.enabled", value, NULL)
diff --git a/media/libstagefright/MediaDefs.cpp b/media/libstagefright/MediaDefs.cpp
index b50af89..0be7261 100644
--- a/media/libstagefright/MediaDefs.cpp
+++ b/media/libstagefright/MediaDefs.cpp
@@ -36,6 +36,7 @@
 const char *MEDIA_MIMETYPE_AUDIO_G711_MLAW = "audio/g711-mlaw";
 const char *MEDIA_MIMETYPE_AUDIO_RAW = "audio/raw";
 const char *MEDIA_MIMETYPE_AUDIO_FLAC = "audio/flac";
+const char *MEDIA_MIMETYPE_AUDIO_AAC_ADTS = "audio/aac-adts";
 
 const char *MEDIA_MIMETYPE_CONTAINER_MPEG4 = "video/mpeg4";
 const char *MEDIA_MIMETYPE_CONTAINER_WAV = "audio/wav";
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index 08ed206..dbd0829 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -27,6 +27,7 @@
 #include "include/DRMExtractor.h"
 #include "include/WVMExtractor.h"
 #include "include/FLACExtractor.h"
+#include "include/AACExtractor.h"
 
 #include "matroska/MatroskaExtractor.h"
 
@@ -98,6 +99,8 @@
         return new MPEG2TSExtractor(source);
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_WVM)) {
         return new WVMExtractor(source);
+    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC_ADTS)) {
+        return new AACExtractor(source);
     }
 
     return NULL;
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index fccd68c..5d502e7 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -3289,7 +3289,7 @@
 }
 
 status_t OMXCodec::stop() {
-    CODEC_LOGI("stop mState=%d", mState);
+    CODEC_LOGV("stop mState=%d", mState);
 
     Mutex::Autolock autoLock(mLock);
 
diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp
index fa12cf0..95cf2d3 100644
--- a/media/libstagefright/avc_utils.cpp
+++ b/media/libstagefright/avc_utils.cpp
@@ -329,5 +329,52 @@
     return foundIDR;
 }
 
+sp<MetaData> MakeAACCodecSpecificData(
+        unsigned profile, unsigned sampling_freq_index,
+        unsigned channel_configuration) {
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+
+    CHECK_LE(sampling_freq_index, 11u);
+    static const int32_t kSamplingFreq[] = {
+        96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
+        16000, 12000, 11025, 8000
+    };
+    meta->setInt32(kKeySampleRate, kSamplingFreq[sampling_freq_index]);
+    meta->setInt32(kKeyChannelCount, channel_configuration);
+
+    static const uint8_t kStaticESDS[] = {
+        0x03, 22,
+        0x00, 0x00,     // ES_ID
+        0x00,           // streamDependenceFlag, URL_Flag, OCRstreamFlag
+
+        0x04, 17,
+        0x40,                       // Audio ISO/IEC 14496-3
+        0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00,
+
+        0x05, 2,
+        // AudioSpecificInfo follows
+
+        // oooo offf fccc c000
+        // o - audioObjectType
+        // f - samplingFreqIndex
+        // c - channelConfig
+    };
+    sp<ABuffer> csd = new ABuffer(sizeof(kStaticESDS) + 2);
+    memcpy(csd->data(), kStaticESDS, sizeof(kStaticESDS));
+
+    csd->data()[sizeof(kStaticESDS)] =
+        ((profile + 1) << 3) | (sampling_freq_index >> 1);
+
+    csd->data()[sizeof(kStaticESDS) + 1] =
+        ((sampling_freq_index << 7) & 0x80) | (channel_configuration << 3);
+
+    meta->setData(kKeyESDS, 0, csd->data(), csd->size());
+
+    return meta;
+}
+
 }  // namespace android
 
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 0bed3ca..f7a9085 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -168,18 +168,6 @@
         CHECK_GT(mBandwidthItems.size(), 0u);
 
         mBandwidthItems.sort(SortByBandwidth);
-
-        char value[PROPERTY_VALUE_MAX];
-        if (property_get("media.httplive.disable-nuplayer", value, NULL)
-                && (!strcasecmp(value, "true") || !strcmp(value, "1"))) {
-            // The "legacy" player cannot deal with audio format changes,
-            // some streams use different audio encoding parameters for
-            // their lowest bandwidth stream.
-            if (mBandwidthItems.size() > 1) {
-                // XXX Remove the lowest bitrate stream for now...
-                mBandwidthItems.removeAt(0);
-            }
-        }
     }
 
     postMonitorQueue();
diff --git a/media/libstagefright/include/AACExtractor.h b/media/libstagefright/include/AACExtractor.h
new file mode 100644
index 0000000..8e5657b
--- /dev/null
+++ b/media/libstagefright/include/AACExtractor.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAC_EXTRACTOR_H_
+
+#define AAC_EXTRACTOR_H_
+
+#include <media/stagefright/MediaExtractor.h>
+
+#include <utils/Vector.h>
+
+namespace android {
+
+struct AMessage;
+class String8;
+
+class AACExtractor : public MediaExtractor {
+public:
+    AACExtractor(const sp<DataSource> &source);
+
+    virtual size_t countTracks();
+    virtual sp<MediaSource> getTrack(size_t index);
+    virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+
+    virtual sp<MetaData> getMetaData();
+
+protected:
+    virtual ~AACExtractor();
+
+private:
+    sp<DataSource> mDataSource;
+    sp<MetaData> mMeta;
+    status_t mInitCheck;
+
+    Vector<uint64_t> mOffsetVector;
+    int64_t mFrameDurationUs;
+
+    AACExtractor(const AACExtractor &);
+    AACExtractor &operator=(const AACExtractor &);
+};
+
+bool SniffAAC(
+        const sp<DataSource> &source, String8 *mimeType, float *confidence,
+        sp<AMessage> *);
+
+}  // namespace android
+
+#endif  // AAC_EXTRACTOR_H_
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 98b8c05..1497732 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -43,8 +43,6 @@
 class DrmManagerClinet;
 class DecryptHandle;
 
-struct LiveSession;
-
 struct AwesomeRenderer : public RefBase {
     AwesomeRenderer() {}
 
@@ -207,8 +205,6 @@
     sp<ARTSPController> mRTSPController;
     sp<ARTSPController> mConnectingRTSPController;
 
-    sp<LiveSession> mLiveSession;
-
     DrmManagerClient *mDrmManagerClient;
     DecryptHandle *mDecryptHandle;
 
@@ -219,7 +215,6 @@
     status_t setDataSource_l(const sp<DataSource> &dataSource);
     status_t setDataSource_l(const sp<MediaExtractor> &extractor);
     void reset_l();
-    void partial_reset_l();
     status_t seekTo_l(int64_t timeUs);
     status_t pause_l(bool at_eos = false);
     void initRenderer_l();
diff --git a/media/libstagefright/include/avc_utils.h b/media/libstagefright/include/avc_utils.h
index 3aeb07f..0218755 100644
--- a/media/libstagefright/include/avc_utils.h
+++ b/media/libstagefright/include/avc_utils.h
@@ -52,6 +52,10 @@
 
 const char *AVCProfileToString(uint8_t profile);
 
+sp<MetaData> MakeAACCodecSpecificData(
+        unsigned profile, unsigned sampling_freq_index,
+        unsigned channel_configuration);
+
 }  // namespace android
 
 #endif  // AVC_UTILS_H_
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index 4335b99..6056739 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -371,21 +371,6 @@
     mBuffer->setRange(0, 0);
 
     switch (type) {
-        case DISCONTINUITY_HTTPLIVE:
-        {
-            mQueue.clear(true);
-
-            if (mStreamType == 0x1b) {
-                // Don't signal discontinuities on audio streams.
-                if (mSource != NULL) {
-                    mSource->queueDiscontinuity(type);
-                } else {
-                    deferDiscontinuity(type);
-                }
-            }
-            break;
-        }
-
         case DISCONTINUITY_SEEK:
         case DISCONTINUITY_FORMATCHANGE:
         {
diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h
index ec3be84..455f9d5 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.h
+++ b/media/libstagefright/mpeg2ts/ATSParser.h
@@ -34,7 +34,6 @@
 struct ATSParser : public RefBase {
     enum DiscontinuityType {
         DISCONTINUITY_NONE,
-        DISCONTINUITY_HTTPLIVE,
         DISCONTINUITY_SEEK,
         DISCONTINUITY_FORMATCHANGE
     };
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index 73efdfe..dcaf9f7 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -341,54 +341,6 @@
     return timeUs;
 }
 
-// static
-sp<MetaData> ElementaryStreamQueue::MakeAACCodecSpecificData(
-        unsigned profile, unsigned sampling_freq_index,
-        unsigned channel_configuration) {
-    sp<MetaData> meta = new MetaData;
-    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
-
-    CHECK_LE(sampling_freq_index, 11u);
-    static const int32_t kSamplingFreq[] = {
-        96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
-        16000, 12000, 11025, 8000
-    };
-    meta->setInt32(kKeySampleRate, kSamplingFreq[sampling_freq_index]);
-    meta->setInt32(kKeyChannelCount, channel_configuration);
-
-    static const uint8_t kStaticESDS[] = {
-        0x03, 22,
-        0x00, 0x00,     // ES_ID
-        0x00,           // streamDependenceFlag, URL_Flag, OCRstreamFlag
-
-        0x04, 17,
-        0x40,                       // Audio ISO/IEC 14496-3
-        0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00,
-
-        0x05, 2,
-        // AudioSpecificInfo follows
-
-        // oooo offf fccc c000
-        // o - audioObjectType
-        // f - samplingFreqIndex
-        // c - channelConfig
-    };
-    sp<ABuffer> csd = new ABuffer(sizeof(kStaticESDS) + 2);
-    memcpy(csd->data(), kStaticESDS, sizeof(kStaticESDS));
-
-    csd->data()[sizeof(kStaticESDS)] =
-        ((profile + 1) << 3) | (sampling_freq_index >> 1);
-
-    csd->data()[sizeof(kStaticESDS) + 1] =
-        ((sampling_freq_index << 7) & 0x80) | (channel_configuration << 3);
-
-    meta->setData(kKeyESDS, 0, csd->data(), csd->size());
-
-    return meta;
-}
-
 struct NALPosition {
     size_t nalOffset;
     size_t nalSize;
diff --git a/media/libstagefright/mpeg2ts/ESQueue.h b/media/libstagefright/mpeg2ts/ESQueue.h
index 5b7957e..d081995 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.h
+++ b/media/libstagefright/mpeg2ts/ESQueue.h
@@ -61,10 +61,6 @@
     // returns its timestamp in us (or -1 if no time information).
     int64_t fetchTimestamp(size_t size);
 
-    static sp<MetaData> MakeAACCodecSpecificData(
-            unsigned profile, unsigned sampling_freq_index,
-            unsigned channel_configuration);
-
     DISALLOW_EVIL_CONSTRUCTORS(ElementaryStreamQueue);
 };
 
diff --git a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
index a1f0796..dfec47f 100644
--- a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
+++ b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
@@ -202,20 +202,13 @@
     LOGI("haveAudio=%d, haveVideo=%d", haveAudio, haveVideo);
 }
 
-static bool isDiscontinuity(const uint8_t *data, ssize_t size) {
-    return size == 188 && data[0] == 0x00;
-}
-
 status_t MPEG2TSExtractor::feedMore() {
     Mutex::Autolock autoLock(mLock);
 
     uint8_t packet[kTSPacketSize];
     ssize_t n = mDataSource->readAt(mOffset, packet, kTSPacketSize);
 
-    if (isDiscontinuity(packet, n)) {
-        LOGI("XXX discontinuity detected");
-        mParser->signalDiscontinuity(ATSParser::DISCONTINUITY_HTTPLIVE);
-    } else if (n < (ssize_t)kTSPacketSize) {
+    if (n < (ssize_t)kTSPacketSize) {
         return (n < 0) ? (status_t)n : ERROR_END_OF_STREAM;
     } else {
         mParser->feedTSPacket(packet, kTSPacketSize);
diff --git a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
index 13988cd..9f6bd29 100644
--- a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
+++ b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
@@ -104,7 +104,7 @@
       mNextExpectedSeqNoValid(false),
       mNextExpectedSeqNo(0),
       mAccessUnitDamaged(false) {
-    mIsGeneric = desc.startsWith("mpeg4-generic/");
+    mIsGeneric = !strncasecmp(desc.c_str(),"mpeg4-generic/", 14);
 
     if (mIsGeneric) {
         AString value;
diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp
index f0b858d..679dcab 100644
--- a/media/libstagefright/rtsp/APacketSource.cpp
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -637,7 +637,7 @@
 
         mFormat->setInt32(kKeyWidth, width);
         mFormat->setInt32(kKeyHeight, height);
-    } else if (!strncmp(desc.c_str(), "mpeg4-generic/", 14)) {
+    } else if (!strncasecmp(desc.c_str(), "mpeg4-generic/", 14)) {
         AString val;
         if (!GetAttribute(params.c_str(), "mode", &val)
                 || (strcasecmp(val.c_str(), "AAC-lbr")
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index 601f569..47de4e09 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -123,7 +123,7 @@
         struct sockaddr_in addr;
         memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
         addr.sin_family = AF_INET;
-        addr.sin_addr.s_addr = INADDR_ANY;
+        addr.sin_addr.s_addr = htonl(INADDR_ANY);
         addr.sin_port = htons(port);
 
         if (bind(*rtpSocket,
@@ -340,6 +340,8 @@
 }
 
 status_t ARTPConnection::receive(StreamInfo *s, bool receiveRTP) {
+    LOGV("receiving %s", receiveRTP ? "RTP" : "RTCP");
+
     CHECK(!s->mIsInjected);
 
     sp<ABuffer> buffer = new ABuffer(65536);
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
index 893a387..84c666f 100644
--- a/media/libstagefright/rtsp/ARTPSource.cpp
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -67,7 +67,7 @@
     } else  if (!strncmp(desc.c_str(), "AMR-WB/", 7)) {
         mAssembler = new AAMRAssembler(notify, true /* isWide */, params);
     } else if (!strncmp(desc.c_str(), "MP4V-ES/", 8)
-            || !strncmp(desc.c_str(), "mpeg4-generic/", 14)) {
+            || !strncasecmp(desc.c_str(), "mpeg4-generic/", 14)) {
         mAssembler = new AMPEG4ElementaryAssembler(notify, desc, params);
         mIssueFIRRequests = true;
     } else {
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index e936923..0740515 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -545,6 +545,10 @@
     return buffer;
 }
 
+static bool IsRTSPVersion(const AString &s) {
+    return s == "RTSP/1.0";
+}
+
 bool ARTSPConnection::receiveRTSPReponse() {
     AString statusLine;
 
@@ -584,13 +588,27 @@
         return false;
     }
 
-    AString statusCodeStr(
-            response->mStatusLine, space1 + 1, space2 - space1 - 1);
+    bool isRequest = false;
 
-    if (!ParseSingleUnsignedLong(
-                statusCodeStr.c_str(), &response->mStatusCode)
-            || response->mStatusCode < 100 || response->mStatusCode > 999) {
-        return false;
+    if (!IsRTSPVersion(AString(response->mStatusLine, 0, space1))) {
+        CHECK(IsRTSPVersion(
+                    AString(
+                        response->mStatusLine,
+                        space2 + 1,
+                        response->mStatusLine.size() - space2 - 1)));
+
+        isRequest = true;
+
+        response->mStatusCode = 0;
+    } else {
+        AString statusCodeStr(
+                response->mStatusLine, space1 + 1, space2 - space1 - 1);
+
+        if (!ParseSingleUnsignedLong(
+                    statusCodeStr.c_str(), &response->mStatusCode)
+                || response->mStatusCode < 100 || response->mStatusCode > 999) {
+            return false;
+        }
     }
 
     AString line;
@@ -680,7 +698,63 @@
         }
     }
 
-    return notifyResponseListener(response);
+    return isRequest
+        ? handleServerRequest(response)
+        : notifyResponseListener(response);
+}
+
+bool ARTSPConnection::handleServerRequest(const sp<ARTSPResponse> &request) {
+    // Implementation of server->client requests is optional for all methods
+    // but we do need to respond, even if it's just to say that we don't
+    // support the method.
+
+    ssize_t space1 = request->mStatusLine.find(" ");
+    CHECK_GE(space1, 0);
+
+    AString response;
+    response.append("RTSP/1.0 501 Not Implemented\r\n");
+
+    ssize_t i = request->mHeaders.indexOfKey("cseq");
+
+    if (i >= 0) {
+        AString value = request->mHeaders.valueAt(i);
+
+        unsigned long cseq;
+        if (!ParseSingleUnsignedLong(value.c_str(), &cseq)) {
+            return false;
+        }
+
+        response.append("CSeq: ");
+        response.append(cseq);
+        response.append("\r\n");
+    }
+
+    response.append("\r\n");
+
+    size_t numBytesSent = 0;
+    while (numBytesSent < response.size()) {
+        ssize_t n =
+            send(mSocket, response.c_str() + numBytesSent,
+                 response.size() - numBytesSent, 0);
+
+        if (n == 0) {
+            // Server closed the connection.
+            LOGE("Server unexpectedly closed the connection.");
+
+            return false;
+        } else if (n < 0) {
+            if (errno == EINTR) {
+                continue;
+            }
+
+            LOGE("Error sending rtsp response.");
+            return false;
+        }
+
+        numBytesSent += (size_t)n;
+    }
+
+    return true;
 }
 
 // static
diff --git a/media/libstagefright/rtsp/ARTSPConnection.h b/media/libstagefright/rtsp/ARTSPConnection.h
index 19be2a6..0fecf3c 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.h
+++ b/media/libstagefright/rtsp/ARTSPConnection.h
@@ -109,6 +109,8 @@
     status_t findPendingRequest(
             const sp<ARTSPResponse> &response, ssize_t *index) const;
 
+    bool handleServerRequest(const sp<ARTSPResponse> &request);
+
     static bool ParseSingleUnsignedLong(
             const char *from, unsigned long *x);
 
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
index 3e710dc..f03f7a2 100644
--- a/media/libstagefright/rtsp/ASessionDescription.cpp
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -71,6 +71,11 @@
             line.setTo(desc, i, eolPos - i);
         }
 
+        if (line.empty()) {
+            i = eolPos + 1;
+            continue;
+        }
+
         if (line.size() < 2 || line.c_str()[1] != '=') {
             return false;
         }
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index ba7c1b2..d15d9c5 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -38,6 +38,7 @@
 
 #include <arpa/inet.h>
 #include <sys/socket.h>
+#include <netdb.h>
 
 // If no access units are received within 5 secs, assume that the rtp
 // stream has ended and signal end of stream.
@@ -121,9 +122,10 @@
         // want to transmit user/pass in cleartext.
         AString host, path, user, pass;
         unsigned port;
-        if (ARTSPConnection::ParseURL(
-                    mSessionURL.c_str(), &host, &port, &path, &user, &pass)
-                && user.size() > 0) {
+        CHECK(ARTSPConnection::ParseURL(
+                    mSessionURL.c_str(), &host, &port, &path, &user, &pass));
+
+        if (user.size() > 0) {
             mSessionURL.clear();
             mSessionURL.append("rtsp://");
             mSessionURL.append(host);
@@ -133,6 +135,8 @@
 
             LOGI("rewritten session url: '%s'", mSessionURL.c_str());
         }
+
+        mSessionHost = host;
     }
 
     void connect(const sp<AMessage> &doneMsg) {
@@ -248,34 +252,64 @@
     // In case we're behind NAT, fire off two UDP packets to the remote
     // rtp/rtcp ports to poke a hole into the firewall for future incoming
     // packets. We're going to send an RR/SDES RTCP packet to both of them.
-    void pokeAHole(int rtpSocket, int rtcpSocket, const AString &transport) {
+    bool pokeAHole(int rtpSocket, int rtcpSocket, const AString &transport) {
+        struct sockaddr_in addr;
+        memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
+        addr.sin_family = AF_INET;
+
         AString source;
         AString server_port;
         if (!GetAttribute(transport.c_str(),
                           "source",
-                          &source)
-                || !GetAttribute(transport.c_str(),
+                          &source)) {
+            LOGW("Missing 'source' field in Transport response. Using "
+                 "RTSP endpoint address.");
+
+            struct hostent *ent = gethostbyname(mSessionHost.c_str());
+            if (ent == NULL) {
+                LOGE("Failed to look up address of session host '%s'",
+                     mSessionHost.c_str());
+
+                return false;
+            }
+
+            addr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
+        } else {
+            addr.sin_addr.s_addr = inet_addr(source.c_str());
+        }
+
+        if (!GetAttribute(transport.c_str(),
                                  "server_port",
                                  &server_port)) {
-            return;
+            LOGI("Missing 'server_port' field in Transport response.");
+            return false;
         }
 
         int rtpPort, rtcpPort;
         if (sscanf(server_port.c_str(), "%d-%d", &rtpPort, &rtcpPort) != 2
                 || rtpPort <= 0 || rtpPort > 65535
                 || rtcpPort <=0 || rtcpPort > 65535
-                || rtcpPort != rtpPort + 1
-                || (rtpPort & 1) != 0) {
-            return;
+                || rtcpPort != rtpPort + 1) {
+            LOGE("Server picked invalid RTP/RTCP port pair %s,"
+                 " RTP port must be even, RTCP port must be one higher.",
+                 server_port.c_str());
+
+            return false;
         }
 
-        struct sockaddr_in addr;
-        memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
-        addr.sin_family = AF_INET;
-        addr.sin_addr.s_addr = inet_addr(source.c_str());
+        if (rtpPort & 1) {
+            LOGW("Server picked an odd RTP port, it should've picked an "
+                 "even one, we'll let it pass for now, but this may break "
+                 "in the future.");
+        }
 
         if (addr.sin_addr.s_addr == INADDR_NONE) {
-            return;
+            return true;
+        }
+
+        if (IN_LOOPBACK(ntohl(addr.sin_addr.s_addr))) {
+            // No firewalls to traverse on the loopback interface.
+            return true;
         }
 
         // Make up an RR/SDES RTCP packet.
@@ -289,16 +323,26 @@
         ssize_t n = sendto(
                 rtpSocket, buf->data(), buf->size(), 0,
                 (const sockaddr *)&addr, sizeof(addr));
-        CHECK_EQ(n, (ssize_t)buf->size());
+
+        if (n < (ssize_t)buf->size()) {
+            LOGE("failed to poke a hole for RTP packets");
+            return false;
+        }
 
         addr.sin_port = htons(rtcpPort);
 
         n = sendto(
                 rtcpSocket, buf->data(), buf->size(), 0,
                 (const sockaddr *)&addr, sizeof(addr));
-        CHECK_EQ(n, (ssize_t)buf->size());
+
+        if (n < (ssize_t)buf->size()) {
+            LOGE("failed to poke a hole for RTCP packets");
+            return false;
+        }
 
         LOGV("successfully poked holes.");
+
+        return true;
     }
 
     virtual void onMessageReceived(const sp<AMessage> &msg) {
@@ -381,6 +425,7 @@
                                 response->mContent->size());
 
                         if (!mSessionDesc->isValid()) {
+                            LOGE("Failed to parse session description.");
                             result = ERROR_MALFORMED;
                         } else {
                             ssize_t i = response->mHeaders.indexOfKey("content-base");
@@ -395,6 +440,25 @@
                                 }
                             }
 
+                            if (!mBaseURL.startsWith("rtsp://")) {
+                                // Some misbehaving servers specify a relative
+                                // URL in one of the locations above, combine
+                                // it with the absolute session URL to get
+                                // something usable...
+
+                                LOGW("Server specified a non-absolute base URL"
+                                     ", combining it with the session URL to "
+                                     "get something usable...");
+
+                                AString tmp;
+                                CHECK(MakeURL(
+                                            mSessionURL.c_str(),
+                                            mBaseURL.c_str(),
+                                            &tmp));
+
+                                mBaseURL = tmp;
+                            }
+
                             CHECK_GT(mSessionDesc->countTracks(), 1u);
                             setupTrack(1);
                         }
@@ -455,9 +519,12 @@
                         if (!track->mUsingInterleavedTCP) {
                             AString transport = response->mHeaders.valueAt(i);
 
-                            pokeAHole(track->mRTPSocket,
-                                      track->mRTCPSocket,
-                                      transport);
+                            // We are going to continue even if we were
+                            // unable to poke a hole into the firewall...
+                            pokeAHole(
+                                    track->mRTPSocket,
+                                    track->mRTCPSocket,
+                                    transport);
                         }
 
                         mRTPConn->addStream(
@@ -853,17 +920,16 @@
             case 'tiou':
             {
                 if (!mReceivedFirstRTCPPacket) {
-                    if (mTryFakeRTCP) {
-                        LOGW("Never received any data, disconnecting.");
-                        (new AMessage('abor', id()))->post();
-                    } else if (mTryTCPInterleaving && mReceivedFirstRTPPacket) {
+                    if (mReceivedFirstRTPPacket && !mTryFakeRTCP) {
                         LOGW("We received RTP packets but no RTCP packets, "
                              "using fake timestamps.");
 
                         mTryFakeRTCP = true;
 
                         mReceivedFirstRTCPPacket = true;
-                    } else {
+
+                        fakeTimestamps();
+                    } else if (!mReceivedFirstRTPPacket && !mTryTCPInterleaving) {
                         LOGW("Never received any data, switching transports.");
 
                         mTryTCPInterleaving = true;
@@ -871,6 +937,9 @@
                         sp<AMessage> msg = new AMessage('abor', id());
                         msg->setInt32("reconnect", true);
                         msg->post();
+                    } else {
+                        LOGW("Never received any data, disconnecting.");
+                        (new AMessage('abor', id()))->post();
                     }
                 }
                 break;
@@ -1016,6 +1085,7 @@
     sp<ASessionDescription> mSessionDesc;
     AString mOriginalSessionURL;  // This one still has user:pass@
     AString mSessionURL;
+    AString mSessionHost;
     AString mBaseURL;
     AString mSessionID;
     bool mSetupTracksSuccessful;
@@ -1158,6 +1228,12 @@
         return true;
     }
 
+    void fakeTimestamps() {
+        for (size_t i = 0; i < mTracks.size(); ++i) {
+            onTimeUpdate(i, 0, 0ll);
+        }
+    }
+
     void onTimeUpdate(int32_t trackIndex, uint32_t rtpTime, uint64_t ntpTime) {
         LOGV("onTimeUpdate track %d, rtpTime = 0x%08x, ntpTime = 0x%016llx",
              trackIndex, rtpTime, ntpTime);
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index fb1b073..4ea8849 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -38,6 +38,7 @@
 
 namespace android {
 
+#if 0
 static bool isMtpDevice(uint16_t vendor, uint16_t product) {
     // Sandisk Sansa Fuze
     if (vendor == 0x0781 && product == 0x74c2)
@@ -47,6 +48,7 @@
         return true;
     return false;
 }
+#endif
 
 MtpDevice* MtpDevice::open(const char* deviceName, int fd) {
     struct usb_device *device = usb_device_new(deviceName, fd);
@@ -91,7 +93,9 @@
                 LOGD("Found MTP device: \"%s\" \"%s\"\n", manufacturerName, productName);
                 free(manufacturerName);
                 free(productName);
-            } else {
+            }
+#if 0
+             else {
                 // look for special cased devices based on vendor/product ID
                 // we are doing this mainly for testing purposes
                 uint16_t vendor = usb_device_get_vendor_id(device);
@@ -119,7 +123,7 @@
                     printf("no MTP string\n");
                 }
             }
-
+#endif
             // if we got here, then we have a likely MTP or PTP device
 
             // interface should be followed by three endpoints
diff --git a/media/tests/MediaFrameworkTest/AndroidManifest.xml b/media/tests/MediaFrameworkTest/AndroidManifest.xml
index c9d2628b..dd5e026 100644
--- a/media/tests/MediaFrameworkTest/AndroidManifest.xml
+++ b/media/tests/MediaFrameworkTest/AndroidManifest.xml
@@ -22,6 +22,8 @@
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+
     <application>    
         <uses-library android:name="android.test.runner" />
         <activity android:label="@string/app_name"
diff --git a/media/tests/MediaFrameworkTest/res/layout/surface_view.xml b/media/tests/MediaFrameworkTest/res/layout/surface_view.xml
index a72c283..4999e5d 100644
--- a/media/tests/MediaFrameworkTest/res/layout/surface_view.xml
+++ b/media/tests/MediaFrameworkTest/res/layout/surface_view.xml
@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
+<!-- Copyright (C) 2011 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
      You may obtain a copy of the License at
-  
+
           http://www.apache.org/licenses/LICENSE-2.0
-  
+
      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -14,29 +14,33 @@
      limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    
-  android:layout_width="match_parent" 
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+  android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="vertical">
 
   <FrameLayout
     android:layout_width="match_parent"
     android:layout_height="match_parent">
-    
+
   <SurfaceView
      android:id="@+id/surface_view"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:layout_centerInParent="true"
      />
-     
-  <VideoView 
-   android:id="@+id/video_view" 
+
+  <ImageView android:id="@+id/overlay_layer"
+     android:layout_width="0dip"
+     android:layout_height="392dip"/>
+
+  <VideoView
+   android:id="@+id/video_view"
         android:layout_width="320px"
         android:layout_height="240px"
   />
-  
+
   </FrameLayout>
-    
+
 </LinearLayout>
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java
index 9fb49b1..79fd2cb 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2011 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
 import android.media.MediaPlayer;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.PowerManager;
 import android.provider.Downloads;
 import android.util.Log;
 import android.util.Log;
@@ -40,12 +41,15 @@
 import android.widget.VideoView;
 import com.android.mediaframeworktest.MediaNames;
 
+import android.graphics.Bitmap;
+import android.widget.ImageView;
+
 import java.io.File;
 import java.io.FileDescriptor;
 import java.net.InetAddress;
 
  
-public class MediaFrameworkTest extends Activity {
+public class MediaFrameworkTest extends Activity implements SurfaceHolder.Callback {
     
     //public static Surface video_sf;
     public static SurfaceView mSurfaceView;
@@ -58,27 +62,60 @@
     public static AssetFileDescriptor midiafd;
     public static AssetFileDescriptor mp3afd;
     
-    
+    public static Bitmap mDestBitmap;
+    public static ImageView mOverlayView;
+    private SurfaceHolder mSurfaceHolder = null;
+    private String TAG = "MediaFrameworkTest";
+    private PowerManager.WakeLock mWakeLock = null;
+
     public MediaFrameworkTest() {
     }
 
-    
     /** Called when the activity is first created. */
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
         setContentView(R.layout.surface_view);
         mSurfaceView = (SurfaceView)findViewById(R.id.surface_view);
+        mOverlayView = (ImageView)findViewById(R.id.overlay_layer);
         ViewGroup.LayoutParams lp = mSurfaceView.getLayoutParams();
-        mSurfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+        mSurfaceHolder = mSurfaceView.getHolder();
+        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+        mSurfaceHolder.addCallback(this);
         
         //Get the midi fd
         midiafd = this.getResources().openRawResourceFd(R.raw.testmidi);
         
         //Get the mp3 fd
         mp3afd = this.getResources().openRawResourceFd(R.raw.testmp3);
+        mOverlayView.setLayoutParams(lp);
+        mDestBitmap = Bitmap.createBitmap((int)640, (int)480, Bitmap.Config.ARGB_8888);
+        mOverlayView.setImageBitmap(mDestBitmap);
+
+        //Acquire the full wake lock to keep the device up
+        PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "MediaFrameworkTest");
+        mWakeLock.acquire();
     }
-    
+
+    public void onStop(Bundle icicle) {
+        mWakeLock.release();
+    }
+
+    public void surfaceDestroyed(SurfaceHolder holder) {
+        //Can do nothing in here. The test case will fail if the surface destroyed.
+        Log.v(TAG, "Test application surface destroyed");
+        mSurfaceHolder = null;
+    }
+
+    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+        //Do nothing in here. Just print out the log
+        Log.v(TAG, "Test application surface changed");
+    }
+
+    public void surfaceCreated(SurfaceHolder holder) {
+    }
+
     public void startPlayback(String filename){
       String mimetype = "audio/mpeg";
       Uri path = Uri.parse(filename);
@@ -148,4 +185,9 @@
       InetAddress address = InetAddress.getByAddress(MediaNames.STREAM_SERVER);
       return address.isReachable(10000);
   }
+
+  public static void testInvalidateOverlay() {
+      mOverlayView.invalidate();
+  }
+
 }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
index 1862fd5..f3cf0f7 100755
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
@@ -33,8 +33,11 @@
 import com.android.mediaframeworktest.functional.MediaVirtualizerTest;
 import com.android.mediaframeworktest.functional.MediaVisualizerTest;
 /*import for VideoEditor Test cases*/
+import com.android.mediaframeworktest.functional.MediaItemThumbnailTest;
+import com.android.mediaframeworktest.functional.MediaPropertiesTest;
 import com.android.mediaframeworktest.functional.VideoEditorAPITest;
-
+import com.android.mediaframeworktest.functional.VideoEditorExportTest;
+import com.android.mediaframeworktest.functional.VideoEditorPreviewTest;
 import junit.framework.TestSuite;
 
 import android.test.InstrumentationTestRunner;
@@ -73,7 +76,11 @@
         suite.addTestSuite(MediaVirtualizerTest.class);
         suite.addTestSuite(MediaVisualizerTest.class);
         /*Test for Video Editor*/
+        suite.addTestSuite(MediaItemThumbnailTest.class);
+        suite.addTestSuite(MediaPropertiesTest.class);
         suite.addTestSuite(VideoEditorAPITest.class);
+        suite.addTestSuite(VideoEditorExportTest.class);
+        suite.addTestSuite(VideoEditorPreviewTest.class);
         return suite;
     }
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
index cad7e53..44707401 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
@@ -60,11 +60,11 @@
     private static boolean onPrepareSuccess = false;
     public static boolean onCompleteSuccess = false;
     public static boolean mPlaybackError = false;
-    public static boolean mIsMediaInfoUnknown = false;
-    public static boolean mIsMediaInfoVideoTrackLagging = false;
-    public static boolean mIsMediaInfoBadInterleaving = false;
-    public static boolean mIsMediaInfoNotSeekable = false;
-    public static boolean mIsMediaInfoMetdataUpdate = false;
+    public static int mMediaInfoUnknownCount = 0;
+    public static int mMediaInfoVideoTrackLaggingCount = 0;
+    public static int mMediaInfoBadInterleavingCount = 0;
+    public static int mMediaInfoNotSeekableCount = 0;
+    public static int mMediaInfoMetdataUpdateCount = 0;
 
     public static String printCpuInfo(){      
         String cm = "dumpsys cpuinfo";
@@ -765,19 +765,19 @@
         public boolean onInfo(MediaPlayer mp, int what, int extra) {
             switch (what){
                 case MediaPlayer.MEDIA_INFO_UNKNOWN:
-                    mIsMediaInfoUnknown = true;
+                    mMediaInfoUnknownCount++;
                     break;
                 case MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING:
-                    mIsMediaInfoVideoTrackLagging = true;
+                    mMediaInfoVideoTrackLaggingCount++;
                     break;
                 case MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING:
-                    mIsMediaInfoBadInterleaving = true;
+                    mMediaInfoBadInterleavingCount++;
                     break;
                 case MediaPlayer.MEDIA_INFO_NOT_SEEKABLE:
-                    mIsMediaInfoNotSeekable = true;
+                    mMediaInfoNotSeekableCount++;
                     break;
                 case MediaPlayer.MEDIA_INFO_METADATA_UPDATE:
-                    mIsMediaInfoMetdataUpdate = true;
+                    mMediaInfoMetdataUpdateCount++;
                     break;
             }
             return true;
@@ -791,11 +791,11 @@
         int nextPosition = 0;
         int waittime = 0;
         onCompleteSuccess = false;
-        mIsMediaInfoUnknown = false;
-        mIsMediaInfoVideoTrackLagging = false;
-        mIsMediaInfoBadInterleaving = false;
-        mIsMediaInfoNotSeekable = false;
-        mIsMediaInfoMetdataUpdate = false;
+        mMediaInfoUnknownCount = 0;
+        mMediaInfoVideoTrackLaggingCount = 0;
+        mMediaInfoBadInterleavingCount = 0;
+        mMediaInfoNotSeekableCount = 0;
+        mMediaInfoMetdataUpdateCount = 0;
         mPlaybackError = false;
         String testResult;
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaItemThumbnailTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaItemThumbnailTest.java
new file mode 100755
index 0000000..895ca25
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaItemThumbnailTest.java
@@ -0,0 +1,954 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.mediaframeworktest.functional;
+
+import java.io.File;
+import java.io.IOException;
+
+import android.graphics.Bitmap;
+import android.media.videoeditor.MediaImageItem;
+import android.media.videoeditor.MediaItem;
+import android.media.videoeditor.MediaVideoItem;
+import android.media.videoeditor.VideoEditor;
+import android.os.Environment;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import com.android.mediaframeworktest.VideoEditorHelper;
+
+public class MediaItemThumbnailTest extends
+    ActivityInstrumentationTestCase<MediaFrameworkTest> {
+    private final String TAG = "MediaItemThumbailTest";
+
+    private final String PROJECT_LOCATION = VideoEditorHelper.PROJECT_LOCATION_COMMON;
+
+    private final String INPUT_FILE_PATH = VideoEditorHelper.INPUT_FILE_PATH_COMMON;
+
+    private VideoEditor mVideoEditor;
+
+    private VideoEditorHelper mVideoEditorHelper;
+
+    public MediaItemThumbnailTest() {
+        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        // setup for each test case.
+        super.setUp();
+        mVideoEditorHelper = new VideoEditorHelper();
+        // Create a random String which will be used as project path, where all
+        // project related files will be stored.
+        final String projectPath = mVideoEditorHelper.
+            createRandomFile(PROJECT_LOCATION);
+        mVideoEditor = mVideoEditorHelper.createVideoEditor(projectPath);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mVideoEditorHelper.destroyVideoEditor(mVideoEditor);
+        // Clean the directory created as project path
+        mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath()));
+        System.gc();
+        super.tearDown();
+    }
+
+    protected void validateThumbnail(Bitmap thumbNailBmp, int outWidth,
+        int outHeight) throws Exception {
+        assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
+        assertEquals("Thumbnail Height", outHeight, thumbNailBmp.getHeight());
+        assertEquals("Thumbnail Width", outWidth, thumbNailBmp.getWidth());
+        thumbNailBmp.recycle();
+    }
+
+    // -----------------------------------------------------------------
+    // THUMBNAIL
+    // -----------------------------------------------------------------
+    /**
+     * To test thumbnail / frame extraction on H.263 QCIF.
+     */
+    // TODO : TC_TN_001
+    @LargeTest
+    public void testThumbnailForH263QCIF() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
+        final int atTime = 0;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+
+        final int outWidth = (mediaVideoItem.getWidth() / 2);
+        final int outHeight = mediaVideoItem.getHeight();
+
+        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
+            outHeight, atTime);
+        validateThumbnail(thumbNailBmp, outWidth, outHeight);
+    }
+
+    /**
+     * To test thumbnail / frame extraction on MPEG4 VGA .
+     */
+    // TODO : TC_TN_002
+    @LargeTest
+    public void testThumbnailForMPEG4VGA() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH +
+            "MPEG4_SP_640x480_30fps_512Kbps_0_23.3gp";
+        final int atTime = 0;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+        final int outWidth = (mediaVideoItem.getWidth() / 2);
+        final int outHeight = mediaVideoItem.getHeight();
+        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
+            outHeight, atTime);
+        validateThumbnail(thumbNailBmp, outWidth, outHeight);
+    }
+
+    /**
+     * To test thumbnail / frame extraction on MPEG4 NTSC.
+     */
+    // TODO : TC_TN_003
+    @LargeTest
+    public void testThumbnailForMPEG4NTSC() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
+        final int atTime = 0;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+        final int outWidth = mediaVideoItem.getWidth() / 2;
+        final int outHeight = mediaVideoItem.getHeight() / 2;
+        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
+            outHeight, atTime);
+        validateThumbnail(thumbNailBmp, outWidth, outHeight);
+    }
+
+    /**
+     * To test thumbnail / frame extraction on MPEG4 WVGA.
+     */
+    // TODO : TC_TN_004
+    @LargeTest
+    public void testThumbnailForMPEG4WVGA() throws Exception {
+
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "MPEG4_SP_800x480_515kbps_15fps_AMR_NB_8KHz_12.2kbps_m_0_26.mp4";
+        final int atTime = 0;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+        final int outWidth = mediaVideoItem.getWidth() * 2;
+        final int outHeight = mediaVideoItem.getHeight();
+        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
+            outHeight, atTime);
+        validateThumbnail(thumbNailBmp, outWidth, outHeight);
+    }
+
+    /**
+     * To test thumbnail / frame extraction on MPEG4 QCIF.
+     */
+    // TODO : TC_TN_005
+    @LargeTest
+    public void testThumbnailForMPEG4QCIF() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
+        final int atTime = 0;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+        final int outWidth = mediaVideoItem.getWidth();
+        final int outHeight = mediaVideoItem.getHeight() * 2;
+        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
+            outHeight, atTime);
+        validateThumbnail(thumbNailBmp, outWidth, outHeight);
+    }
+
+    /**
+     * To test thumbnail / frame extraction on H264 QCIF.
+     */
+    // TODO : TC_TN_006
+    @LargeTest
+    public void testThumbnailForH264QCIF() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "H264_BP_176x144_15fps_144kbps_AMRNB_8kHz_12.2kbps_m_1_17.3gp";
+
+        final int atTime = 0;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+        final int outWidth = mediaVideoItem.getWidth() * 2;
+        final int outHeight = mediaVideoItem.getHeight() * 2;
+        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
+            outHeight, atTime);
+        validateThumbnail(thumbNailBmp, outWidth, outHeight);
+    }
+
+    /**
+     * To test thumbnail / frame extraction on H264 VGA.
+     */
+    // TODO : TC_TN_007
+    @LargeTest
+    public void testThumbnailForH264VGA() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH +
+            "H264_BP_640x480_30fps_192kbps_1_5.mp4";
+        final int outWidth = 32;
+        final int outHeight = 32;
+        final int atTime = 0;
+
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+
+        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
+            outHeight, atTime);
+        validateThumbnail(thumbNailBmp, outWidth, outHeight);
+    }
+    /**
+     * To test thumbnail / frame extraction on H264 WVGA.
+     */
+    // TODO : TC_TN_008
+    @LargeTest
+    public void testThumbnailForH264WVGA() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH +
+            "H264_BP_800x480_15fps_512kbps_AACLC_24KHz_38Kbps_s_1_17.mp4";
+        final int outWidth = 64;
+        final int outHeight = 64;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+        final long atTime = mediaVideoItem.getDuration() / 2;
+        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
+            outHeight, atTime);
+        validateThumbnail(thumbNailBmp, outWidth, outHeight);
+    }
+
+    /**
+     * To test thumbnail / frame extraction on H264 854x480.
+     */
+    // TODO : TC_TN_009
+    @LargeTest
+    public void testThumbnailForH264854_480() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "MPEG4_SP_854x480_15fps_256kbps_AACLC_16khz_48kbps_s_0_26.mp4";
+        final int outWidth = 128;
+        final int outHeight = 128;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        MediaVideoItem mediaVideoItem = null;
+        mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+        final long atTime = mediaVideoItem.getDuration() - 1000;
+        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
+            outHeight, atTime);
+        validateThumbnail(thumbNailBmp, outWidth, outHeight);
+    }
+
+    /**
+     * To test thumbnail / frame extraction on H264 960x720.
+     */
+    // TODO : TC_TN_010
+    @LargeTest
+    public void testThumbnailForH264HD960() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH +
+            "H264_BP_960x720_25fps_800kbps_AACLC_48Khz_192Kbps_s_1_17.mp4";
+        final int outWidth = 75;
+        final int outHeight = 75;
+
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+        final long atTime = mediaVideoItem.getDuration() - 1000;
+        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
+            outHeight, atTime);
+        validateThumbnail(thumbNailBmp, outWidth, outHeight);
+    }
+
+    /**
+     * To test thumbnail / frame extraction on H264 1080x720 .
+     */
+    // TODO : TC_TN_011
+    @LargeTest
+    public void testThumbnailForH264HD1080() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH +
+            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+        final int outWidth = mediaVideoItem.getWidth() / 2;
+        final int outHeight = mediaVideoItem.getHeight() / 2;
+        final long atTime = mediaVideoItem.getDuration() / 4;
+        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
+            outHeight, atTime);
+        validateThumbnail(thumbNailBmp, outWidth, outHeight);
+    }
+
+    /**
+     * Check the thumbnail / frame extraction precision at 0,100 and 200 ms
+     */
+    // TODO : TC_TN_012
+    @LargeTest
+    public void testThumbnailForH264VGADifferentDuration() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH +
+            "H264_BP_640x480_30fps_256kbps_1_17.mp4";
+        final int atTime = 0;
+        final int atTime1 = 100;
+        final int atTime2 = 200;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+        final int outWidth = mediaVideoItem.getWidth();
+        final int outHeight = mediaVideoItem.getHeight();
+
+        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
+            outHeight, atTime);
+        validateThumbnail(thumbNailBmp, outWidth, outHeight);
+
+        // get Thumbnail @ 100ms
+        final Bitmap thumbNailBmpAt100 =
+            mediaVideoItem.getThumbnail(outWidth, outHeight, atTime1);
+        validateThumbnail(thumbNailBmpAt100, outWidth, outHeight);
+
+        // get Thumbnail @ 200ms
+        final Bitmap thumbNailBmpAt200 = mediaVideoItem.getThumbnail(
+            outWidth, outHeight, atTime2);
+        validateThumbnail(thumbNailBmpAt200, outWidth, outHeight);
+    }
+
+    /**
+     *Check the thumbnail / frame extraction precision at
+     * FileDuration,FileDuration/2 + 100 andFileDuration/2 + 200 ms
+     */
+    // TODO : TC_TN_013
+    @LargeTest
+    public void testThumbnailForMP4VGA() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH +
+            "MPEG4_SP_640x480_15fps_256kbps_0_30.mp4";
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, MediaItem.RENDERING_MODE_BLACK_BORDER);
+
+        final int outWidth = mediaVideoItem.getWidth();
+        final int outHeight = mediaVideoItem.getHeight();
+        final long atTime = mediaVideoItem.getDuration() / 2;
+        final long atTime1 = atTime + 100;
+        final long atTime2 = atTime + 200;
+
+        // get Thumbnail @ duration/2
+        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
+            outHeight, atTime);
+        validateThumbnail(thumbNailBmp, outWidth, outHeight);
+
+        // get Thumbnail @ duration/2 + 100ms
+        final Bitmap thumbNailBmpAt100 = mediaVideoItem.getThumbnail(
+            outWidth, outHeight, atTime1);
+        validateThumbnail(thumbNailBmpAt100, outWidth, outHeight);
+
+        // get Thumbnail @ duration/2 + 200ms
+        final Bitmap thumbNailBmpAt200 = mediaVideoItem.getThumbnail(
+            outWidth, outHeight, atTime2);
+        validateThumbnail(thumbNailBmpAt200, outWidth, outHeight);
+    }
+
+    /**
+     * Check the thumbnail / frame extraction on JPEG file
+     */
+    // TODO : TC_TN_014
+    @LargeTest
+    public void testThumbnailForImage() throws Exception {
+        final String imageItemFilename = INPUT_FILE_PATH + "IMG_640x480.jpg";
+        final int mediaDuration = 1000;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        boolean flagForException = false;
+        int outWidth = 0;
+        int outHeight = 0;
+
+        final MediaImageItem mii = mVideoEditorHelper.createMediaItem(
+            mVideoEditor, "m1", imageItemFilename, mediaDuration, renderingMode);
+        assertNotNull("Media Image Item is Null",  mii);
+        outWidth =  mii.getWidth() / 2;
+        outHeight =  mii.getHeight() / 2;
+
+        final Bitmap thumbNailBmp = mii.getThumbnail(outWidth,
+            outHeight, mediaDuration);
+        validateThumbnail(thumbNailBmp, outWidth, outHeight);
+    }
+    /**
+     *To test ThumbnailList for H263 QCIF
+     */
+    // TODO : TC_TN_015
+    @LargeTest
+    public void testThumbnailListH263QCIF() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_1_17.3gp";
+        final int startTime = 0;
+        final int tnCount = 10;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+
+        final int outWidth = mediaVideoItem.getWidth() / 4;
+        final int outHeight = mediaVideoItem.getHeight() / 4;
+        final long endTime = mediaVideoItem.getDuration() / 2;
+
+        final Bitmap thumbNailBmp[] = mediaVideoItem.getThumbnailList(
+            outWidth, outHeight, startTime, endTime, tnCount);
+        assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
+        assertEquals("Thumbnail Count", tnCount, thumbNailBmp.length);
+
+        for (int i = 0; i < thumbNailBmp.length; i++) {
+            validateThumbnail(thumbNailBmp[i], outWidth, outHeight);
+            thumbNailBmp[i] = null;
+        }
+    }
+
+    /**
+     *To test ThumbnailList for MPEG4 QCIF
+     */
+    // TODO : TC_TN_016
+    @LargeTest
+    public void testThumbnailListMPEG4QCIF() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
+        final int tnCount = 10;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+
+        final int outWidth = mediaVideoItem.getWidth() / 2;
+        final int outHeight = mediaVideoItem.getHeight() / 2;
+        final long startTime = mediaVideoItem.getDuration() / 2;
+        final long endTime = mediaVideoItem.getDuration();
+
+        final Bitmap thumbNailBmp[] = mediaVideoItem.getThumbnailList(
+            outWidth, outHeight, startTime, endTime, tnCount);
+
+        assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
+        assertEquals("Thumbnail Count", tnCount, thumbNailBmp.length);
+        for (int i = 0; i < thumbNailBmp.length; i++) {
+            validateThumbnail(thumbNailBmp[i], outWidth, outHeight);
+            thumbNailBmp[i] = null;
+        }
+    }
+
+    /**
+     *To test ThumbnailList for H264 VGA
+     */
+    // TODO : TC_TN_017
+    @LargeTest
+    public void testThumbnailListH264VGA() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH +
+            "H264_BP_640x480_30fps_256kbps_1_17.mp4";
+        final int tnCount = 10;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+
+        final int outWidth = mediaVideoItem.getWidth() / 2;
+        final int outHeight = mediaVideoItem.getHeight() / 2;
+        final long startTime = mediaVideoItem.getDuration() / 3;
+        final long endTime = mediaVideoItem.getDuration() / 2;
+
+        final Bitmap thumbNailBmp[] = mediaVideoItem.getThumbnailList(
+            outWidth, outHeight, startTime, endTime, tnCount);
+        assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
+        assertEquals("Thumbnail Count", tnCount, thumbNailBmp.length);
+        for (int i = 0; i < thumbNailBmp.length; i++) {
+            validateThumbnail(thumbNailBmp[i], outWidth, outHeight);
+            thumbNailBmp[i] = null;
+        }
+    }
+
+    /**
+     *To test ThumbnailList for H264 WVGA
+     */
+    // TODO : TC_TN_018
+    @LargeTest
+    public void testThumbnailListH264WVGA() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH +
+            "H264_BP_800x480_15fps_512kbps_AACLC_24KHz_38Kbps_s_1_17.mp4";
+        final int tnCount = 10;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+
+        final int outWidth = mediaVideoItem.getWidth() / 2;
+        final int outHeight = mediaVideoItem.getHeight() / 2;
+        final long startTime = mediaVideoItem.getDuration() / 3;
+        final long endTime = mediaVideoItem.getDuration() / 2;
+
+        final Bitmap thumbNailBmp[] = mediaVideoItem.getThumbnailList(
+            outWidth, outHeight, startTime, endTime, tnCount);
+        assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
+        assertEquals("Thumbnail Count", tnCount, thumbNailBmp.length);
+        for (int i = 0; i < thumbNailBmp.length; i++) {
+            validateThumbnail(thumbNailBmp[i], outWidth, outHeight);
+            thumbNailBmp[i] = null;
+        }
+    }
+
+    /**
+     *To test ThumbnailList for H264 VGA ,Time exceeding file duration
+     */
+    // TODO : TC_TN_019
+    @LargeTest
+    public void testThumbnailH264VGAExceedingFileDuration() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH +
+            "H264_BP_640x480_30fps_256kbps_1_17.mp4";
+        boolean flagForException = false;
+        int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+
+        try {
+            final MediaVideoItem mediaVideoItem =
+                mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                    videoItemFilename, renderingMode);
+            final int outWidth = mediaVideoItem.getWidth() / 2;
+            final int outHeight = mediaVideoItem.getHeight() / 2;
+            final long atTime = mediaVideoItem.getDuration() + 2000;
+            mediaVideoItem.getThumbnail(outWidth, outHeight, atTime);
+        } catch (IllegalArgumentException e) {
+            flagForException = true;
+        }
+        assertTrue("Exception in Extracting thumbanil with Invalid Time",
+            flagForException);
+    }
+
+    /**
+     *To test ThumbnailList for VGA Image
+     */
+    // TODO : TC_TN_020
+    @LargeTest
+    public void testThumbnailListVGAImage() throws Exception {
+        final String imageItemFilename = INPUT_FILE_PATH + "IMG_640x480.jpg";
+        final int imageItemDuration = 10000;
+        final int startTime = 0;
+        final int endTime = 0;
+        final int tnCount = 10;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+
+        final MediaImageItem mediaImageItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                imageItemFilename, imageItemDuration, renderingMode);
+        final int outWidth = mediaImageItem.getWidth() / 2;
+        final int outHeight = mediaImageItem.getHeight() / 2;
+
+        final Bitmap thumbNailBmp[] = mediaImageItem.getThumbnailList
+            (outWidth, outHeight, startTime, endTime, tnCount);
+        assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
+        assertEquals("Thumbnail Count", tnCount, thumbNailBmp.length);
+        for (int i = 0; i < thumbNailBmp.length; i++) {
+            validateThumbnail(thumbNailBmp[i], outWidth, outHeight);
+            thumbNailBmp[i] = null;
+        }
+    }
+
+    /**
+     *To test ThumbnailList for Invalid file path
+     */
+    // TODO : TC_TN_021
+    @LargeTest
+    public void testThumbnailForInvalidFilePath() throws Exception {
+        final String imageItemFileName = INPUT_FILE_PATH + "/sdcard/abc.jpg";
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        boolean flagForException = false;
+        try{
+        final MediaImageItem mii = new MediaImageItem(mVideoEditor, "m1",
+            imageItemFileName, 3000, renderingMode);
+        }catch (IllegalArgumentException e){
+            flagForException = true;
+        }
+        assertTrue(" Invalid File Path", flagForException);
+    }
+
+    /**
+     * To test thumbnail / frame extraction with setBoundaries
+     */
+    // TODO : TC_TN_022
+    @LargeTest
+    public void testThumbnailForMPEG4WVGAWithSetBoundaries() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH +
+            "MPEG4_SP_800x480_515kbps_15fps_AMR_NB_8KHz_12.2kbps_m_0_26.mp4";
+        final int atTime = 10000;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+
+        mediaVideoItem.setExtractBoundaries(1000,
+            (mediaVideoItem.getDuration() - 21000));
+
+        final int outWidth = (mediaVideoItem.getWidth() / 2);
+        final int outHeight = (mediaVideoItem.getHeight() / 2);
+        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
+            outHeight, atTime);
+        validateThumbnail(thumbNailBmp, outWidth, outHeight);
+    }
+
+    /**
+     *To test ThumbnailList for H264 WVGA with setExtractboundaries
+     */
+    // TODO : TC_TN_023
+    @LargeTest
+    public void testThumbnailListForH264WVGAWithSetBoundaries() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH +
+            "H264_BP_800x480_15fps_512kbps_1_17.mp4";
+        final int thumbNailStartTime = 10000;
+        final int thumbNailEndTime = 12000;
+        final int tnCount = 10;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+
+        final int outWidth = (mediaVideoItem.getWidth() / 2);
+        final int outHeight = (mediaVideoItem.getHeight() / 2);
+
+        mediaVideoItem.setExtractBoundaries(10000, 12000);
+
+        final Bitmap thumbNailBmp[] = mediaVideoItem.getThumbnailList
+            (outWidth, outHeight, thumbNailStartTime, thumbNailEndTime,
+             tnCount);
+        assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
+        assertTrue("Thumbnail Size", (thumbNailBmp.length > 0) ? true : false);
+        for (int i = 0; i < thumbNailBmp.length; i++) {
+            validateThumbnail(thumbNailBmp[i], outWidth, outHeight);
+            thumbNailBmp[i] = null;
+        }
+    }
+
+    /**
+     *To test ThumbnailList for H264 WVGA with count > frame available
+     */
+    // TODO : TC_TN_024
+    @LargeTest
+    public void testThumbnailListForH264WVGAWithCount() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH +
+            "H264_BP_800x480_15fps_512kbps_AACLC_24KHz_38Kbps_s_1_17.mp4";
+        final int tnCount = 100;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+
+        final int outWidth = (mediaVideoItem.getWidth() / 2);
+        final int outHeight = (mediaVideoItem.getHeight() / 2);
+        final long thumbNailStartTime = mediaVideoItem.getDuration() / 2;
+        final long thumbNailEndTime = thumbNailStartTime + 4000;
+        Bitmap thumbNailBmp[] = null;
+        boolean flagForException = false;
+        try{
+            thumbNailBmp = mediaVideoItem.getThumbnailList(outWidth, outHeight,
+                thumbNailStartTime, thumbNailEndTime, tnCount);
+        }catch (Exception e){
+            assertTrue("Unable to get Thumbnail list", flagForException);
+        }
+        if (thumbNailBmp.length <= tnCount) {
+            flagForException = true;
+        }
+        assertTrue("Thumbnail count more than asked", flagForException);
+    }
+
+    /**
+     *To test ThumbnailList for H264 WVGA with startTime > End Time
+     */
+    // TODO : TC_TN_025
+    @LargeTest
+    public void testThumbnailListH264WVGAWithStartGreaterEnd() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH +
+            "H264_BP_800x480_15fps_512kbps_AACLC_24KHz_38Kbps_s_1_17.mp4";
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final int tnCount = 10;
+        boolean flagForException = false;
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+        final int outWidth = (mediaVideoItem.getWidth() / 2);
+        final int outHeight = (mediaVideoItem.getHeight() / 2);
+        final long thumbNailStartTime = mediaVideoItem.getDuration() / 2;
+        final long thumbNailEndTime = thumbNailStartTime - 1000;
+        try{
+            mediaVideoItem.getThumbnailList(outWidth, outHeight,
+                thumbNailStartTime, thumbNailEndTime, tnCount);
+        } catch (IllegalArgumentException e) {
+            flagForException = true;
+        }
+        assertTrue("Thumbnail Extraction where start time > end time",
+            flagForException);
+    }
+
+    /**
+     *To test ThumbnailList TC_TN_026 for H264 WVGA with startTime = End Time
+     */
+    // TODO : TC_TN_026
+    @LargeTest
+    public void testThumbnailListH264WVGAWithStartEqualEnd() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH +
+            "H264_BP_800x480_15fps_512kbps_AACLC_24KHz_38Kbps_s_1_17.mp4";
+        final int tnCount = 1;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+        final int outWidth = (mediaVideoItem.getWidth() / 2);
+        final int outHeight = (mediaVideoItem.getHeight() / 2);
+        final long thumbNailStartTime = mediaVideoItem.getDuration() / 2;
+        final long thumbNailEndTime = thumbNailStartTime;
+        final Bitmap thumbNailBmp[] = mediaVideoItem.getThumbnailList(outWidth,
+            outHeight, thumbNailStartTime, thumbNailEndTime, tnCount);
+        assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
+        assertEquals("Thumbnail Count", tnCount, thumbNailBmp.length);
+        for (int i = 0; i < thumbNailBmp.length; i++) {
+            validateThumbnail(thumbNailBmp[i], outWidth, outHeight);
+            thumbNailBmp[i] = null;
+        }
+    }
+
+    /**
+     *To test ThumbnailList TC_TN_027 for file where video duration is less
+     * than file duration.
+     */
+    // TODO : TC_TN_027
+    @LargeTest
+    public void testThumbnailForVideoDurationLessFileDuration() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "H264_BP_640x480_15fps_1200Kbps_AACLC_48KHz_64kps_m_0_27.3gp";
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+            final MediaVideoItem mediaVideoItem =
+                mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                    videoItemFilename, renderingMode);
+            final int outWidth = (mediaVideoItem.getWidth() / 2);
+            final int outHeight = (mediaVideoItem.getHeight() / 2);
+            final long atTime = mediaVideoItem.getDuration() - 2000;
+            final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail (outWidth,
+                outHeight, atTime);
+        validateThumbnail(thumbNailBmp, outWidth, outHeight);
+
+    }
+
+    /**
+     *To test ThumbnailList TC_TN_028 for file which has video part corrupted
+     */
+    // TODO : TC_TN_028
+    @LargeTest
+    public void testThumbnailWithCorruptedVideoPart() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH +
+            "corrupted_H264_BP_640x480_12.5fps_256kbps_AACLC_16khz_24kbps_s_0_26.mp4";
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        boolean flagForException = false;
+
+        try {
+            final MediaVideoItem mediaVideoItem =
+                 mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                    videoItemFilename, renderingMode);
+            final int outWidth = mediaVideoItem.getWidth();
+            final int outHeight = mediaVideoItem.getHeight() * 2;
+            final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail
+                (outWidth, outHeight, mediaVideoItem.getDuration()/2);
+        } catch (IllegalArgumentException e) {
+            flagForException = true;
+        }
+        assertTrue("Corrupted File cannot be read", flagForException);
+    }
+
+    /**
+     * Check the thumbnail / frame list extraction for Height as Negative Value
+     */
+    // TODO : TC_TN_029
+    @LargeTest
+    public void testThumbnailWithNegativeHeight() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
+        final int tnCount = 10;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        boolean flagForException = false;
+        try {
+            final MediaVideoItem mediaVideoItem =
+                mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                    videoItemFilename, renderingMode);
+            final int outWidth = (mediaVideoItem.getWidth() / 2);
+            final int outHeight = -1;
+            final long thumbNailStartTime =
+                mediaVideoItem.getBoundaryBeginTime()/2;
+            final long thumbNailEndTime = mediaVideoItem.getBoundaryEndTime();
+            mediaVideoItem.getThumbnailList(outWidth, outHeight,
+                thumbNailStartTime, thumbNailEndTime, tnCount);
+        } catch (IllegalArgumentException e) {
+            flagForException = true;
+        }
+        assertTrue("Thumbnail List with negative Height", flagForException);
+    }
+
+    /**
+     * Check the thumbnail for Height as Zero
+     */
+    // TODO : TC_TN_030
+    @LargeTest
+    public void testThumbnailWithHeightAsZero() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
+        final int atTime = 100;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        boolean flagForException = false;
+        try {
+            final MediaVideoItem mediaVideoItem =
+                mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                    videoItemFilename, renderingMode);
+            final int outWidth = (mediaVideoItem.getWidth() / 2);
+            final int outHeight = -1;
+            mediaVideoItem.getThumbnail(outWidth, outHeight, atTime);
+        } catch (IllegalArgumentException e) {
+            flagForException = true;
+        }
+        assertTrue("Thumbnail List with Zero Height", flagForException);
+    }
+
+    /**
+     * Check the thumbnail for Height = 10
+     */
+    // TODO : TC_TN_031
+    @LargeTest
+    public void testThumbnailWithHeight() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
+        final int atTime = 1000;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+            final MediaVideoItem mediaVideoItem =
+                mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                    videoItemFilename, renderingMode);
+            final int outWidth = (mediaVideoItem.getWidth() / 2);
+            final int outHeight = 10;
+            final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail (outWidth,
+                outHeight, atTime);
+        validateThumbnail(thumbNailBmp, outWidth, outHeight);
+    }
+
+    /**
+     * Check the thumbnail / frame list extraction for Width as Negative Value
+     */
+    // TODO : TC_TN_032
+    @LargeTest
+    public void testThumbnailWithNegativeWidth() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
+        final int tnCount = 10;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        boolean flagForException = false;
+        try {
+            final MediaVideoItem mediaVideoItem =
+                mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                    videoItemFilename, renderingMode);
+            final int outWidth = -1;
+            final int outHeight = mediaVideoItem.getHeight();
+            final long thumbNailStartTime =
+                mediaVideoItem.getBoundaryBeginTime()/2;
+            final long thumbNailEndTime = mediaVideoItem.getBoundaryEndTime();
+            mediaVideoItem.getThumbnailList(outWidth, outHeight, thumbNailStartTime,
+                thumbNailEndTime, tnCount);
+        } catch (IllegalArgumentException e) {
+            flagForException = true;
+        }
+        assertTrue("Thumbnail List with negative Height", flagForException);
+    }
+
+    /**
+     * Check the thumbnail / frame list extraction for Width zero
+     */
+    // TODO : TC_TN_033
+    @LargeTest
+    public void testThumbnailWithWidthAsZero() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
+        final int atTime = 1000;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        boolean flagForException = false;
+        try {
+            final MediaVideoItem mediaVideoItem =
+                mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                    videoItemFilename, renderingMode);
+            final int outWidth = 0;
+            final int outHeight = mediaVideoItem.getHeight() / 2;
+            mediaVideoItem.getThumbnail(outWidth, outHeight, atTime);
+        } catch (IllegalArgumentException e) {
+            flagForException = true;
+        }
+        assertTrue("Thumbnail List with Zero Width", flagForException);
+    }
+
+    /**
+     * Check the thumbnail for Width = 10
+     */
+    // TODO : TC_TN_034
+    @LargeTest
+    public void testThumbnailWithWidth() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
+        final int atTime = 1000;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+        final int outWidth = 10;
+        final int outHeight = mediaVideoItem.getHeight();
+        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail (outWidth,
+            outHeight, atTime);
+        validateThumbnail(thumbNailBmp, outWidth, outHeight);
+    }
+
+    /**
+     * To test thumbnail / frame extraction on MPEG4 (time beyond file duration).
+     */
+    // TODO : TC_TN_035
+    @LargeTest
+    public void testThumbnailMPEG4withMorethanFileDuration() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
+        boolean flagForException = false;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename, renderingMode);
+        final int outWidth =  mediaVideoItem.getWidth()/2;
+        final int outHeight =  mediaVideoItem.getHeight()/2;
+        final long atTime = mediaVideoItem.getDuration() + 100;
+        try{
+            final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail (outWidth,
+            outHeight, atTime);
+        } catch (IllegalArgumentException e) {
+            flagForException = true;
+        }
+        assertTrue("Thumbnail duration is more than file duration",
+            flagForException);
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPropertiesTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPropertiesTest.java
new file mode 100755
index 0000000..3efa5b2
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPropertiesTest.java
@@ -0,0 +1,734 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.functional;
+
+import java.io.File;
+import java.io.IOException;
+
+import android.media.videoeditor.AudioTrack;
+import android.media.videoeditor.MediaImageItem;
+import android.media.videoeditor.MediaItem;
+import android.media.videoeditor.MediaProperties;
+import android.media.videoeditor.MediaVideoItem;
+import android.media.videoeditor.VideoEditor;
+import android.os.Environment;
+import android.test.ActivityInstrumentationTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import com.android.mediaframeworktest.VideoEditorHelper;
+
+public class MediaPropertiesTest extends
+    ActivityInstrumentationTestCase<MediaFrameworkTest> {
+    private final String TAG = "MediaPropertiesTest";
+
+    private final String PROJECT_LOCATION = VideoEditorHelper.PROJECT_LOCATION_COMMON;
+
+    private final String INPUT_FILE_PATH = VideoEditorHelper.INPUT_FILE_PATH_COMMON;
+
+    private VideoEditor mVideoEditor;
+
+    private VideoEditorHelper mVideoEditorHelper;
+
+    public MediaPropertiesTest() {
+        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        // setup for each test case.
+        super.setUp();
+        mVideoEditorHelper = new VideoEditorHelper();
+        // Create a random String which will be used as project path,
+        // where all project related files will be stored.
+        final String projectPath = mVideoEditorHelper.
+            createRandomFile(PROJECT_LOCATION);
+        mVideoEditor = mVideoEditorHelper.createVideoEditor(projectPath);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mVideoEditorHelper.destroyVideoEditor(mVideoEditor);
+        // Clean the directory created as project path
+        mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath()));
+        System.gc();
+        super.tearDown();
+    }
+
+    protected void validateVideoProperties(int aspectRatio, int fileType,
+        int videoCodecType, int duration, int videoBitrate, int fps,
+        int videoProfile, int width, int height, int audioCodecType,
+        int audioSamplingFrequency, int audioChannel, int audioBitrate,
+        MediaVideoItem mvi) throws Exception {
+        assertEquals("Aspect Ratio Mismatch", aspectRatio, mvi.getAspectRatio());
+        assertEquals("File Type Mismatch", fileType, mvi.getFileType());
+        assertEquals("VideoCodec Mismatch", videoCodecType, mvi.getVideoType());
+
+        assertTrue("Video duration Mismatch", mVideoEditorHelper.checkRange (
+            duration, mvi.getDuration(), 10));
+        assertEquals("Video Profile " + mvi.getVideoProfile(), videoProfile,
+            mvi.getVideoProfile());
+        assertEquals("Video height " + mvi.getHeight(), height, mvi.getHeight());
+        assertEquals("Video width " + mvi.getWidth(), width, mvi.getWidth());
+        /** Check FPS with 10% range */
+        assertTrue("fps Mismatch" + mvi.getFps(),
+            mVideoEditorHelper.checkRange(fps, mvi.getFps(), 10));
+
+        assertEquals("AudioType Mismatch ", audioCodecType, mvi.getAudioType());
+        assertEquals("Audio Sampling " + mvi.getAudioSamplingFrequency(),
+            audioSamplingFrequency, mvi.getAudioSamplingFrequency());
+        assertEquals("Audio Channels " + mvi.getAudioChannels(), audioChannel,
+            mvi.getAudioChannels());
+    }
+
+    protected void validateAudioProperties(int audioCodecType, int duration,
+        int audioSamplingFrequency, int audioChannel, int audioBitrate,
+        AudioTrack aT) throws Exception {
+        assertEquals("AudioType Mismatch ", audioCodecType, aT.getAudioType());
+        assertTrue("Video duration Mismatch", mVideoEditorHelper.checkRange (
+            duration, aT.getDuration(), 10));
+        assertEquals("Audio Sampling " + aT.getAudioSamplingFrequency(),
+            audioSamplingFrequency, aT.getAudioSamplingFrequency());
+        assertEquals("Audio Channels " + aT.getAudioChannels(), audioChannel,
+            aT.getAudioChannels());
+    }
+
+    protected void validateImageProperties(int aspectRatio, int fileType,
+        int width, int height, MediaImageItem mii)
+        throws Exception {
+        assertEquals("Aspect Ratio Mismatch", aspectRatio, mii.getAspectRatio());
+        assertEquals("File Type Mismatch", fileType, mii.getFileType());
+        assertEquals("Image height " + mii.getHeight(), height, mii.getHeight());
+        assertEquals("Image width " + mii.getWidth(), width, mii.getWidth());
+    }
+
+
+    /**
+     *To test Media Properties for file MPEG4 854 x 480
+     */
+    // TODO : Remove TC_MP_001
+    @LargeTest
+    public void testPropertiesMPEG4854_480() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "MPEG4_SP_854x480_15fps_256kbps_AACLC_16khz_48kbps_s_0_26.mp4";
+        final int aspectRatio = MediaProperties.ASPECT_RATIO_16_9;
+        final int fileType = MediaProperties.FILE_MP4;
+        final int videoCodecType = MediaProperties.VCODEC_MPEG4;
+        final int duration = 26933;
+        final int videoBitrate = 319000;
+        final int audioBitrate = 48000;
+        final int fps = 15;
+        final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
+        final int audioSamplingFrequency = 16000;
+        final int audioChannel = 2;
+        final int videoProfile = MediaProperties.MPEG4_SP_LEVEL_1;
+        final int width = 854;
+        final int height = MediaProperties.HEIGHT_480;
+
+        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
+            (mVideoEditor, "m1", videoItemFilename,
+            MediaItem.RENDERING_MODE_BLACK_BORDER);
+
+        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
+            videoBitrate, fps, videoProfile, width, height, audioCodecType,
+            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
+    }
+
+
+    /**
+     *To test Media Properties for file MPEG4 WVGA
+     */
+    // TODO : Remove TC_MP_002
+    @LargeTest
+    public void testPropertiesMPEGWVGA() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "MPEG4_SP_800x480_515kbps_15fps_AMR_NB_8KHz_12.2kbps_m_0_26.mp4";
+        final int aspectRatio = MediaProperties.ASPECT_RATIO_5_3;
+        final int fileType = MediaProperties.FILE_MP4;
+        final int videoCodecType = MediaProperties.VCODEC_MPEG4;
+        final int duration = 26933;
+        final int videoBitrate = 384000;
+        final int audioBitrate = 12800;
+        final int fps = 15;
+        final int audioCodecType = MediaProperties.ACODEC_AMRNB;
+        final int audioSamplingFrequency = 8000;
+        final int audioChannel = 1;
+        final int videoProfile = MediaProperties.MPEG4_SP_LEVEL_1;
+        final int width = 800;
+        final int height = MediaProperties.HEIGHT_480;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+
+        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
+            (mVideoEditor, "m1", videoItemFilename, renderingMode);
+
+        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
+            videoBitrate, fps, videoProfile, width, height, audioCodecType,
+            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
+    }
+
+    /**
+     *To test media properties for MPEG4 720x480 (NTSC) + AAC file.
+     */
+    // TODO : Remove TC_MP_003
+    @LargeTest
+    public void testPropertiesMPEGNTSC() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_161kbps_s_0_26.mp4";
+        final int aspectRatio = MediaProperties.ASPECT_RATIO_3_2;
+        final int fileType = MediaProperties.FILE_MP4;
+        final int videoCodecType = MediaProperties.VCODEC_MPEG4;
+        final int duration = 26866;
+        final int videoBitrate = 403000;
+        final int audioBitrate = 160000;
+        final int fps = 30;
+        final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
+        final int audioSamplingFrequency = 48000;
+        final int audioChannel = 2;
+        final int videoProfile = MediaProperties.MPEG4_SP_LEVEL_1;
+        final int width = 720;
+        final int height = MediaProperties.HEIGHT_480;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+
+        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
+            (mVideoEditor, "m1", videoItemFilename, renderingMode);
+
+        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
+            videoBitrate, fps, videoProfile, width, height, audioCodecType,
+            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
+    }
+
+    /**
+     *To test Media Properties for file MPEG4 VGA
+     */
+    // TODO : Remove TC_MP_004
+    @LargeTest
+    public void testPropertiesMPEGVGA() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
+        final int aspectRatio = MediaProperties.ASPECT_RATIO_4_3;
+        final int fileType = MediaProperties.FILE_MP4;
+        final int videoCodecType = MediaProperties.VCODEC_MPEG4;
+        final int duration = 26933;
+        final int videoBitrate = 533000;
+        final int audioBitrate = 128000;
+        final int fps = 15;
+        final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
+        final int audioSamplingFrequency = 48000;
+        final int audioChannel = 2;
+        final int videoProfile = MediaProperties.MPEG4_SP_LEVEL_1;
+        final int width = 640;
+        final int height = MediaProperties.HEIGHT_480;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+
+        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
+            (mVideoEditor, "m1", videoItemFilename, renderingMode);
+
+        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
+            videoBitrate, fps, videoProfile, width, height, audioCodecType,
+            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
+    }
+
+    /**
+     *To test Media Properties for file MPEG4 QCIF
+     */
+    // TODO : Remove TC_MP_005
+    @LargeTest
+    public void testPropertiesMPEGQCIF() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "MPEG4_SP_176x144_12fps_92kbps_AMRNB_8KHz_12.2kbps_m_0_27.3gp";
+        final int aspectRatio = MediaProperties.ASPECT_RATIO_11_9;
+        final int fileType = MediaProperties.FILE_3GP;
+        final int videoCodecType = MediaProperties.VCODEC_MPEG4;
+        final int duration = 27000;
+        final int videoBitrate = 384000;
+        final int audioBitrate = 12200;
+        final int fps = 12;
+        final int audioCodecType = MediaProperties.ACODEC_AMRNB;
+        final int audioSamplingFrequency = 8000;
+        final int audioChannel = 1;
+        final int videoProfile = MediaProperties.MPEG4_SP_LEVEL_1;
+        final int width = 176;
+        final int height = MediaProperties.HEIGHT_144;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+
+        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
+            (mVideoEditor, "m1", videoItemFilename, renderingMode);
+
+        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
+            videoBitrate, fps, videoProfile, width, height, audioCodecType,
+            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
+    }
+
+    /**
+     *To To test media properties for H263 176x144 (QCIF) + AAC (mono) file.
+     */
+    // TODO : Remove TC_MP_006
+    @LargeTest
+    public void testPropertiesH263QCIF() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "H263_profile0_176x144_15fps_256kbps_AACLC_16kHz_32kbps_m_0_26.3gp";
+        final int aspectRatio = MediaProperties.ASPECT_RATIO_11_9;
+        final int fileType = MediaProperties.FILE_3GP;
+        final int videoCodecType = MediaProperties.VCODEC_H263;
+        final int duration = 26933;
+        final int videoBitrate = 384000;
+        final int audioBitrate = 64000;
+        final int fps = 15;
+        final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
+        final int audioSamplingFrequency = 16000;
+        final int audioChannel = 1;
+        final int videoProfile = MediaProperties.H263_PROFILE_0_LEVEL_10;
+        final int width = 176;
+        final int height = MediaProperties.HEIGHT_144;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
+            (mVideoEditor, "m1", videoItemFilename, renderingMode);
+
+        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
+            videoBitrate, fps, videoProfile, width, height, audioCodecType,
+            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
+    }
+
+    /**
+     *To test Media Properties for file H264 VGA
+     */
+    // TODO : Remove TC_MP_007
+    @LargeTest
+    public void testPropertiesH264VGA() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "H264_BP_640x480_15fps_1200Kbps_AACLC_48KHz_64kps_m_0_27.3gp";
+        final int aspectRatio = MediaProperties.ASPECT_RATIO_4_3;
+        final int fileType = MediaProperties.FILE_3GP;
+        final int videoCodecType = MediaProperties.VCODEC_H264BP;
+        final int duration = 77600;
+        final int videoBitrate = 745000;
+        final int audioBitrate = 64000;
+        final int fps = 15;
+        final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
+        final int audioSamplingFrequency = 48000;
+        final int audioChannel = 2;
+        final int videoProfile = MediaProperties.H264_PROFILE_0_LEVEL_1_3;
+        final int width = 640;
+        final int height = MediaProperties.HEIGHT_480;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
+            (mVideoEditor, "m1", videoItemFilename, renderingMode);
+
+        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
+            videoBitrate, fps, videoProfile, width, height, audioCodecType,
+            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
+    }
+
+    /**
+     *To test Media Properties for file H264 NTSC
+     */
+    // TODO : Remove TC_MP_008
+    @LargeTest
+    public void testPropertiesH264NTSC() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "H264_BP_720x480_25fps_256kbps_AMRNB_8khz_12.2kbps_m_0_26.mp4";
+        final int aspectRatio = MediaProperties.ASPECT_RATIO_3_2;
+        final int fileType = MediaProperties.FILE_MP4;
+        final int videoCodecType = MediaProperties.VCODEC_H264BP;
+        final int duration = 26880;
+        final int videoBitrate = 244000;
+        final int audioBitrate = 12200;
+        final int fps = 25;
+        final int audioCodecType = MediaProperties.ACODEC_AMRNB;
+        final int audioSamplingFrequency = 8000;
+        final int audioChannel = 1;
+        final int videoProfile = MediaProperties.H264_PROFILE_0_LEVEL_1_3;
+        final int width = 720;
+        final int height = MediaProperties.HEIGHT_480;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+
+        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
+            (mVideoEditor, "m1", videoItemFilename, renderingMode);
+
+        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
+            videoBitrate, fps, videoProfile, width, height, audioCodecType,
+            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
+    }
+
+    /**
+     *To test media properties for H264 800x480 (WVGA) + AAC file.
+     */
+    // TODO : Remove TC_MP_009
+    @LargeTest
+    public void testPropertiesH264WVGA() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH +
+              "H264_BP_800x480_15fps_512kbps_AACLC_24KHz_38Kbps_s_1_17.mp4";
+        final int aspectRatio = MediaProperties.ASPECT_RATIO_5_3;
+        final int fileType = MediaProperties.FILE_MP4;
+        final int videoCodecType = MediaProperties.VCODEC_H264BP;
+        final int duration = 77466;
+        final int videoBitrate = 528000;
+        final int audioBitrate = 38000;
+        final int fps = 15;
+        final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
+        final int audioSamplingFrequency = 24000;
+        final int audioChannel = 2;
+        final int videoProfile = MediaProperties.H264_PROFILE_0_LEVEL_1_3;
+        final int width = 800;
+        final int height = MediaProperties.HEIGHT_480;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+
+        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
+            (mVideoEditor, "m1", videoItemFilename, renderingMode);
+
+        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
+            videoBitrate, fps, videoProfile, width, height, audioCodecType,
+            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
+    }
+
+    /**
+     *To test Media Properties for file H264 HD1280
+     */
+    // TODO : Remove TC_MP_010
+    @LargeTest
+    public void testPropertiesH264HD1280() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "H264_BP_1280x720_15fps_512kbps_AACLC_16khz_48kbps_s_1_17.mp4";
+        final int aspectRatio = MediaProperties.ASPECT_RATIO_16_9;
+        final int fileType = MediaProperties.FILE_MP4;
+        final int videoCodecType = MediaProperties.VCODEC_H264BP;
+        final int duration = 77600;
+        final int videoBitrate = 606000;
+        final int audioBitrate = 48000;
+        final int fps = 15;
+        final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
+        final int audioSamplingFrequency = 16000;
+        final int audioChannel = 2;
+        final int videoProfile = MediaProperties.H264_PROFILE_0_LEVEL_1_3;
+        final int width = 1280;
+        final int height = MediaProperties.HEIGHT_720;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+
+        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
+            (mVideoEditor, "m1", videoItemFilename, renderingMode);
+
+        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
+            videoBitrate, fps, videoProfile, width, height, audioCodecType,
+            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
+    }
+
+    /**
+     *To test media properties for H264 1080x720 + AAC file
+     */
+    // TODO : Remove TC_MP_011
+    @LargeTest
+    public void testPropertiesH264HD1080WithAudio() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "H264_BP_1080x720_30fps_12Mbps_AACLC_44.1khz_64kbps_s_1_17.mp4";
+        final int aspectRatio = MediaProperties.ASPECT_RATIO_3_2;
+        final int fileType = MediaProperties.FILE_MP4;
+        final int videoCodecType = MediaProperties.VCODEC_H264BP;
+        final int duration = 77500;
+        final int videoBitrate = 1190000;
+        final int audioBitrate = 64000;
+        final int fps = 10;
+        final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
+        final int audioSamplingFrequency = 44100;
+        final int audioChannel = 2;
+        final int videoProfile = MediaProperties.H264_PROFILE_0_LEVEL_1_3;
+        final int width = 1080;
+        final int height = MediaProperties.HEIGHT_720;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+
+        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
+            (mVideoEditor, "m1", videoItemFilename, renderingMode);
+
+        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
+            videoBitrate, fps, videoProfile, width, height, audioCodecType,
+            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
+    }
+
+    /**
+     *To test Media Properties for file WMV - Unsupported type
+     */
+    // TODO : Remove TC_MP_012
+    @LargeTest
+    public void testPropertiesWMVFile() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH +
+            "WMV_V7_640x480_15fps_512Kbps_wma_V9_44khz_48Kbps_s_1_30.wmv";
+        boolean flagForException = false;
+        try {
+            new MediaVideoItem(mVideoEditor, "m1", videoItemFilename,
+                MediaItem.RENDERING_MODE_BLACK_BORDER);
+        } catch (IllegalArgumentException e) {
+            flagForException = true;
+        }
+        assertTrue("Media Properties for a WMV File -- Unsupported file type",
+            flagForException);
+    }
+
+    /**
+     *To test media properties for H.264 Main/Advanced profile. (unsupported profile input)
+     */
+    // TODO : Remove TC_MP_013
+    @LargeTest
+    public void testPropertiesH264MainLineProfile() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH
+            + "H264_MP_960x720_25fps_800kbps_AACLC_48Khz_192Kbps_s_1_17.mp4";
+        final int aspectRatio = MediaProperties.ASPECT_RATIO_4_3;
+        //final int videoCodecType = MediaProperties.VCODEC_H264BP;
+        final int videoCodecType = MediaProperties.VCODEC_H264MP;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        boolean flagForException = false;
+
+        try {
+        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
+            (mVideoEditor, "m1", videoItemFilename, renderingMode);
+            assertEquals("VideoCodec Mismatch", videoCodecType, mvi.getVideoType());
+        }catch (IllegalArgumentException e){
+            flagForException = true;
+        }
+            assertTrue("Unsupported Main Profile", flagForException);
+    }
+
+    /**
+     *To test Media Properties for non existing file.
+     */
+    // TODO : Remove TC_MP_014
+    @LargeTest
+    public void testPropertiesForNonExsitingFile() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH + "abc.3gp";
+        boolean flagForException = false;
+
+        try {
+            new MediaVideoItem(mVideoEditor, "m1", videoItemFilename,
+                MediaItem.RENDERING_MODE_BLACK_BORDER);
+        } catch (IllegalArgumentException e) {
+            flagForException = true;
+        }
+        assertTrue("Media Properties for non exsisting file", flagForException);
+     }
+
+    /**
+     *To test Media Properties for file H264 HD1080
+     */
+    // TODO : Remove TC_MP_015
+    @LargeTest
+    public void testPropertiesH264HD1080WithoutAudio() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH +
+            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
+        final int aspectRatio = MediaProperties.ASPECT_RATIO_3_2;
+        final int fileType = MediaProperties.FILE_MP4;
+        final int videoCodecType = MediaProperties.VCODEC_H264BP;
+        final int duration = 77366;
+        final int videoBitrate = 859000;
+        final int audioBitrate = 0;
+        final int fps = 30;
+        final int audioCodecType = -1;
+        final int audioSamplingFrequency = 0;
+        final int audioChannel = 0;
+        final int videoProfile = MediaProperties.H264_PROFILE_0_LEVEL_1_3;
+        final int width = 1080;
+        final int height = MediaProperties.HEIGHT_720;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+
+        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
+            (mVideoEditor, "m1", videoItemFilename, renderingMode);
+
+        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
+            videoBitrate, fps, videoProfile, width, height, audioCodecType,
+            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
+    }
+
+    /**
+     *To test Media Properties for Image file of JPEG Type
+     */
+    // TODO : Remove TC_MP_016
+    @LargeTest
+    public void testPropertiesVGAImage() throws Exception {
+        final String imageItemFilename = INPUT_FILE_PATH + "IMG_640x480.jpg";
+        final int imageItemDuration = 10000;
+        final int aspectRatio = MediaProperties.ASPECT_RATIO_4_3;
+        final int fileType = MediaProperties.FILE_JPEG;
+        final int width = 640;
+        final int height = MediaProperties.HEIGHT_480;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+
+        final MediaImageItem mii = mVideoEditorHelper.createMediaItem
+            (mVideoEditor, "m1", imageItemFilename, imageItemDuration,
+            renderingMode);
+        validateImageProperties(aspectRatio, fileType, width, height, mii);
+    }
+
+    /**
+     *To test Media Properties for Image file of PNG Type
+     */
+    // TODO : Remove TC_MP_017
+    @LargeTest
+    public void testPropertiesPNG() throws Exception {
+        final String imageItemFilename = INPUT_FILE_PATH + "IMG_640x480.png";
+        final int imageItemDuration = 10000;
+        final int aspectRatio = MediaProperties.ASPECT_RATIO_4_3;
+        final int fileType = MediaProperties.FILE_PNG;
+        final int width = 640;
+        final int height = 480;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final MediaImageItem mii = mVideoEditorHelper.createMediaItem
+            (mVideoEditor, "m1", imageItemFilename, imageItemDuration,
+            renderingMode);
+        validateImageProperties(aspectRatio, fileType, width, height, mii);
+    }
+
+    /**
+     *To test Media Properties for file GIF - Unsupported type
+     */
+    // TODO : Remove TC_MP_018
+    @LargeTest
+    public void testPropertiesGIFFile() throws Exception {
+
+        final String imageItemFilename = INPUT_FILE_PATH + "IMG_640x480.gif";
+        final int imageItemDuration = 10000;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        boolean flagForException = false;
+        try {
+            new MediaImageItem(mVideoEditor, "m1", imageItemFilename,
+                imageItemDuration, renderingMode);
+        } catch (IllegalArgumentException e) {
+            flagForException = true;
+        }
+        assertTrue("Media Properties for a GIF File -- Unsupported file type",
+            flagForException);
+    }
+
+    /**
+     *To test Media Properties for file Text file named as 3GP
+     */
+    // TODO : Remove TC_MP_019
+    @LargeTest
+    public void testPropertiesofDirtyFile() throws Exception {
+
+        final String videoItemFilename = INPUT_FILE_PATH +
+            "Text_FileRenamedTo3gp.3gp";
+        boolean flagForException = false;
+
+        try {
+            new MediaVideoItem(mVideoEditor, "m1", videoItemFilename,
+                MediaItem.RENDERING_MODE_BLACK_BORDER);
+        } catch (IllegalArgumentException e) {
+            flagForException = true;
+        }
+        assertTrue("Media Properties for a Dirty  File ",
+            flagForException);
+    }
+
+    /**
+     *To test Media Properties for file name as NULL
+     */
+    // TODO : Remove TC_MP_020
+    @LargeTest
+    public void testPropertieNULLFile() throws Exception {
+        final String videoItemFilename = null;
+        boolean flagForException = false;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        try {
+            new MediaVideoItem(mVideoEditor, "m1", videoItemFilename,
+                renderingMode);
+        } catch (IllegalArgumentException e) {
+            flagForException = true;
+        }
+        assertTrue("Media Properties for NULL  File ",
+            flagForException);
+    }
+
+    /**
+     *To test Media Properties for file which is of type MPEG2
+     */
+    // TODO : Remove TC_MP_021
+    @LargeTest
+    public void testPropertiesMPEG2File() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH +
+            "MPEG2_640x480_30fps_192kbps_1_5.mp4";
+        boolean flagForException = false;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        try {
+            new MediaVideoItem(mVideoEditor, "m1", videoItemFilename,
+                renderingMode);
+        } catch (IllegalArgumentException e) {
+            flagForException = true;
+        }
+        assertTrue("Media Properties for a MPEG2 File --Unsupported file type",
+            flagForException);
+    }
+
+    /**
+     *To test Media Properties TC_MP_023 for file without Video only Audio
+     */
+    // TODO : Remove TC_MP_023
+    @LargeTest
+    public void testProperties3GPWithoutVideoMediaItem() throws Exception {
+        final String audioFilename = INPUT_FILE_PATH +
+            "AACLC_48KHz_256Kbps_s_1_17.3gp";
+        boolean flagForException = false;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        try {
+            new MediaVideoItem(mVideoEditor, "m1", audioFilename,
+                renderingMode);
+        } catch (IllegalArgumentException e) {
+            flagForException = true;
+        }
+        assertTrue("Exception in Creaing Media Video item object without video",
+            flagForException);
+    }
+
+    /**
+     *To test media properties for Audio Track file. (No Video, AAC Audio)
+     */
+    // TODO : Remove TC_MP_024
+    @LargeTest
+    public void testProperties3GPWithoutVideoAudioTrack() throws Exception {
+
+        final String audioFilename = INPUT_FILE_PATH +
+            "AACLC_44.1kHz_256kbps_s_1_17.mp4";
+        final int duration = 77554;
+        final int audioBitrate = 384000;
+        final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
+        final int audioSamplingFrequency = 44100;
+        final int audioChannel = 2;
+
+        final AudioTrack audioTrack = mVideoEditorHelper.createAudio
+            (mVideoEditor, "a1", audioFilename);
+
+        validateAudioProperties(audioCodecType, duration, audioSamplingFrequency,
+            audioChannel, audioBitrate, audioTrack);
+    }
+
+        /**
+     *To test media properties for Audio Track file. MP3 file
+     */
+    // TODO : Remove TC_MP_025
+    @LargeTest
+    public void testPropertiesMP3AudioTrack() throws Exception {
+
+        final String audioFilename = INPUT_FILE_PATH +
+            "MP3_48KHz_128kbps_s_1_17.mp3";
+        final int duration = 77640;
+        final int audioBitrate = 128000;
+        final int audioCodecType = MediaProperties.ACODEC_MP3;
+        final int audioSamplingFrequency = 48000;
+        final int audioChannel = 2;
+
+        final AudioTrack audioTrack = mVideoEditorHelper.createAudio
+            (mVideoEditor, "a1", audioFilename);
+
+        validateAudioProperties(audioCodecType, duration, audioSamplingFrequency,
+            audioChannel, audioBitrate, audioTrack);
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java
index 6a87656..0dadaa5 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java
@@ -89,7 +89,6 @@
      * To Test Creation of Media Video Item.
      */
     // TODO : remove TC_API_001
-    @SuppressWarnings("unused")
     @LargeTest
     public void testMediaVideoItem() throws Exception {
         final String videoItemFileName = INPUT_FILE_PATH
@@ -132,7 +131,6 @@
      * the Begin and End Time.
      */
     // TODO : remove TC_API_002
-    @SuppressWarnings("unused")
     @LargeTest
     public void testMediaVideoItemExtractBoundaries() throws Exception {
         final String videoItemFileName = INPUT_FILE_PATH
@@ -202,7 +200,6 @@
      * To test creation of Media Video Item with Set and Get rendering Mode
      */
     // TODO : remove TC_API_003
-    @SuppressWarnings("unused")
     @LargeTest
     public void testMediaVideoItemRenderingModes() throws Exception {
         final String videoItemFileName = INPUT_FILE_PATH
@@ -247,7 +244,6 @@
      * To Test the Media Video API : Set Audio Volume, Get Audio Volume and Mute
      */
     // TODO : remove TC_API_005
-    @SuppressWarnings("unused")
     @LargeTest
     public void testMediaVideoItemAudioFeatures() throws Exception {
         final String videoItemFileName = INPUT_FILE_PATH
@@ -306,7 +302,6 @@
      */
 
     // TODO : remove TC_API_006
-    @SuppressWarnings("unused")
     @LargeTest
     public void testMediaVideoItemGetWaveformData() throws Exception {
 
@@ -349,7 +344,6 @@
      */
 
     // TODO : remove TC_API_007
-    @SuppressWarnings("unused")
     @LargeTest
     public void testMediaVideoItemEffect() throws Exception {
         final String videoItemFileName = INPUT_FILE_PATH
@@ -391,7 +385,6 @@
      */
 
     // TODO : remove TC_API_008
-    @SuppressWarnings("unused")
     @LargeTest
     public void testMediaVideoItemTransitions() throws Exception {
         final String videoItemFileName = INPUT_FILE_PATH
@@ -439,7 +432,6 @@
      */
 
     // TODO : remove TC_API_009
-    @SuppressWarnings("unused")
     @LargeTest
     public void testMediaVideoItemOverlays() throws Exception {
         final String videoItemFileName = INPUT_FILE_PATH
@@ -1404,8 +1396,6 @@
         final Rect endRect1 = new Rect(10, 10, mediaImageItem.getWidth() / 4,
             mediaImageItem.getHeight() / 4);
 
-        //kbEffectOnMediaItem.setStartRect(startRect1);
-        //kbEffectOnMediaItem.setEndRect(endRect1);
         /* Added newly to take care of removal set APIs */
         kbEffectOnMediaItem = new EffectKenBurns(mediaImageItem, "KBOnM2_changed",
             startRect1, endRect1, 500, 3000);
@@ -1417,7 +1407,6 @@
 
         final Rect zeroRect = new Rect(0, 0, 0, 0);
         try {
-            //kbEffectOnMediaItem.setStartRect(zeroRect);
             kbEffectOnMediaItem = new EffectKenBurns(mediaImageItem, "KBOnM2_zeroStart",
                 zeroRect, endRect, 500, 3000);
 
@@ -1428,7 +1417,6 @@
 
         flagForException = false;
         try {
-            //kbEffectOnMediaItem.setEndRect(zeroRect);
             kbEffectOnMediaItem = new EffectKenBurns(mediaImageItem, "KBOnM2_zeroEnd",
                 startRect, zeroRect, 500, 3000);
         } catch (IllegalArgumentException e) {
@@ -1443,7 +1431,6 @@
      */
 
     // TODO : remove TC_API_037
-    @SuppressWarnings("unused")
     @LargeTest
     public void testTransitionFadeBlack() throws Exception {
 
@@ -1592,7 +1579,6 @@
      */
 
     // TODO : remove TC_API_038
-    @SuppressWarnings("unused")
     @LargeTest
     public void testTransitionCrossFade() throws Exception {
 
@@ -1744,7 +1730,6 @@
      */
 
     // TODO : remove TC_API_039
-    @SuppressWarnings("unused")
     @LargeTest
     public void testTransitionSliding() throws Exception {
         final String videoItemFilename1 = INPUT_FILE_PATH +
@@ -1935,7 +1920,6 @@
      */
 
     // TODO : remove TC_API_040
-    @SuppressWarnings("unused")
     @LargeTest
     public void testTransitionAlpha() throws Exception {
 
@@ -2115,7 +2099,6 @@
      */
 
     // TODO : remove TC_API_041
-    @SuppressWarnings("unused")
     @LargeTest
     public void testFrameOverlayVideoItem() throws Exception {
         final String videoItemFilename1 = INPUT_FILE_PATH +
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorExportTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorExportTest.java
new file mode 100755
index 0000000..37b1f54
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorExportTest.java
@@ -0,0 +1,818 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.functional;
+
+import java.io.File;
+
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.media.videoeditor.AudioTrack;
+import android.media.videoeditor.EffectColor;
+import android.media.videoeditor.EffectKenBurns;
+import android.media.videoeditor.MediaImageItem;
+import android.media.videoeditor.MediaItem;
+import android.media.videoeditor.MediaProperties;
+import android.media.videoeditor.MediaVideoItem;
+import android.media.videoeditor.OverlayFrame;
+import android.media.videoeditor.Transition;
+import android.media.videoeditor.TransitionAlpha;
+import android.media.videoeditor.TransitionCrossfade;
+import android.media.videoeditor.TransitionFadeBlack;
+import android.media.videoeditor.TransitionSliding;
+import android.media.videoeditor.VideoEditor;
+import android.media.videoeditor.VideoEditor.ExportProgressListener;
+import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener;
+import android.os.Environment;
+import android.test.ActivityInstrumentationTestCase;
+
+
+import android.util.Log;
+
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import android.test.suitebuilder.annotation.LargeTest;
+import com.android.mediaframeworktest.VideoEditorHelper;
+
+public class VideoEditorExportTest extends
+    ActivityInstrumentationTestCase<MediaFrameworkTest> {
+    private final String TAG = "TransitionTest";
+
+    private final String PROJECT_LOCATION = VideoEditorHelper.PROJECT_LOCATION_COMMON;
+
+    private final String INPUT_FILE_PATH = VideoEditorHelper.INPUT_FILE_PATH_COMMON;
+
+    private VideoEditor mVideoEditor;
+
+    private VideoEditorHelper mVideoEditorHelper;
+
+    // Declares the annotation for Preview Test Cases
+    public @interface TransitionTests {
+    }
+
+    public VideoEditorExportTest() {
+        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        // setup for each test case.
+        super.setUp();
+        mVideoEditorHelper = new VideoEditorHelper();
+        // Create a random String which will be used as project path, where all
+        // project related files will be stored.
+        final String projectPath =
+            mVideoEditorHelper.createRandomFile(PROJECT_LOCATION);
+        mVideoEditor = mVideoEditorHelper.createVideoEditor(projectPath);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mVideoEditorHelper.destroyVideoEditor(mVideoEditor);
+        // Clean the directory created as project path
+        mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath()));
+        System.gc();
+        super.tearDown();
+    }
+
+    /**
+     * To Test export : Merge and Trim different types of Video and Image files
+     */
+    // TODO :remove TC_EXP_001
+    @LargeTest
+    public void testExportMergeTrim() throws Exception {
+        final String videoItemFilename1 = INPUT_FILE_PATH
+            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
+        final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
+        final String videoItemFilename2 = INPUT_FILE_PATH
+            + "H264_BP_640x480_12.5fps_256kbps_AACLC_16khz_24kbps_s_0_26.mp4";
+        final String videoItemFilename3 = INPUT_FILE_PATH
+            + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
+        final String imageItemFilename2 = INPUT_FILE_PATH + "IMG_176x144.jpg";
+        final String imageItemFilename3 = INPUT_FILE_PATH + "IMG_640x480.jpg";
+        final String outFilename = mVideoEditorHelper
+            .createRandomFile(mVideoEditor.getPath() + "/")
+            + ".3gp";
+
+        final MediaVideoItem mediaVideoItem1 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaVideoItem1.setExtractBoundaries(2000, 7000);
+        mVideoEditor.addMediaItem(mediaVideoItem1);
+
+        final MediaImageItem mediaImageItem2 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
+                imageItemFilename1, 3000, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaImageItem2);
+
+        final MediaVideoItem mediaVideoItem3 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
+                videoItemFilename2, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaVideoItem3.setExtractBoundaries(0, 2000);
+        mVideoEditor.addMediaItem(mediaVideoItem3);
+
+        final MediaVideoItem mediaVideoItem4 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m4",
+                videoItemFilename3, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaVideoItem4.setExtractBoundaries(mediaVideoItem4.getDuration()-5000,
+            mediaVideoItem4.getDuration());
+        mVideoEditor.addMediaItem(mediaVideoItem4);
+
+        final MediaImageItem mediaImageItem5 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m5",
+                imageItemFilename2, 4000, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaImageItem5);
+
+        final MediaImageItem mediaImageItem6 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m6",
+                imageItemFilename3, 2000, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaImageItem6);
+
+        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
+            public void onProgress(Object item, int action, int progress) {
+            }
+        });
+
+        try {
+            final int[] progressUpdate = new int[100];
+            mVideoEditor.export(outFilename, MediaProperties.HEIGHT_720,
+                MediaProperties.BITRATE_800K, new ExportProgressListener() {
+                    int i = 0;
+                    public void onProgress(VideoEditor ve, String outFileName,
+                        int progress) {
+                            progressUpdate[i++] = progress;
+                    }
+                });
+            mVideoEditorHelper.checkProgressCBValues(progressUpdate);
+        } catch (Exception e) {
+            assertTrue("Error in Export" + e.toString(), false);
+        }
+        final long storyBoardDuration = mediaVideoItem1.getTimelineDuration()
+            + mediaImageItem2.getDuration() + mediaVideoItem3.getTimelineDuration()
+            + mediaVideoItem4.getTimelineDuration() + mediaImageItem5.getDuration()
+            + mediaImageItem6.getDuration();
+        mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
+            MediaProperties.HEIGHT_720, 0, storyBoardDuration,
+            MediaProperties.VCODEC_H264BP, MediaProperties.ACODEC_AAC_LC);
+        mVideoEditorHelper.checkDeleteExistingFile(outFilename);
+    }
+
+    /**
+     *To Test export : With Effect and Overlays on Different Media Items
+     */
+    // TODO :remove TC_EXP_002
+    @LargeTest
+    public void testExportEffectOverlay() throws Exception {
+          final String videoItemFilename1 = INPUT_FILE_PATH
+            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
+        final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
+        final String videoItemFilename2 = INPUT_FILE_PATH
+              + "H264_BP_640x480_15fps_1200Kbps_AACLC_48KHz_64kps_m_0_27.3gp";
+        final String videoItemFilename3 = INPUT_FILE_PATH
+            + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
+        final String imageItemFilename2 = INPUT_FILE_PATH + "IMG_176x144.jpg";
+        final String imageItemFilename3 = INPUT_FILE_PATH + "IMG_640x480.jpg";
+        final String outFilename = mVideoEditorHelper
+            .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
+
+        final String overlayFile = INPUT_FILE_PATH + "IMG_640x480_Overlay1.png";
+
+        final MediaVideoItem mediaVideoItem1 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaVideoItem1.setExtractBoundaries(2000, 7000);
+        mVideoEditor.addMediaItem(mediaVideoItem1);
+
+        final EffectColor effectPink =
+            mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effectPink",
+                0, 2000, EffectColor.TYPE_COLOR, EffectColor.PINK);
+        mediaVideoItem1.addEffect(effectPink);
+
+        final EffectColor effectNegative =
+            mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effectNegative",
+                3000, 4000, EffectColor.TYPE_NEGATIVE, 0);
+        mediaVideoItem1.addEffect(effectNegative);
+
+        final MediaImageItem mediaImageItem2 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
+                imageItemFilename1, 3000, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaImageItem2);
+
+        final EffectColor effectFifties =
+            mVideoEditorHelper.createEffectItem(mediaImageItem2, "effectFifties",
+                0, 3000, EffectColor.TYPE_FIFTIES, 0);
+        mediaImageItem2.addEffect(effectFifties);
+
+        final MediaVideoItem mediaVideoItem3 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
+                videoItemFilename2, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaVideoItem3);
+        mediaVideoItem3.setExtractBoundaries(0, 8000);
+
+        final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(overlayFile,
+            640, 480);
+        final OverlayFrame overlayFrame =
+            mVideoEditorHelper.createOverlay(mediaVideoItem3, "overlay",
+                mBitmap, 2000, 5000);
+        mediaVideoItem3.addOverlay(overlayFrame);
+
+        final EffectColor effectGreen =
+            mVideoEditorHelper.createEffectItem(mediaVideoItem3, "effectGreen",
+                0, 2000, EffectColor.TYPE_COLOR, EffectColor.GREEN);
+        mediaVideoItem3.addEffect(effectGreen);
+
+        final MediaVideoItem mediaVideoItem4 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m4",
+                videoItemFilename3, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaVideoItem4.setExtractBoundaries(mediaVideoItem4.getDuration()-5000,
+            mediaVideoItem4.getDuration());
+        mVideoEditor.addMediaItem(mediaVideoItem4);
+
+        final EffectColor effectSepia =
+            mVideoEditorHelper.createEffectItem(mediaVideoItem4, "effectSepia",
+                0, 2000, EffectColor.TYPE_SEPIA, 0);
+        mediaVideoItem4.addEffect(effectSepia);
+
+        final MediaImageItem mediaImageItem5 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m5",
+                imageItemFilename2, 4000, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaImageItem5);
+
+        final EffectColor effectGray =
+            mVideoEditorHelper.createEffectItem(mediaImageItem5, "effectGray",
+                0, 2000, EffectColor.TYPE_COLOR, EffectColor.GRAY);
+        mediaImageItem5.addEffect(effectGray);
+
+        final MediaImageItem mediaImageItem6 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m6",
+                imageItemFilename3, 2000, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaImageItem6);
+
+        final EffectColor effectGradient =
+            mVideoEditorHelper.createEffectItem(mediaImageItem6,
+                "effectGradient", 0, 2000, EffectColor.TYPE_GRADIENT,
+                EffectColor.PINK);
+        mediaImageItem6.addEffect(effectGradient);
+
+        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
+            public void onProgress(Object item, int action, int progress) {
+            }
+        });
+
+        try {
+            final int[] progressUpdate = new int[100];
+            mVideoEditor.export(outFilename, MediaProperties.HEIGHT_720,
+                MediaProperties.BITRATE_800K, new ExportProgressListener() {
+                    int i = 0;
+                    public void onProgress(VideoEditor ve, String outFileName,
+                        int progress) {
+                            progressUpdate[i++] = progress;
+                    }
+                });
+            mVideoEditorHelper.checkProgressCBValues(progressUpdate);
+        } catch (Exception e) {
+            assertTrue("Error in Export" + e.toString(), false);
+        }
+        final long storyBoardDuration = mediaVideoItem1.getTimelineDuration()
+            + mediaImageItem2.getDuration()
+            + mediaVideoItem3.getTimelineDuration()
+            + mediaVideoItem4.getTimelineDuration()
+            + mediaImageItem5.getDuration()
+            + mediaImageItem6.getDuration();
+        mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
+            MediaProperties.HEIGHT_720, 0, storyBoardDuration,
+            MediaProperties.VCODEC_H264BP, MediaProperties.ACODEC_AAC_LC);
+        mVideoEditorHelper.checkDeleteExistingFile(outFilename);
+    }
+
+    /**
+     * To test export : with Image with KenBurnEffect
+     */
+    // TODO : remove TC_EXP_003
+    @LargeTest
+    public void testExportEffectKenBurn() throws Exception {
+        final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
+        final int imageItemRenderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final String outFilename = mVideoEditorHelper
+            .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
+
+        final MediaImageItem mediaImageItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
+                imageItemFileName, 5000, imageItemRenderingMode);
+        mVideoEditor.addMediaItem(mediaImageItem);
+
+        final Rect startRect = new Rect((mediaImageItem.getHeight() / 3),
+            (mediaImageItem.getWidth() / 3), (mediaImageItem.getHeight() / 2),
+            (mediaImageItem.getWidth() / 2));
+
+        final Rect endRect = new Rect(0, 0, mediaImageItem.getWidth(),
+            mediaImageItem.getHeight());
+
+        final EffectKenBurns kbEffectOnMediaItem = new EffectKenBurns(
+            mediaImageItem, "KBOnM2", startRect, endRect, 500, 3000);
+        assertNotNull("EffectKenBurns", kbEffectOnMediaItem);
+        mediaImageItem.addEffect(kbEffectOnMediaItem);
+
+        assertEquals("KenBurn Start Rect", startRect,
+            kbEffectOnMediaItem.getStartRect());
+        assertEquals("KenBurn End Rect", endRect,
+            kbEffectOnMediaItem.getEndRect());
+
+        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
+            public void onProgress(Object item, int action, int progress) {
+            }
+        });
+
+        try {
+            final int[] progressUpdate = new int[100];
+            mVideoEditor.export(outFilename, MediaProperties.HEIGHT_720,
+                MediaProperties.BITRATE_800K, new ExportProgressListener() {
+                    int i = 0;
+                    public void onProgress(VideoEditor ve, String outFileName,
+                        int progress) {
+                            progressUpdate[i++] = progress;
+                    }
+                });
+            mVideoEditorHelper.checkProgressCBValues(progressUpdate);
+        } catch (Exception e) {
+            assertTrue("Error in Export" + e.toString(), false);
+        }
+        mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
+            MediaProperties.HEIGHT_720, 0, mediaImageItem.getDuration(),
+            MediaProperties.VCODEC_H264BP, MediaProperties.ACODEC_AAC_LC);
+        mVideoEditorHelper.checkDeleteExistingFile(outFilename);
+    }
+
+    /**
+     * To Test Export : With Video and Image and An Audio BackGround Track
+     */
+    // TODO : remove TC_EXP_004
+    @LargeTest
+    public void testExportAudio() throws Exception {
+        final String videoItemFileName = INPUT_FILE_PATH
+            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
+        final String imageItemFileName = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
+        final String outFilename = mVideoEditorHelper
+            .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
+        final String audioTrackFilename = INPUT_FILE_PATH +
+            "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
+
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaVideoItem.setExtractBoundaries(0, 10000);
+        mVideoEditor.addMediaItem(mediaVideoItem);
+
+        final MediaImageItem mediaImageItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
+                imageItemFileName, 5000, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaImageItem);
+
+        final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
+            mVideoEditor, "a1", audioTrackFilename);
+        audioTrack.setExtractBoundaries(2000, 5000);
+        mVideoEditor.addAudioTrack(audioTrack);
+
+        audioTrack.disableDucking();
+        audioTrack.enableLoop();
+        audioTrack.setVolume(75);
+
+        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
+            public void onProgress(Object item, int action, int progress) {
+            }
+        });
+
+        try {
+            final int[] progressUpdate = new int[100];
+            mVideoEditor.export(outFilename, MediaProperties.HEIGHT_720,
+                MediaProperties.BITRATE_800K, new ExportProgressListener() {
+                    int i = 0;
+                    public void onProgress(VideoEditor ve, String outFileName,
+                        int progress) {
+                            progressUpdate[i++] = progress;
+                    }
+                });
+            mVideoEditorHelper.checkProgressCBValues(progressUpdate);
+        } catch (Exception e) {
+            assertTrue("Error in Export" + e.toString(), false);
+        }
+        mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
+            MediaProperties.HEIGHT_720, 0, (mediaVideoItem.getTimelineDuration() +
+            mediaImageItem.getDuration()),
+            MediaProperties.VCODEC_H264BP, MediaProperties.ACODEC_AAC_LC);
+
+        mVideoEditorHelper.checkDeleteExistingFile(outFilename);
+    }
+
+    /**
+     *To Test export : With Transition on Different Media Items
+     */
+    // TODO :remove TC_EXP_005
+    @LargeTest
+    public void testExportTransition() throws Exception {
+        final String videoItemFilename1 = INPUT_FILE_PATH
+            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
+        final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
+        final String videoItemFilename2 = INPUT_FILE_PATH
+            + "H264_BP_640x480_12.5fps_256kbps_AACLC_16khz_24kbps_s_0_26.mp4";
+        final String videoItemFilename3 = INPUT_FILE_PATH +
+            "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
+
+        final String imageItemFilename2 = INPUT_FILE_PATH + "IMG_176x144.jpg";
+        final String imageItemFilename3 = INPUT_FILE_PATH + "IMG_640x480.jpg";
+        final String outFilename = mVideoEditorHelper
+            .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
+        final String maskFilename = INPUT_FILE_PATH +
+            "TransitionSpiral_QVGA.jpg";
+
+        final MediaVideoItem mediaItem1 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaItem1.setExtractBoundaries(2000, 7000);
+        mVideoEditor.addMediaItem(mediaItem1);
+
+        final TransitionAlpha transition1 =
+            mVideoEditorHelper.createTAlpha("transition1", null, mediaItem1,
+                2000, Transition.BEHAVIOR_LINEAR, maskFilename, 50, true);
+        mVideoEditor.addTransition(transition1);
+
+        final MediaImageItem mediaItem2 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
+                imageItemFilename1, 8000, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaItem2);
+
+        final MediaVideoItem mediaItem3 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
+                videoItemFilename2, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaItem3.setExtractBoundaries(0, 8000);
+        mVideoEditor.addMediaItem(mediaItem3);
+
+        final TransitionSliding transition2And3 =
+            mVideoEditorHelper.createTSliding("transition2", mediaItem2,
+                mediaItem3, 4000, Transition.BEHAVIOR_MIDDLE_FAST,
+                TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN);
+        mVideoEditor.addTransition(transition2And3);
+
+        final MediaVideoItem mediaItem4 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m4",
+                videoItemFilename3, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaItem4);
+        mediaItem4.setExtractBoundaries(0, 8000);
+
+        final TransitionCrossfade transition3And4 =
+            mVideoEditorHelper.createTCrossFade("transition3", mediaItem3,
+                mediaItem4, 3500, Transition.BEHAVIOR_MIDDLE_SLOW);
+        mVideoEditor.addTransition(transition3And4);
+
+        final MediaImageItem mediaItem5 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m5",
+                imageItemFilename2, 7000, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaItem5);
+
+        final TransitionFadeBlack transition4And5 =
+            mVideoEditorHelper.createTFadeBlack("transition4", mediaItem4,
+                mediaItem5, 3500, Transition.BEHAVIOR_SPEED_DOWN);
+        mVideoEditor.addTransition(transition4And5);
+
+        final MediaImageItem mediaItem6 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m6",
+                imageItemFilename3, 3000, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaItem6);
+
+        final TransitionSliding transition5And6 =
+            mVideoEditorHelper.createTSliding("transition5", mediaItem5,
+                mediaItem6, 1000/*4000*/, Transition.BEHAVIOR_SPEED_UP,
+                TransitionSliding.DIRECTION_LEFT_OUT_RIGHT_IN);
+        mVideoEditor.addTransition(transition5And6);
+
+        final TransitionSliding transition6 =
+            mVideoEditorHelper.createTSliding("transition6", mediaItem6, null,
+                1000 /*4000*/, Transition.BEHAVIOR_SPEED_UP,
+                TransitionSliding.DIRECTION_TOP_OUT_BOTTOM_IN);
+        mVideoEditor.addTransition(transition6);
+
+        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
+            public void onProgress(Object item, int action, int progress) {
+            }
+        });
+
+        try {
+            final int[] progressUpdate = new int[100];
+            mVideoEditor.export(outFilename, MediaProperties.HEIGHT_720,
+                MediaProperties.BITRATE_800K, new ExportProgressListener() {
+                    int i = 0;
+                    public void onProgress(VideoEditor ve, String outFileName,
+                        int progress) {
+                            progressUpdate[i++] = progress;
+                    }
+                });
+            mVideoEditorHelper.checkProgressCBValues(progressUpdate);
+        } catch (Exception e) {
+            assertTrue("Error in Export" + e.toString(), false);
+        }
+        final long storyBoardDuration = mediaItem1.getTimelineDuration()
+            + mediaItem2.getTimelineDuration()
+            + mediaItem3.getTimelineDuration() - transition2And3.getDuration()
+            + mediaItem4.getTimelineDuration() - transition3And4.getDuration()
+            + mediaItem5.getTimelineDuration() - transition4And5.getDuration()
+            + mediaItem6.getTimelineDuration() - transition5And6.getDuration();
+        mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
+            MediaProperties.HEIGHT_720, 0, storyBoardDuration,
+            MediaProperties.VCODEC_H264BP, MediaProperties.ACODEC_AAC_LC);
+        mVideoEditorHelper.checkDeleteExistingFile(outFilename);
+    }
+
+    /**
+     * To Test Export : Without any Media Items in the story Board
+     *
+     * @throws Exception
+     */
+    // TODO :remove TC_EXP_006
+    @LargeTest
+    public void testExportWithoutMediaItems() throws Exception {
+        boolean flagForException = false;
+        try {
+            final int[] progressUpdate = new int[100];
+            mVideoEditor.export("/sdcard/Test.3gp", MediaProperties.HEIGHT_720,
+                MediaProperties.BITRATE_800K, new ExportProgressListener() {
+                    int i = 0;
+                    public void onProgress(VideoEditor ve, String outFileName,
+                        int progress) {
+                            progressUpdate[i++] = progress;
+                    }
+                });
+            mVideoEditorHelper.checkProgressCBValues(progressUpdate);
+        } catch (IllegalStateException e) {
+            flagForException = true;
+        }
+        assertTrue("Export without any MediaItems", flagForException);
+    }
+
+    /**
+     * To Test Export : With Media Items add and removed in the story Board
+     *
+     * @throws Exception
+     */
+    // TODO :remove TC_EXP_007
+    @LargeTest
+    public void testExportWithoutMediaItemsAddRemove() throws Exception {
+        final String videoItemFilename1 = INPUT_FILE_PATH +
+            "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_1_17.3gp";
+        final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_640x480.jpg";
+        final String maskFilename = INPUT_FILE_PATH + "TransitionSpiral_QVGA.jpg";
+        boolean flagForException = false;
+
+        final MediaVideoItem mediaItem1 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaItem1.setExtractBoundaries(0, 15000);
+        mVideoEditor.addMediaItem(mediaItem1);
+
+        final MediaImageItem mediaItem2 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
+                imageItemFilename1, 15000,
+                MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaItem2);
+
+        final TransitionAlpha transition1 =
+            mVideoEditorHelper.createTAlpha("transition1", mediaItem1, mediaItem2,
+                3000, Transition.BEHAVIOR_LINEAR, maskFilename, 50, false);
+        mVideoEditor.addTransition(transition1);
+
+        final EffectColor effectColor =
+            mVideoEditorHelper.createEffectItem(mediaItem2, "effect", 12000,
+                3000, EffectColor.TYPE_COLOR, EffectColor.PINK);
+        mediaItem2.addEffect(effectColor);
+
+        mVideoEditor.removeMediaItem(mediaItem1.getId());
+        mVideoEditor.removeMediaItem(mediaItem2.getId());
+        try {
+            final int[] progressUpdate = new int[100];
+            mVideoEditor.export("/sdcard/Test.3gp", MediaProperties.HEIGHT_720,
+                MediaProperties.BITRATE_800K, new ExportProgressListener() {
+                    int i = 0;
+                    public void onProgress(VideoEditor ve, String outFileName,
+                        int progress) {
+                            progressUpdate[i++] = progress;
+                    }
+                });
+            mVideoEditorHelper.checkProgressCBValues(progressUpdate);
+        } catch (IllegalStateException e) {
+            flagForException = true;
+        }
+        assertTrue("Export with MediaItem added and removed", flagForException);
+    }
+
+    /**
+     * To Test Export : With Video and Image : MMS use case
+     *
+     * @throws Exception
+     */
+    // TODO :remove TC_EXP_008
+    @LargeTest
+    public void testExportMMS() throws Exception {
+        final String videoItemFilename1 = INPUT_FILE_PATH
+            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_1_17.3gp";
+        final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
+        final String videoItemFilename2 = INPUT_FILE_PATH
+            + "H264_BP_640x480_12.5fps_256kbps_AACLC_16khz_24kbps_s_0_26.mp4";
+        final String maskFilename = INPUT_FILE_PATH + "TransitionSpiral_QVGA.jpg";
+        final String outFilename = mVideoEditorHelper
+            .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
+
+        final MediaVideoItem mediaItem1 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaItem1.setExtractBoundaries(2000, 7000);
+        mVideoEditor.addMediaItem(mediaItem1);
+
+        final TransitionAlpha transition1 =
+            mVideoEditorHelper.createTAlpha("transition1", null, mediaItem1,
+                2000, Transition.BEHAVIOR_LINEAR, maskFilename, 50, true);
+        mVideoEditor.addTransition(transition1);
+
+        final MediaImageItem mediaItem2 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
+                imageItemFilename1, 8000, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaItem2);
+
+        final MediaVideoItem mediaItem3 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
+                videoItemFilename2, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaItem3.setExtractBoundaries(0, 8000);
+        mVideoEditor.addMediaItem(mediaItem3);
+
+        final TransitionSliding transition2And3 =
+            mVideoEditorHelper.createTSliding("transition2", mediaItem2,
+                mediaItem3, 4000, Transition.BEHAVIOR_MIDDLE_FAST,
+                TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN);
+        mVideoEditor.addTransition(transition2And3);
+
+        final TransitionCrossfade transition3 =
+            mVideoEditorHelper.createTCrossFade("transition3", mediaItem3, null,
+                3500, Transition.BEHAVIOR_MIDDLE_SLOW);
+        mVideoEditor.addTransition(transition3);
+
+        final EffectColor effectColor =
+            mVideoEditorHelper.createEffectItem(mediaItem2, "effect", 0,
+                3000, EffectColor.TYPE_COLOR, EffectColor.PINK);
+        mediaItem2.addEffect(effectColor);
+
+        mVideoEditor.setAspectRatio(MediaProperties.ASPECT_RATIO_11_9);
+
+        try {
+            final int[] progressUpdate = new int[100];
+            mVideoEditor.export(outFilename, MediaProperties.HEIGHT_144,
+                MediaProperties.BITRATE_800K, new ExportProgressListener() {
+                    int i = 0;
+                    public void onProgress(VideoEditor ve, String outFileName,
+                        int progress) {
+                            progressUpdate[i++] = progress;
+                    }
+                });
+            mVideoEditorHelper.checkProgressCBValues(progressUpdate);
+        } catch (Exception e) {
+            assertTrue("Error in Export" + e.toString(), false);
+        }
+        final long storyBoardDuration = mediaItem1.getTimelineDuration()
+            + mediaItem2.getTimelineDuration() + mediaItem3.getTimelineDuration()
+            - transition2And3.getDuration();
+
+        mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
+            MediaProperties.HEIGHT_144, 0, storyBoardDuration,
+            MediaProperties.VCODEC_H264BP, MediaProperties.ACODEC_AAC_LC);
+         mVideoEditorHelper.checkDeleteExistingFile(outFilename);
+    }
+
+    /**
+     * To Test Export :Media Item having duration of 1 Hour
+     *
+     * @throws Exception
+     */
+    @LargeTest
+    public void testExportDuration1Hour() throws Exception {
+        final String videoItemFilename1 = INPUT_FILE_PATH +
+            "H264_BP_640x480_15fps_384kbps_60_0.mp4";
+        final String outFilename = mVideoEditorHelper.createRandomFile(
+            mVideoEditor.getPath() + "/") + ".3gp";
+
+        final MediaVideoItem mediaItem1 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaItem1);
+        try {
+            final int[] progressUpdate = new int[100];
+            mVideoEditor.export(outFilename, MediaProperties.HEIGHT_144,
+                MediaProperties.BITRATE_800K, new ExportProgressListener() {
+                    int i = 0;
+                    public void onProgress(VideoEditor ve, String outFileName,
+                        int progress) {
+                            progressUpdate[i++] = progress;
+                    }
+                });
+            mVideoEditorHelper.checkProgressCBValues(progressUpdate);
+        }catch (Exception e) {
+            assertTrue("Error in Export" + e.toString(), false);
+        }
+        mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
+            MediaProperties.HEIGHT_720, 0, mediaItem1.getDuration(),
+            MediaProperties.VCODEC_H264BP, MediaProperties.ACODEC_AAC_LC);
+        mVideoEditorHelper.checkDeleteExistingFile(outFilename);
+    }
+
+    /**
+     * To Test Export : Storage location having very less space (Less than 100
+     * KB)
+     *
+     * @throws Exception
+     */
+    @LargeTest
+    public void testExportWithStorageFull() throws Exception {
+        final String videoItemFilename1 = INPUT_FILE_PATH
+            + "H264_BP_640x480_12.5fps_256kbps_AACLC_16khz_24kbps_s_0_26.mp4";
+        final String outFilename = mVideoEditorHelper
+            .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
+        boolean flagForException = false;
+
+        mVideoEditorHelper.createMediaItem(mVideoEditor, "m1", videoItemFilename1,
+            MediaItem.RENDERING_MODE_BLACK_BORDER);
+        try {
+            final int[] progressUpdate = new int[100];
+            mVideoEditor.export(outFilename, MediaProperties.HEIGHT_144,
+                MediaProperties.BITRATE_800K, new ExportProgressListener() {
+                    int i = 0;
+                    public void onProgress(VideoEditor ve, String outFileName,
+                        int progress) {
+                            progressUpdate[i++] = progress;
+                    }
+                });
+            mVideoEditorHelper.checkProgressCBValues(progressUpdate);
+        } catch (Exception e) {
+            flagForException = true;
+        }
+        assertTrue("Error in exporting file due to lack of storage space",
+            flagForException);
+    }
+
+     /**
+     * To Test Export :Two Media Items added
+     *
+     * @throws Exception
+     */
+    @LargeTest
+    public void testExportTwoVideos() throws Exception {
+        final String videoItemFileName = INPUT_FILE_PATH
+            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_1_17.3gp";
+        final String videoItemFileName1 = INPUT_FILE_PATH +
+            "H264_BP_640x480_12.5fps_256kbps_AACLC_16khz_24kbps_s_0_26.mp4";
+        final String outFilename = mVideoEditorHelper
+            .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
+
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaVideoItem);
+
+        final MediaVideoItem mediaVideoItem1 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
+                videoItemFileName1, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaVideoItem1);
+
+        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
+            public void onProgress(Object item, int action, int progress) {
+            }
+        });
+
+        try {
+            final int[] progressUpdate = new int[100];
+            mVideoEditor.export(outFilename, MediaProperties.HEIGHT_720,
+                MediaProperties.BITRATE_800K, new ExportProgressListener() {
+                    int i = 0;
+                    public void onProgress(VideoEditor ve, String outFileName,
+                        int progress) {
+                            progressUpdate[i++] = progress;
+                    }
+                });
+            mVideoEditorHelper.checkProgressCBValues(progressUpdate);
+        } catch (Exception e) {
+            assertTrue("Error in Export" + e.toString(), false);
+        }
+        mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
+            MediaProperties.HEIGHT_720, 0,
+            (mediaVideoItem.getDuration()+ mediaVideoItem1.getDuration()),
+            MediaProperties.VCODEC_H264BP, MediaProperties.ACODEC_AAC_LC);
+        mVideoEditorHelper.checkDeleteExistingFile(outFilename);
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorPreviewTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorPreviewTest.java
new file mode 100644
index 0000000..bd0a838
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorPreviewTest.java
@@ -0,0 +1,1161 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.functional;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.concurrent.Semaphore;
+
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.media.videoeditor.AudioTrack;
+import android.media.videoeditor.Effect;
+import android.media.videoeditor.EffectColor;
+import android.media.videoeditor.EffectKenBurns;
+import android.media.videoeditor.MediaImageItem;
+import android.media.videoeditor.MediaItem;
+import android.media.videoeditor.MediaProperties;
+import android.media.videoeditor.MediaVideoItem;
+import android.media.videoeditor.Overlay;
+import android.media.videoeditor.OverlayFrame;
+import android.media.videoeditor.Transition;
+import android.media.videoeditor.TransitionAlpha;
+import android.media.videoeditor.TransitionCrossfade;
+import android.media.videoeditor.TransitionFadeBlack;
+import android.media.videoeditor.TransitionSliding;
+import android.media.videoeditor.VideoEditor;
+import android.media.videoeditor.VideoEditor.ExportProgressListener;
+import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener;
+import android.media.videoeditor.VideoEditor.PreviewProgressListener;
+import android.media.videoeditor.VideoEditor.OverlayData;
+import android.os.Environment;
+import android.test.ActivityInstrumentationTestCase;
+import android.view.SurfaceHolder;
+
+
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import android.test.suitebuilder.annotation.LargeTest;
+import com.android.mediaframeworktest.VideoEditorHelper;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+
+import java.util.concurrent.TimeUnit;
+
+import android.util.Log;
+
+public class VideoEditorPreviewTest extends
+    ActivityInstrumentationTestCase<MediaFrameworkTest> {
+    private final String TAG = "VideoEditorTest";
+
+    private final String PROJECT_LOCATION = VideoEditorHelper.PROJECT_LOCATION_COMMON;
+
+    private final String INPUT_FILE_PATH = VideoEditorHelper.INPUT_FILE_PATH_COMMON;
+
+    private final String PROJECT_CLASS_NAME =
+        "android.media.videoeditor.VideoEditorImpl";
+
+    private VideoEditor mVideoEditor;
+
+    private VideoEditorHelper mVideoEditorHelper;
+
+    private class EventHandler extends Handler {
+        public EventHandler( Looper lp)
+        {
+            super(lp);
+        }
+        public void handleMessage(Message msg)
+        {
+            switch (msg.what)
+            {
+                default:
+                MediaFrameworkTest.testInvalidateOverlay();
+            }
+        }
+    }
+    private EventHandler mEventHandler;
+
+    private boolean previewStart;
+    private boolean previewStop;
+
+    /* Minimum waiting time for Semaphore to wait for release */
+    private final long minWaitingTime = 1000;
+
+    // Declares the annotation for Preview Test Cases
+    public @interface Preview {
+    }
+
+    public VideoEditorPreviewTest() {
+        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+
+        Looper looper;
+        if ((looper = Looper.myLooper()) != null) {
+            mEventHandler = new EventHandler(looper);
+
+        } else {
+            //Handle error when looper can not be created.
+            ;
+        }
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        // setup for each test case.
+        super.setUp();
+        mVideoEditorHelper = new VideoEditorHelper();
+        // Create a random String which will be used as project path, where all
+        // project related files will be stored.
+        final String projectPath =
+            mVideoEditorHelper.createRandomFile(PROJECT_LOCATION);
+        mVideoEditor = mVideoEditorHelper.createVideoEditor(projectPath);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mVideoEditorHelper.destroyVideoEditor(mVideoEditor);
+        // Clean the directory created as project path
+        mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath()));
+        System.gc();
+        super.tearDown();
+    }
+
+    protected void setPreviewStart() {
+        previewStart = true;
+    }
+    protected void setPreviewStop() {
+        previewStop = true;
+    }
+
+    protected void validatePreviewProgress(int startMs, int endMs,
+        boolean loop, long duration) throws Exception {
+
+        final int[] progressUpdate = new int[100];
+        final Semaphore blockTillPreviewCompletes = new Semaphore(1);
+        previewStart = false;
+        previewStop = false;
+        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
+            int i = 0;
+            public void onProgress(Object item, int action, int progress) {
+                progressUpdate[i++] = progress;
+            }
+        });
+        mVideoEditorHelper.checkProgressCBValues(progressUpdate);
+        final SurfaceHolder surfaceHolder =
+            MediaFrameworkTest.mSurfaceView.getHolder();
+
+        long waitingTime = minWaitingTime;
+        if (endMs == -1) {
+            waitingTime += duration;
+        }
+        else {
+            waitingTime += (endMs - startMs);
+        }
+        blockTillPreviewCompletes.acquire();
+        try {
+        mVideoEditor.startPreview(surfaceHolder, startMs, endMs, loop, 1,
+            new PreviewProgressListener() {
+                public void onProgress(VideoEditor videoEditor, long timeMs,
+                    OverlayData overlayData) {
+
+                        if ( overlayData != null) {
+                            if(overlayData.needsRendering()) {
+                                overlayData.renderOverlay(MediaFrameworkTest.mDestBitmap);
+                                mEventHandler.sendMessage(mEventHandler.obtainMessage(1, 2, 3));
+                            }
+                        }
+                }
+                public void onStart(VideoEditor videoEditor) {
+                    setPreviewStart();
+                }
+                public void onStop(VideoEditor videoEditor) {
+                    setPreviewStop();
+                    blockTillPreviewCompletes.release();
+                }
+        });
+        } catch (Exception e) {
+            blockTillPreviewCompletes.release();
+        }
+        blockTillPreviewCompletes.tryAcquire(waitingTime, TimeUnit.MILLISECONDS);
+
+        mVideoEditor.stopPreview();
+        assertTrue("Preview Failed to start", previewStart);
+        assertTrue("Preview Failed to stop", previewStop);
+
+        blockTillPreviewCompletes.release();
+    }
+
+    // -----------------------------------------------------------------
+    // Preview
+    // -----------------------------------------------------------------
+
+    /**
+     *To test Preview : FULL Preview of current work (beginning till end)
+     */
+    // TODO : remove TC_PRV_001
+    @LargeTest
+    public void testPreviewTheStoryBoard() throws Exception {
+        final String videoItemFileName1 = INPUT_FILE_PATH
+            + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
+        final String videoItemFileName2 = INPUT_FILE_PATH
+            + "MPEG4_SP_640x480_15fps_256kbps_0_30.mp4";
+        final String videoItemFileName3 = INPUT_FILE_PATH
+            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_1_17.3gp";
+        previewStart = false;
+        previewStop = false;
+        final MediaVideoItem mediaVideoItem1 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
+                videoItemFileName1, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaVideoItem1.setExtractBoundaries(0, 10000);
+        mVideoEditor.addMediaItem(mediaVideoItem1);
+
+        final MediaVideoItem mediaVideoItem2 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem2",
+                videoItemFileName2, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaVideoItem2);
+        mediaVideoItem2.setExtractBoundaries(0, 10000);
+
+        final MediaVideoItem mediaVideoItem3 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem3",
+                videoItemFileName3, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaVideoItem3.setExtractBoundaries(0, 10000);
+
+        mVideoEditor.insertMediaItem(mediaVideoItem3, mediaVideoItem1.getId());
+        List<MediaItem> mediaList = mVideoEditor.getAllMediaItems();
+        assertEquals("Media Item 1", mediaVideoItem1, mediaList.get(0));
+        assertEquals("Media Item 3", mediaVideoItem3, mediaList.get(1));
+        assertEquals("Media Item 2", mediaVideoItem2, mediaList.get(2));
+
+        mediaVideoItem1.setRenderingMode(MediaItem.RENDERING_MODE_BLACK_BORDER);
+        assertEquals("Media Item 1 Rendering Mode",
+            MediaItem.RENDERING_MODE_BLACK_BORDER,
+            mediaVideoItem1.getRenderingMode());
+
+        mediaVideoItem2.setRenderingMode(MediaItem.RENDERING_MODE_BLACK_BORDER);
+        assertEquals("Media Item 2 Rendering Mode",
+            MediaItem.RENDERING_MODE_BLACK_BORDER,
+            mediaVideoItem2.getRenderingMode());
+
+        mediaVideoItem3.setRenderingMode(MediaItem.RENDERING_MODE_STRETCH);
+        assertEquals("Media Item 3 Rendering Mode",
+            MediaItem.RENDERING_MODE_STRETCH,
+            mediaVideoItem3.getRenderingMode());
+
+        mVideoEditor.setAspectRatio(MediaProperties.ASPECT_RATIO_5_3);
+        assertEquals("Aspect Ratio", MediaProperties.ASPECT_RATIO_5_3,
+            mVideoEditor.getAspectRatio());
+
+        validatePreviewProgress(0, -1, false, mVideoEditor.getDuration());
+    }
+
+    /**
+     * To test Preview : Preview of start + 10 sec till end of story board
+     */
+    // TODO : remove TC_PRV_002
+    @LargeTest
+    public void testPreviewTheStoryBoardFromDuration() throws Exception {
+        final String videoItemFileName1 = INPUT_FILE_PATH
+            + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
+        final String videoItemFileName2 = INPUT_FILE_PATH +
+            "MPEG4_SP_640x480_15fps_256kbps_0_30.mp4";
+        final String videoItemFileName3 = INPUT_FILE_PATH
+            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_1_17.3gp";
+        final Semaphore blockTillPreviewCompletes = new Semaphore(1);
+        previewStart = false;
+        previewStop = false;
+        final MediaVideoItem mediaVideoItem1 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
+                videoItemFileName1, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaVideoItem1.setExtractBoundaries(0, 10000);
+        mVideoEditor.addMediaItem(mediaVideoItem1);
+
+        final MediaVideoItem mediaVideoItem2 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem2",
+                videoItemFileName2, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaVideoItem2.setExtractBoundaries(0, 10000);
+        mVideoEditor.addMediaItem(mediaVideoItem2);
+
+        final MediaVideoItem mediaVideoItem3 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem3",
+                videoItemFileName3, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaVideoItem3.setExtractBoundaries(0, 10000);
+
+        mVideoEditor.insertMediaItem(mediaVideoItem3, mediaVideoItem1.getId());
+
+        List<MediaItem> mediaList = mVideoEditor.getAllMediaItems();
+        assertEquals("Media Item 1", mediaVideoItem1, mediaList.get(0));
+        assertEquals("Media Item 3", mediaVideoItem3, mediaList.get(1));
+        assertEquals("Media Item 2", mediaVideoItem2, mediaList.get(2));
+        mediaVideoItem1.setRenderingMode(MediaItem.RENDERING_MODE_BLACK_BORDER);
+
+        assertEquals("Media Item 1 Rendering Mode",
+            MediaItem.RENDERING_MODE_BLACK_BORDER,
+            mediaVideoItem1.getRenderingMode());
+        mediaVideoItem2.setRenderingMode(MediaItem.RENDERING_MODE_BLACK_BORDER);
+
+        assertEquals("Media Item 2 Rendering Mode",
+            MediaItem.RENDERING_MODE_BLACK_BORDER,
+            mediaVideoItem2.getRenderingMode());
+        mediaVideoItem3.setRenderingMode(MediaItem.RENDERING_MODE_STRETCH);
+
+        assertEquals("Media Item 3 Rendering Mode",
+            MediaItem.RENDERING_MODE_STRETCH,
+            mediaVideoItem3.getRenderingMode());
+
+        mVideoEditor.setAspectRatio(MediaProperties.ASPECT_RATIO_5_3);
+        assertEquals("Aspect Ratio", MediaProperties.ASPECT_RATIO_5_3,
+            mVideoEditor.getAspectRatio());
+
+        validatePreviewProgress(10000, -1, false, mVideoEditor.getDuration());
+    }
+
+    /**
+     * To test Preview : Preview of current Effects applied
+     */
+    // TODO : remove TC_PRV_003
+    @LargeTest
+    public void testPreviewOfEffects() throws Exception {
+        final String videoItemFileName1 = INPUT_FILE_PATH +
+            "H264_BP_640x480_30fps_256kbps_1_17.mp4";
+
+        final Semaphore blockTillPreviewCompletes = new Semaphore(1);
+        previewStart = false;
+        previewStop = false;
+        final MediaVideoItem mediaVideoItem1 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
+                videoItemFileName1, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaVideoItem1);
+
+        final EffectColor effectNegative =
+            mVideoEditorHelper.createEffectItem(mediaVideoItem1,
+                "effectNegative", 0, 2000, EffectColor.TYPE_NEGATIVE, 0);
+        mediaVideoItem1.addEffect(effectNegative);
+
+        final EffectColor effectGreen =
+            mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effectGreen",
+                2000, 3000, EffectColor.TYPE_COLOR, EffectColor.GREEN);
+        mediaVideoItem1.addEffect(effectGreen);
+
+        final EffectColor effectFifties =
+            mVideoEditorHelper.createEffectItem(mediaVideoItem1,
+                "effectFifties", 5000, 4000, EffectColor.TYPE_FIFTIES, 0);
+        mediaVideoItem1.addEffect(effectFifties);
+
+        List<Effect> effectList = mediaVideoItem1.getAllEffects();
+        assertEquals("Effect List Size", 3, effectList.size());
+        assertEquals("Effect negative", effectNegative, effectList.get(0));
+        assertEquals("Effect Green", effectGreen, effectList.get(1));
+        assertEquals("Effect Fifties", effectFifties, effectList.get(2));
+
+        mVideoEditor.setAspectRatio(MediaProperties.ASPECT_RATIO_4_3);
+        assertEquals("Aspect Ratio", MediaProperties.ASPECT_RATIO_4_3,
+            mVideoEditor.getAspectRatio());
+
+        final long storyboardDuration = mVideoEditor.getDuration() ;
+        validatePreviewProgress(0, (int)(storyboardDuration/2), false, (storyboardDuration/2));
+
+        assertEquals("Removing Effect : Negative", effectNegative,
+            mediaVideoItem1.removeEffect(effectNegative.getId()));
+
+        effectList = mediaVideoItem1.getAllEffects();
+
+        assertEquals("Effect List Size", 2, effectList.size());
+        assertEquals("Effect Green", effectGreen, effectList.get(0));
+        assertEquals("Effect Fifties", effectFifties, effectList.get(1));
+
+        validatePreviewProgress(0, -1, false, mVideoEditor.getDuration());
+    }
+
+    /**
+     *To test Preview : Preview of current Transitions applied (with multiple
+     * generatePreview)
+     */
+    // TODO : remove TC_PRV_004
+    @LargeTest
+    public void testPreviewWithTransition() throws Exception {
+
+        final String videoItemFileName1 = INPUT_FILE_PATH +
+            "H263_profile0_176x144_10fps_96kbps_0_25.3gp";
+        final String imageItemFileName1 = INPUT_FILE_PATH +
+            "IMG_1600x1200.jpg";
+        final String videoItemFileName2 = INPUT_FILE_PATH +
+            "MPEG4_SP_800x480_515kbps_15fps_AMR_NB_8KHz_12.2kbps_m_0_26.mp4";
+        final String maskFilename = INPUT_FILE_PATH +
+            "TransitionSpiral_QVGA.jpg";
+        previewStart = false;
+        previewStop = false;
+
+        final Semaphore blockTillPreviewCompletes = new Semaphore(1);
+
+        final MediaVideoItem mediaVideoItem1 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFileName1, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaVideoItem1.setExtractBoundaries(0, 10000);
+        mVideoEditor.addMediaItem(mediaVideoItem1);
+
+        final MediaImageItem mediaImageItem1 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
+                imageItemFileName1, 10000, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaImageItem1);
+
+        final MediaVideoItem mediaVideoItem2 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
+                videoItemFileName2, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaVideoItem2.setExtractBoundaries(0, 10000);
+        mVideoEditor.addMediaItem(mediaVideoItem2);
+
+        final TransitionCrossfade transition1And2CrossFade =
+            mVideoEditorHelper.createTCrossFade("transition_1_2_CF",
+                mediaVideoItem1, mediaImageItem1, 2000,
+                Transition.BEHAVIOR_MIDDLE_FAST);
+        mVideoEditor.addTransition(transition1And2CrossFade);
+
+        final TransitionAlpha transition2And3Alpha =
+            mVideoEditorHelper.createTAlpha("transition_2_3", mediaImageItem1,
+                mediaVideoItem2, 4000, Transition.BEHAVIOR_SPEED_UP,
+                maskFilename, 50, true);
+        mVideoEditor.addTransition(transition2And3Alpha);
+
+        final TransitionFadeBlack transition1FadeBlack =
+            mVideoEditorHelper.createTFadeBlack("transition_1FB", null,
+                mediaVideoItem1, 2000, Transition.BEHAVIOR_MIDDLE_FAST);
+        mVideoEditor.addTransition(transition1FadeBlack);
+
+        List<Transition> transitionList = mVideoEditor.getAllTransitions();
+        assertEquals("Transition List Size", 3, transitionList.size());
+        assertEquals("Transition 1", transition1And2CrossFade,
+            transitionList.get(0));
+        assertEquals("Transition 2", transition2And3Alpha, transitionList.get(1));
+        assertEquals("Transition 3", transition1FadeBlack, transitionList.get(2));
+
+        mVideoEditor.setAspectRatio(MediaProperties.ASPECT_RATIO_3_2);
+
+        final int[] progressValues = new int[300];
+        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
+            int i = 0;
+
+            public void onProgress(Object item, int action, int progress) {
+                if (item instanceof TransitionCrossfade) {
+                    progressValues[i] = progress;
+                    assertEquals("Object", item, transition1And2CrossFade);
+                    assertEquals("Action", action,
+                        MediaProcessingProgressListener.ACTION_ENCODE);
+                } else if (item instanceof TransitionAlpha) {
+                    progressValues[i] = progress;
+                    assertEquals("Object", item, transition2And3Alpha);
+                    assertEquals("Action", action,
+                        MediaProcessingProgressListener.ACTION_ENCODE);
+                } else if (item instanceof TransitionFadeBlack) {
+                    progressValues[i] = progress;
+                    assertEquals("Object", item, transition1FadeBlack);
+                    assertEquals("Action", action,
+                        MediaProcessingProgressListener.ACTION_ENCODE);
+                }
+                i++;
+            }
+        });
+
+        mVideoEditorHelper.checkProgressCBValues(progressValues);
+        final SurfaceHolder surfaceHolder =
+            MediaFrameworkTest.mSurfaceView.getHolder();
+
+        long waitingTime = minWaitingTime + 10000;
+
+        blockTillPreviewCompletes.acquire();
+        try {
+        mVideoEditor.startPreview(surfaceHolder, 0, 10000, false, 1,
+            new PreviewProgressListener() {
+            public void onProgress(VideoEditor videoEditor, long timeMs,
+                OverlayData overlayData) {
+                }
+                public void onStart(VideoEditor videoEditor) {
+                    setPreviewStart();
+                }
+                public void onStop(VideoEditor videoEditor) {
+                    setPreviewStop();
+                    blockTillPreviewCompletes.release();
+                }
+        });
+        } catch (Exception e) {
+            blockTillPreviewCompletes.release();
+        }
+        blockTillPreviewCompletes.tryAcquire(waitingTime, TimeUnit.MILLISECONDS);
+        mVideoEditor.stopPreview();
+        blockTillPreviewCompletes.release();
+        assertTrue("Preview Failed to start", previewStart);
+        assertTrue("Preview Failed to stop", previewStop);
+
+        assertEquals("Removing Transition " + transition1And2CrossFade.getId(),
+            transition1And2CrossFade,
+            mVideoEditor.removeTransition(transition1And2CrossFade.getId()));
+        transitionList = mVideoEditor.getAllTransitions();
+        assertEquals("Transition List Size", 2, transitionList.size());
+        assertEquals("Transition 1", transition2And3Alpha, transitionList.get(0));
+        assertEquals("Transition 2", transition1FadeBlack, transitionList.get(1));
+
+        validatePreviewProgress(0, -1, false, mVideoEditor.getDuration());
+
+
+        final TransitionSliding transition1And2Sliding =
+            mVideoEditorHelper.createTSliding("transition_1_2Sliding",
+                mediaVideoItem1, mediaImageItem1, 4000,
+                Transition.BEHAVIOR_MIDDLE_FAST,
+                TransitionSliding.DIRECTION_LEFT_OUT_RIGHT_IN);
+        mVideoEditor.addTransition(transition1And2Sliding);
+
+        transitionList = mVideoEditor.getAllTransitions();
+        assertEquals("Transition List Size", 3, transitionList.size());
+        assertEquals("Transition 1", transition2And3Alpha, transitionList.get(0));
+        assertEquals("Transition 2", transition1FadeBlack, transitionList.get(1));
+        assertEquals("Transition 3", transition1And2Sliding,
+            transitionList.get(2));
+
+        validatePreviewProgress(5000, -1, false, (mVideoEditor.getDuration()));
+
+    }
+
+    /**
+     * To test Preview : Preview of current Overlay applied
+     */
+    // TODO : remove TC_PRV_005
+    @LargeTest
+    public void testPreviewWithOverlay() throws Exception {
+        final String videoItemFileName = INPUT_FILE_PATH
+            + "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp";
+        final String overlayFilename1 = INPUT_FILE_PATH +
+            "IMG_640x480_Overlay1.png";
+        final String overlayFilename2 = INPUT_FILE_PATH +
+            "IMG_640x480_Overlay2.png";
+        final int previewFrom = 5000;
+        final int previewTo = 10000;
+        final boolean previewLoop = false;
+        final int previewCallbackFrameCount = 1;
+        final int setAspectRatio = MediaProperties.ASPECT_RATIO_4_3;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final Semaphore blockTillPreviewCompletes = new Semaphore(1);
+        previewStart = false;
+        previewStop = false;
+        boolean flagForException = false;
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFileName, renderingMode);
+        mVideoEditor.addMediaItem(mediaVideoItem);
+        mediaVideoItem.setExtractBoundaries(0, 10000);
+
+        final Bitmap mBitmap1 =  mVideoEditorHelper.getBitmap(overlayFilename1,
+            640, 480);
+        final OverlayFrame overlayOnMvi1 =
+            mVideoEditorHelper.createOverlay(mediaVideoItem, "OverlayOnMvi1",
+                mBitmap1, 0, 5000);
+        mediaVideoItem.addOverlay(overlayOnMvi1);
+
+        final Bitmap mBitmap2 =  mVideoEditorHelper.getBitmap(overlayFilename2,
+            640, 480);
+        final OverlayFrame overlayOnMvi2 =
+            mVideoEditorHelper.createOverlay(mediaVideoItem, "OverlayOnMvi2",
+                mBitmap2, 5000, 9000);
+        mediaVideoItem.addOverlay(overlayOnMvi2);
+
+        List<Overlay> overlayList = mediaVideoItem.getAllOverlays();
+        assertEquals("Overlay Size", 2, overlayList.size());
+        assertEquals("Overlay 1", overlayOnMvi1, overlayList.get(0));
+        assertEquals("Overlay 2", overlayOnMvi2, overlayList.get(1));
+
+        mVideoEditor.setAspectRatio(setAspectRatio);
+
+        validatePreviewProgress(0 /* previewFrom */, -1, previewLoop,
+            mVideoEditor.getDuration());
+    }
+
+    /**
+     * To test Preview : Preview of current Trim applied (with default aspect
+     * ratio)
+     */
+    // TODO : remove TC_PRV_006
+    @LargeTest
+    public void testPreviewWithTrim() throws Exception {
+        final String videoItemFileName = INPUT_FILE_PATH +
+            "H264_BP_640x480_30fps_192kbps_1_5.mp4";
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFileName, MediaItem.RENDERING_MODE_CROPPING);
+        final Semaphore blockTillPreviewCompletes = new Semaphore(1);
+        boolean flagForException = false;
+        previewStart = false;
+        previewStop = false;
+        mediaVideoItem.setExtractBoundaries(mediaVideoItem.getDuration() / 2,
+            mediaVideoItem.getDuration());
+        mVideoEditor.addMediaItem(mediaVideoItem);
+
+        validatePreviewProgress(1000, -1, false, mVideoEditor.getDuration());
+    }
+
+    /**
+     * To test Preview : Preview of current work having Overlay and Effect
+     * applied
+     */
+
+    // TODO : remove TC_PRV_007
+    @LargeTest
+    public void testPreviewWithOverlayEffectKenBurn() throws Exception {
+
+        final String videoItemFileName = INPUT_FILE_PATH +
+            "H264_BP_640x480_30fps_192kbps_1_5.mp4";
+        final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
+        final String videoItemFileName1 = INPUT_FILE_PATH +
+            "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
+        final String overlayFilename = INPUT_FILE_PATH +
+            "IMG_640x480_Overlay1.png";
+        final Semaphore blockTillPreviewCompletes = new Semaphore(1);
+        previewStart = false;
+        previewStop = false;
+        final MediaVideoItem mediaVideoItem1 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaVideoItem1);
+
+        final MediaImageItem mediaImageItem2 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
+                imageItemFileName, 10000, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaImageItem2);
+
+        final MediaVideoItem mediaVideoItem3 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
+                videoItemFileName1, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaVideoItem3);
+
+        final EffectColor effectColor =
+            mVideoEditorHelper.createEffectItem(mediaVideoItem1, "Effect1",
+                1000, 3000, EffectColor.TYPE_COLOR, EffectColor.GREEN);
+        mediaVideoItem1.addEffect(effectColor);
+
+        final Rect startRect = new Rect((mediaImageItem2.getHeight() / 3),
+            (mediaImageItem2.getWidth() / 3), (mediaImageItem2.getHeight() / 2),
+            (mediaImageItem2.getWidth() / 2));
+        final Rect endRect = new Rect(0, 0, mediaImageItem2.getWidth(),
+            mediaImageItem2.getHeight());
+
+        final EffectKenBurns kbeffectOnMI2 = new EffectKenBurns(mediaImageItem2,
+            "KBOnM2", startRect, endRect, 0, 10000);
+        assertNotNull("EffectKenBurns", kbeffectOnMI2);
+        mediaImageItem2.addEffect(kbeffectOnMI2);
+
+        final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(overlayFilename,
+            640, 480);
+        final OverlayFrame overlayFrame =
+            mVideoEditorHelper.createOverlay(mediaVideoItem3, "OverlayID",
+                mBitmap, (mediaImageItem2.getDuration() / 4),
+                (mediaVideoItem3.getDuration() / 3));
+        mediaVideoItem3.addOverlay(overlayFrame);
+
+        validatePreviewProgress(5000, -1, false, mVideoEditor.getDuration());
+    }
+
+    /**
+     *To test Preview : Export during preview
+     */
+    // TODO : remove TC_PRV_008
+    @LargeTest
+    public void testPreviewDuringExport() throws Exception {
+        final String videoItemFileName = INPUT_FILE_PATH +
+            "H264_BP_640x480_30fps_192kbps_1_5.mp4";
+        final Semaphore blockTillPreviewCompletes = new Semaphore(1);
+        previewStart = false;
+        previewStop = false;
+
+        final MediaVideoItem mediaVideoItem1 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaVideoItem1.setExtractBoundaries(0, 20000);
+        mVideoEditor.addMediaItem(mediaVideoItem1);
+
+        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
+            public void onProgress(Object item, int action, int progress) {
+            }
+        });
+
+        long waitingTime = minWaitingTime + mVideoEditor.getDuration();
+
+        blockTillPreviewCompletes.acquire();
+
+        final SurfaceHolder surfaceHolder =
+            MediaFrameworkTest.mSurfaceView.getHolder();
+        try {
+            mVideoEditor.startPreview(surfaceHolder, 5000, -1, false, 1,
+                new PreviewProgressListener() {
+                    final String fileName = mVideoEditor.getPath() + "\test.3gp";
+                    final int height = MediaProperties.HEIGHT_360;
+                    final int bitrate = MediaProperties.BITRATE_512K;
+                    public void onProgress(VideoEditor videoEditor, long timeMs,
+                        OverlayData overlayData) {
+                            if (timeMs >= 10000)
+                            try {
+                                videoEditor.export(fileName, height, bitrate,
+                                    new ExportProgressListener() {
+                                        public void onProgress(VideoEditor ve,
+                                            String outFileName,int progress) {
+
+                                        }
+                                    });
+                            } catch (IOException e) {
+                                assertTrue("UnExpected Error in Export" +
+                                    e.toString(), false);
+                        }
+                    }
+                public void onStart(VideoEditor videoEditor) {
+                    setPreviewStart();
+                }
+                public void onStop(VideoEditor videoEditor) {
+                    setPreviewStop();
+                    blockTillPreviewCompletes.release();
+                }
+            });
+        } catch (Exception e) {
+            blockTillPreviewCompletes.release();
+        }
+
+        blockTillPreviewCompletes.tryAcquire(waitingTime, TimeUnit.MILLISECONDS);
+        mVideoEditor.stopPreview();
+        assertTrue("Preview Failed to start", previewStart);
+        assertTrue("Preview Failed to stop", previewStop);
+        blockTillPreviewCompletes.release();
+    }
+
+    /**
+     * To test Preview : Preview of current Effects applied (with from time >
+     * total duration)
+     */
+    // TODO : remove TC_PRV_009
+    @LargeTest
+    public void testPreviewWithDurationGreaterThanMediaDuration()
+        throws Exception {
+        final String videoItemFileName = INPUT_FILE_PATH +
+            "H264_BP_640x480_30fps_192kbps_1_5.mp4";
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        boolean flagForException = false;
+        final Semaphore blockTillPreviewCompletes = new Semaphore(1);
+
+        final MediaVideoItem mediaVideoItem1 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFileName, renderingMode);
+        try {
+            mediaVideoItem1.setExtractBoundaries(0, 20000);
+        } catch (Exception e) {
+            assertTrue("Exception during setExtract Boundaries", false);
+        }
+        mVideoEditor.addMediaItem(mediaVideoItem1);
+        final SurfaceHolder surfaceHolder =
+            MediaFrameworkTest.mSurfaceView.getHolder();
+        long waitingTime = minWaitingTime + (mVideoEditor.getDuration() - 30000);
+        if(waitingTime < 0)
+        {
+            waitingTime = minWaitingTime;
+        }
+
+        blockTillPreviewCompletes.acquire();
+        try {
+            mVideoEditor.startPreview(surfaceHolder, 30000, -1, true, 1,
+            new PreviewProgressListener() {
+                public void onProgress(VideoEditor videoEditor, long timeMs,
+                    OverlayData overlayData) {
+            }
+                public void onStart(VideoEditor videoEditor) {
+                    setPreviewStart();
+                }
+                public void onStop(VideoEditor videoEditor) {
+                    setPreviewStop();
+                    blockTillPreviewCompletes.release();
+                }
+        });
+
+        } catch (IllegalArgumentException e) {
+            blockTillPreviewCompletes.release();
+            flagForException = true;
+        }
+        blockTillPreviewCompletes.tryAcquire(waitingTime, TimeUnit.MILLISECONDS);
+        assertTrue("Expected Error in Preview", flagForException);
+        mVideoEditor.stopPreview();
+        blockTillPreviewCompletes.release();
+    }
+
+    /**
+     * To test Preview : Preview of current Effects applied (with Render Preview
+     * Frame)
+     */
+    // TODO : remove TC_PRV_010
+    @LargeTest
+    public void testPreviewWithRenderPreviewFrame() throws Exception {
+        final String videoItemFileName = INPUT_FILE_PATH +
+            "H264_BP_640x480_30fps_256kbps_1_17.mp4";
+        final Semaphore blockTillPreviewCompletes = new Semaphore(1);
+        boolean flagForException = false;
+        OverlayData overlayData1 = new OverlayData();
+        previewStart = false;
+        previewStop = false;
+
+        final String overlayFilename1 = INPUT_FILE_PATH +
+            "IMG_640x480_Overlay1.png";
+
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor,
+            "m1", videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaVideoItem);
+
+        final EffectColor effectPink =
+            mVideoEditorHelper.createEffectItem(mediaVideoItem,
+                "effectNegativeOnMvi", 1000, 3000, EffectColor.TYPE_COLOR,
+                 EffectColor.PINK);
+        mediaVideoItem.addEffect(effectPink);
+
+        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
+            public void onProgress(Object item, int action, int progress) {
+            }
+        });
+        final SurfaceHolder surfaceHolder =
+            MediaFrameworkTest.mSurfaceView.getHolder();
+
+        assertEquals("Render preview Frame at 5 Sec", 5000,
+            mVideoEditor.renderPreviewFrame(surfaceHolder, 5000,
+            overlayData1));
+
+        assertEquals("Render preview Frame at 7 Sec", 7000,
+            mVideoEditor.renderPreviewFrame(surfaceHolder, 7000,
+            overlayData1));
+
+        long waitingTime = minWaitingTime + (mVideoEditor.getDuration() - 5000);
+
+        blockTillPreviewCompletes.acquire();
+        try {
+            mVideoEditor.startPreview(surfaceHolder, 5000, -1, false, 1,
+                new PreviewProgressListener() {
+                    public void onProgress(VideoEditor videoEditor, long timeMs,
+                        OverlayData overlayData) {
+                    }
+                    public void onStart(VideoEditor videoEditor) {
+                        setPreviewStart();
+                    }
+                    public void onStop(VideoEditor videoEditor) {
+                        setPreviewStop();
+                        blockTillPreviewCompletes.release();
+                    }
+            });
+        } catch (Exception e) {
+            blockTillPreviewCompletes.release();
+        }
+        blockTillPreviewCompletes.tryAcquire(waitingTime, TimeUnit.MILLISECONDS);
+        mVideoEditor.stopPreview();
+        assertTrue("Preview Failed to start", previewStart);
+        assertTrue("Preview Failed to stop", previewStop);
+        blockTillPreviewCompletes.release();
+    }
+
+    /**
+     * To test Preview : Preview of current work from selected jump location
+     * till end with Audio Track
+     */
+    // TODO : remove TC_PRV_011
+    @LargeTest
+    public void testPreviewWithEndAudioTrack() throws Exception {
+        final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
+        final String videoItemFileName = INPUT_FILE_PATH +
+            "H264_BP_640x480_30fps_256kbps_1_17.mp4";
+        final String imageItemFilename2 = INPUT_FILE_PATH + "IMG_640x480.jpg";
+        final String audioFilename = INPUT_FILE_PATH +
+            "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
+
+        boolean flagForException = false;
+        previewStart = false;
+        previewStop = false;
+        final MediaImageItem mediaImageItem1 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                imageItemFilename1, 7000, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaImageItem1);
+
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
+                videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaVideoItem.setExtractBoundaries(1000, 8000);
+        mVideoEditor.addMediaItem(mediaVideoItem);
+
+        final MediaImageItem mediaImageItem2 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
+                imageItemFilename2, 7000, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaImageItem2);
+
+        final AudioTrack audioTrack =
+            mVideoEditorHelper.createAudio(mVideoEditor, "a1", audioFilename);
+        mVideoEditor.addAudioTrack(audioTrack);
+
+        List<AudioTrack> audioList = mVideoEditor.getAllAudioTracks();
+        assertEquals("Audio Track List size", 1, audioList.size());
+        assertEquals("Audio Track", audioTrack, audioList.get(0));
+        mVideoEditor.setAspectRatio(MediaProperties.ASPECT_RATIO_4_3);
+
+        validatePreviewProgress(10000, -1, false, mVideoEditor.getDuration());
+    }
+
+    /**
+     * To test render Preview Frame
+     */
+    // TODO : remove TC_PRV_012
+    @LargeTest
+    public void testRenderPreviewFrame() throws Exception {
+        final String videoItemFileName1 = INPUT_FILE_PATH
+            + "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
+        final String videoItemFileName2 = INPUT_FILE_PATH
+            + "MPEG4_SP_800x480_515kbps_15fps_AMR_NB_8KHz_12.2kbps_m_0_26.mp4";
+        final String videoItemFileName3 = INPUT_FILE_PATH
+            + "H264_BP_640x480_30fps_256kbps_1_17.mp4";
+        final String imageItemFilename1 = INPUT_FILE_PATH
+            + "IMG_1600x1200.jpg";
+        final String imageItemFilename2 = INPUT_FILE_PATH
+            + "IMG_176x144.jpg";
+        final String audioFilename = INPUT_FILE_PATH
+            + "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
+        OverlayData overlayData1 = new OverlayData();
+        previewStart = false;
+        previewStop = false;
+        final MediaVideoItem mediaVideoItem1 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFileName1, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaVideoItem1.setExtractBoundaries(0, 10000);
+        mVideoEditor.addMediaItem(mediaVideoItem1);
+
+        final MediaVideoItem mediaVideoItem2 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
+                videoItemFileName2, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaVideoItem1.setExtractBoundaries(mediaVideoItem2.getDuration() / 4,
+            mediaVideoItem2.getDuration() / 2);
+        mVideoEditor.addMediaItem(mediaVideoItem2);
+
+        final MediaVideoItem mediaVideoItem3 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
+                videoItemFileName3, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaVideoItem1.setExtractBoundaries(mediaVideoItem2.getDuration() / 2,
+            mediaVideoItem2.getDuration());
+        mVideoEditor.addMediaItem(mediaVideoItem3);
+
+        final MediaImageItem mediaImageItem4 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m4",
+                imageItemFilename1, 5000, MediaItem.RENDERING_MODE_BLACK_BORDER);
+
+        final MediaImageItem mediaImageItem5 =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m5",
+                imageItemFilename2, 5000, MediaItem.RENDERING_MODE_BLACK_BORDER);
+
+        List<MediaItem> mediaList = mVideoEditor.getAllMediaItems();
+        assertEquals("Media Item List Size", 3, mediaList.size());
+
+        mVideoEditor.insertMediaItem(mediaImageItem4, mediaVideoItem2.getId());
+        mediaList = mVideoEditor.getAllMediaItems();
+        assertEquals("Media Item List Size", 4, mediaList.size());
+        assertEquals("Media item 1", mediaVideoItem1, mediaList.get(0));
+        assertEquals("Media item 2", mediaVideoItem2, mediaList.get(1));
+        assertEquals("Media item 4", mediaImageItem4, mediaList.get(2));
+        assertEquals("Media item 3", mediaVideoItem3, mediaList.get(3));
+
+        mVideoEditor.insertMediaItem(mediaImageItem5, mediaImageItem4.getId());
+        mediaList = mVideoEditor.getAllMediaItems();
+        assertEquals("Media Item List Size", 5, mediaList.size());
+        assertEquals("Media item 1", mediaVideoItem1, mediaList.get(0));
+        assertEquals("Media item 2", mediaVideoItem2, mediaList.get(1));
+        assertEquals("Media item 4", mediaImageItem4, mediaList.get(2));
+        assertEquals("Media item 5", mediaImageItem5, mediaList.get(3));
+        assertEquals("Media item 3", mediaVideoItem3, mediaList.get(4));
+
+        mVideoEditor.moveMediaItem(mediaVideoItem1.getId(),
+            mediaImageItem5.getId());
+        mediaList = mVideoEditor.getAllMediaItems();
+        assertEquals("Media Item List Size", 5, mediaList.size());
+        assertEquals("Media item 2", mediaVideoItem2, mediaList.get(0));
+        assertEquals("Media item 4", mediaImageItem4, mediaList.get(1));
+        assertEquals("Media item 5", mediaImageItem5, mediaList.get(2));
+        assertEquals("Media item 1", mediaVideoItem1, mediaList.get(3));
+        assertEquals("Media item 3", mediaVideoItem3, mediaList.get(4));
+
+        final TransitionCrossfade transition2And4CrossFade =
+            mVideoEditorHelper.createTCrossFade("transition2And4CrossFade",
+                mediaVideoItem2, mediaImageItem4, 2000,
+                Transition.BEHAVIOR_MIDDLE_FAST);
+        mVideoEditor.addTransition(transition2And4CrossFade);
+
+        final TransitionCrossfade transition1And3CrossFade =
+            mVideoEditorHelper.createTCrossFade("transition1And3CrossFade",
+                mediaVideoItem1, mediaVideoItem3, 5000,
+                Transition.BEHAVIOR_MIDDLE_FAST);
+        mVideoEditor.addTransition(transition1And3CrossFade);
+
+        final AudioTrack audioTrack =
+            mVideoEditorHelper.createAudio(mVideoEditor, "a1", audioFilename);
+        audioTrack.setExtractBoundaries(0, 2000);
+        mVideoEditor.addAudioTrack(audioTrack);
+
+        audioTrack.enableLoop();
+
+        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
+            public void onProgress(Object item, int action, int progress) {
+            }
+        });
+
+        final SurfaceHolder surfaceHolder =
+            MediaFrameworkTest.mSurfaceView.getHolder();
+
+        mVideoEditor.renderPreviewFrame(surfaceHolder, mVideoEditor.getDuration()/4, overlayData1);
+        Thread.sleep(1000);
+        mVideoEditor.renderPreviewFrame(surfaceHolder, mVideoEditor.getDuration()/2, overlayData1);
+        Thread.sleep(1000);
+        mVideoEditor.renderPreviewFrame(surfaceHolder, mVideoEditor.getDuration(), overlayData1);
+
+    }
+
+    /**
+     * To Test Preview : Without any Media Items in the story Board
+     */
+    // TODO : remove TC_PRV_013
+    @LargeTest
+    public void testStartPreviewWithoutMediaItems() throws Exception {
+        boolean flagForException = false;
+
+        final SurfaceHolder surfaceHolder =
+            MediaFrameworkTest.mSurfaceView.getHolder();
+        try{
+            mVideoEditor.startPreview(surfaceHolder, 0, -1, false, 1,
+                new PreviewProgressListener() {
+                    public void onProgress(VideoEditor videoEditor, long timeMs,
+                        OverlayData overlayData) {
+                    }
+                    public void onStart(VideoEditor videoEditor) {
+                        setPreviewStart();
+                    }
+                    public void onStop(VideoEditor videoEditor) {
+                        setPreviewStop();
+                }
+            });
+        }catch (IllegalArgumentException e) {
+            flagForException = true;
+        }
+        assertTrue("Preview without Media Items", flagForException);
+    }
+
+    /**
+     * To Test Preview : Add Media and Remove Media Item (Without any Media
+     * Items in the story Board)
+     */
+    // TODO : remove TC_PRV_014
+    @LargeTest
+    public void testStartPreviewAddRemoveMediaItems() throws Exception {
+        final String videoItemFilename1 = INPUT_FILE_PATH
+            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
+        final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
+        final String alphaFilename = INPUT_FILE_PATH +
+            "TransitionSpiral_QVGA.jpg";
+        boolean flagForException = false;
+
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
+                videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mediaVideoItem.setExtractBoundaries(0, 15000);
+        mVideoEditor.addMediaItem(mediaVideoItem);
+
+        final MediaImageItem mediaImageItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
+                imageItemFilename1, 15000, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaImageItem);
+
+        final TransitionAlpha transition1And2 =
+            mVideoEditorHelper.createTAlpha("transition", mediaVideoItem,
+                mediaImageItem, 3000, Transition.BEHAVIOR_SPEED_UP,
+                alphaFilename, 10, false);
+        mVideoEditor.addTransition(transition1And2);
+
+        final EffectColor effectColor =
+            mVideoEditorHelper.createEffectItem(mediaImageItem, "effect", 5000,
+                3000, EffectColor.TYPE_COLOR, EffectColor.PINK);
+        mediaImageItem.addEffect(effectColor);
+
+        assertEquals("removing Media item 1", mediaVideoItem,
+            mVideoEditor.removeMediaItem(mediaVideoItem.getId()));
+        assertEquals("removing Media item 2", mediaImageItem,
+            mVideoEditor.removeMediaItem(mediaImageItem.getId()));
+
+        try{
+            mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
+                public void onProgress(Object item, int action, int progress) {
+                }
+            });
+            final SurfaceHolder surfaceHolder =
+                MediaFrameworkTest.mSurfaceView.getHolder();
+            mVideoEditor.startPreview(surfaceHolder, 0, -1, false, 1,
+                new PreviewProgressListener() {
+                    public void onProgress(VideoEditor videoEditor, long timeMs,
+                        OverlayData overlayData) {
+                    }
+                    public void onStart(VideoEditor videoEditor) {
+                        setPreviewStart();
+                    }
+                    public void onStop(VideoEditor videoEditor) {
+                        setPreviewStop();
+                }
+            });
+        }catch (IllegalArgumentException e) {
+            flagForException = true;
+        }
+        assertTrue("Preview with removed Media Items", flagForException);
+
+    }
+
+    /**
+     * To test Preview : Preview of current Effects applied (with Render Preview
+     * Frame)
+     */
+    // TODO : remove TC_PRV_015
+    @LargeTest
+    public void testPreviewWithRenderPreviewFrameWithoutGenerate() throws Exception {
+        final String videoItemFileName = INPUT_FILE_PATH +
+            "H264_BP_640x480_30fps_256kbps_1_17.mp4";
+        boolean flagForException = false;
+        long duration = 0;
+        OverlayData overlayData1 = new OverlayData();
+
+        final MediaVideoItem mediaVideoItem =
+            mVideoEditorHelper.createMediaItem(mVideoEditor,
+            "m1", videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
+        mVideoEditor.addMediaItem(mediaVideoItem);
+
+        final SurfaceHolder surfaceHolder =
+            MediaFrameworkTest.mSurfaceView.getHolder();
+        duration = mVideoEditor.getDuration();
+        /* RenderPreviewFrame returns -1 to indicate last frame */
+        try {
+        assertEquals("Render preview Frame at item duration", -1,
+            mVideoEditor.renderPreviewFrame(surfaceHolder, duration,
+            overlayData1));
+        } catch ( Exception e) {
+            assertTrue (" Render Preview Frame without generate", false);
+        }
+        duration = mVideoEditor.getDuration() + 1000;
+        try {
+            mVideoEditor.renderPreviewFrame(surfaceHolder, duration,
+            overlayData1);
+        } catch ( IllegalStateException e) {
+            flagForException = true;
+        }
+        assertTrue (" Preview time greater than duration", flagForException);
+    }
+
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java
index b694d16..20e2936 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java
@@ -65,11 +65,11 @@
         output.write("File Name: " + filename);
         output.write(" Complete: " + CodecTest.onCompleteSuccess);
         output.write(" Error: " + CodecTest.mPlaybackError);
-        output.write(" Unknown Info: " + CodecTest.mIsMediaInfoUnknown);
-        output.write(" Track Lagging: " +  CodecTest.mIsMediaInfoVideoTrackLagging);
-        output.write(" BadInterleaving: " + CodecTest.mIsMediaInfoBadInterleaving);
-        output.write(" Not Seekable: " + CodecTest.mIsMediaInfoNotSeekable);
-        output.write(" Info Meta data update: " + CodecTest.mIsMediaInfoMetdataUpdate);
+        output.write(" Unknown Info: " + CodecTest.mMediaInfoUnknownCount);
+        output.write(" Track Lagging: " +  CodecTest.mMediaInfoVideoTrackLaggingCount);
+        output.write(" BadInterleaving: " + CodecTest.mMediaInfoBadInterleavingCount);
+        output.write(" Not Seekable: " + CodecTest.mMediaInfoNotSeekableCount);
+        output.write(" Info Meta data update: " + CodecTest.mMediaInfoMetdataUpdateCount);
         output.write("\n");
     }
 
@@ -92,21 +92,11 @@
         else if (CodecTest.mPlaybackError){
             mTotalPlaybackError++;
         }
-        else if (CodecTest.mIsMediaInfoUnknown){
-            mTotalInfoUnknown++;
-        }
-        else if (CodecTest.mIsMediaInfoVideoTrackLagging){
-            mTotalVideoTrackLagging++;
-        }
-        else if (CodecTest.mIsMediaInfoBadInterleaving){
-            mTotalBadInterleaving++;
-        }
-        else if (CodecTest.mIsMediaInfoNotSeekable){
-            mTotalNotSeekable++;
-        }
-        else if (CodecTest.mIsMediaInfoMetdataUpdate){
-            mTotalMetaDataUpdate++;
-        }
+        mTotalInfoUnknown += CodecTest.mMediaInfoUnknownCount;
+        mTotalVideoTrackLagging += CodecTest.mMediaInfoVideoTrackLaggingCount;
+        mTotalBadInterleaving += CodecTest.mMediaInfoBadInterleavingCount;
+        mTotalNotSeekable += CodecTest.mMediaInfoNotSeekableCount;
+        mTotalMetaDataUpdate += CodecTest.mMediaInfoMetdataUpdateCount;
     }
 
     //Test that will start the playback for all the videos
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 3dc8c03f..3d5a4d1 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -22,7 +22,7 @@
 
 #include <sys/ioctl.h>
 
-#if HAVE_ANDROID_OS
+#ifdef HAVE_ANDROID_OS
 #include <linux/android_pmem.h>
 #endif
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
index b1e74ad..ce0848b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
@@ -90,8 +90,8 @@
             if (imi2 == null) return 0;
             if (imi1 == null) return 1;
             if (mPackageManager != null) {
-                CharSequence imiId1 = imi1.loadLabel(mPackageManager);
-                CharSequence imiId2 = imi2.loadLabel(mPackageManager);
+                CharSequence imiId1 = imi1.loadLabel(mPackageManager) + "/" + imi1.getId();
+                CharSequence imiId2 = imi2.loadLabel(mPackageManager) + "/" + imi2.getId();
                 if (imiId1 != null && imiId2 != null) {
                     return imiId1.toString().compareTo(imiId2.toString());
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
index a072aed..a8f4262 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
@@ -158,7 +158,9 @@
     private void advance() {
         // Out with the old...
         if (mCurrentView != null) {
-            mWindow.removeView(mCurrentView);
+            if (mWindow != null) {
+                mWindow.removeView(mCurrentView);
+            }
             mCurrentView = null;
             mCurrentKey = null;
             mCurrentNotification = null;
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
index e775dac..5ed67a9 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
@@ -26,6 +26,7 @@
 import static android.os.BatteryManager.BATTERY_STATUS_FULL;
 import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
 import android.media.AudioManager;
+import android.os.BatteryManager;
 import android.os.Handler;
 import android.os.Message;
 import android.os.SystemClock;
@@ -70,12 +71,12 @@
 
     private boolean mKeyguardBypassEnabled;
 
-    private boolean mDevicePluggedIn;
-
     private boolean mDeviceProvisioned;
 
     private int mBatteryLevel;
 
+    private int mBatteryStatus;
+
     private CharSequence mTelephonyPlmn;
     private CharSequence mTelephonySpn;
 
@@ -203,7 +204,7 @@
 
         // take a guess to start
         mSimState = IccCard.State.READY;
-        mDevicePluggedIn = true;
+        mBatteryStatus = BATTERY_STATUS_FULL;
         mBatteryLevel = 100;
 
         mTelephonyPlmn = getDefaultPlmn();
@@ -283,13 +284,12 @@
     /**
      * Handle {@link #MSG_BATTERY_UPDATE}
      */
-    private void handleBatteryUpdate(int pluggedInStatus, int batteryLevel) {
+    private void handleBatteryUpdate(int batteryStatus, int batteryLevel) {
         if (DEBUG) Log.d(TAG, "handleBatteryUpdate");
-        final boolean pluggedIn = isPluggedIn(pluggedInStatus);
-
-        if (isBatteryUpdateInteresting(pluggedIn, batteryLevel)) {
+        if (isBatteryUpdateInteresting(batteryStatus, batteryLevel)) {
+            mBatteryStatus = batteryStatus;
             mBatteryLevel = batteryLevel;
-            mDevicePluggedIn = pluggedIn;
+            final boolean pluggedIn = isPluggedIn(batteryStatus);;
             for (int i = 0; i < mInfoCallbacks.size(); i++) {
                 mInfoCallbacks.get(i).onRefreshBatteryInfo(
                         shouldShowBatteryInfo(), pluggedIn, batteryLevel);
@@ -336,26 +336,34 @@
         return status == BATTERY_STATUS_CHARGING || status == BATTERY_STATUS_FULL;
     }
 
-    private boolean isBatteryUpdateInteresting(boolean pluggedIn, int batteryLevel) {
+    private boolean isBatteryUpdateInteresting(int batteryStatus, int batteryLevel) {
         // change in plug is always interesting
-        if (mDevicePluggedIn != pluggedIn) {
+        final boolean isPluggedIn = isPluggedIn(batteryStatus);
+        final boolean wasPluggedIn = isPluggedIn(mBatteryStatus);
+        final boolean stateChangedWhilePluggedIn =
+            wasPluggedIn == true && isPluggedIn == true && (mBatteryStatus != batteryStatus);
+        if (wasPluggedIn != isPluggedIn || stateChangedWhilePluggedIn) {
             return true;
         }
 
         // change in battery level while plugged in
-        if (pluggedIn && mBatteryLevel != batteryLevel) {
+        if (isPluggedIn && mBatteryLevel != batteryLevel) {
             return true;
         }
 
-        if (!pluggedIn) {
+        if (!isPluggedIn) {
             // not plugged in and below threshold
-            if (batteryLevel < LOW_BATTERY_THRESHOLD && batteryLevel != mBatteryLevel) {
+            if (isBatteryLow(batteryLevel) && batteryLevel != mBatteryLevel) {
                 return true;
             }
         }
         return false;
     }
 
+    private boolean isBatteryLow(int batteryLevel) {
+        return batteryLevel < LOW_BATTERY_THRESHOLD;
+    }
+
     /**
      * @param intent The intent with action {@link Telephony.Intents#SPN_STRINGS_UPDATED_ACTION}
      * @return The string to use for the plmn, or null if it should not be shown.
@@ -485,7 +493,12 @@
     }
 
     public boolean isDevicePluggedIn() {
-        return mDevicePluggedIn;
+        return isPluggedIn(mBatteryStatus);
+    }
+
+    public boolean isDeviceCharged() {
+        return mBatteryStatus == BatteryManager.BATTERY_STATUS_FULL
+                || mBatteryLevel >= 100; // in case a particular device doesn't flag it
     }
 
     public int getBatteryLevel() {
@@ -493,7 +506,7 @@
     }
 
     public boolean shouldShowBatteryInfo() {
-        return mDevicePluggedIn || mBatteryLevel < LOW_BATTERY_THRESHOLD;
+        return isPluggedIn(mBatteryStatus) || isBatteryLow(mBatteryLevel);
     }
 
     public CharSequence getTelephonyPlmn() {
diff --git a/policy/src/com/android/internal/policy/impl/StatusView.java b/policy/src/com/android/internal/policy/impl/StatusView.java
index da7bbb8..2aff4a8 100644
--- a/policy/src/com/android/internal/policy/impl/StatusView.java
+++ b/policy/src/com/android/internal/policy/impl/StatusView.java
@@ -51,6 +51,7 @@
     private LockPatternUtils mLockPatternUtils;
     private int mHelpMessageId;
     private int mHelpIconId;
+    private KeyguardUpdateMonitor mUpdateMonitor;
 
     private View findViewById(int id) {
         return mView.findViewById(id);
@@ -97,6 +98,7 @@
         mHasDate = (mDate != null);
         mDateFormatString = getContext().getString(R.string.full_wday_month_day_no_year);
         mLockPatternUtils = lockPatternUtils;
+        mUpdateMonitor = updateMonitor;
 
         refreshTimeAndDateDisplay();
 
@@ -186,7 +188,7 @@
             // Battery status
             if (mPluggedIn) {
                 // Charging or charged
-                if (mBatteryLevel >= 100) {
+                if (mUpdateMonitor.isDeviceCharged()) {
                     mStatus1.setText(getContext().getString(R.string.lockscreen_charged));
                 } else {
                     mStatus1.setText(getContext().getString(R.string.lockscreen_plugged_in,
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index b2d534b..df2cd1b 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -79,9 +79,9 @@
  * Implementation of the device policy APIs.
  */
 public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
-    private static final int REQUEST_EXPIRE_PASSWORD = 5571;
+    private static final String TAG = "DevicePolicyManagerService";
 
-    static final String TAG = "DevicePolicyManagerService";
+    private static final int REQUEST_EXPIRE_PASSWORD = 5571;
 
     private static final long EXPIRATION_GRACE_PERIOD_MS = 5 * 86400 * 1000; // 5 days, in ms
 
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index d25b9c8..51e9b00 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -1949,14 +1949,7 @@
 
     private boolean canAddToLastInputMethod(InputMethodSubtype subtype) {
         if (subtype == null) return true;
-        String[] extraValues = subtype.getExtraValue().split(",");
-        final int N = extraValues.length;
-        for (int i = 0; i < N; ++i) {
-            if (SUBTYPE_EXTRAVALUE_EXCLUDE_FROM_LAST_IME.equals(extraValues[i])) {
-                return false;
-            }
-        }
-        return true;
+        return !subtype.containsExtraValueKey(SUBTYPE_EXTRAVALUE_EXCLUDE_FROM_LAST_IME);
     }
 
     private void saveCurrentInputMethodAndSubtypeToHistory() {
diff --git a/services/java/com/android/server/UsbService.java b/services/java/com/android/server/UsbService.java
index 460fd4d..af4c425 100644
--- a/services/java/com/android/server/UsbService.java
+++ b/services/java/com/android/server/UsbService.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.hardware.IUsbManager;
+import android.hardware.UsbAccessory;
 import android.hardware.UsbConstants;
 import android.hardware.UsbDevice;
 import android.hardware.UsbEndpoint;
@@ -78,18 +79,63 @@
     private int mLastConfiguration = -1;
 
     // lists of enabled and disabled USB functions (for USB device mode)
+    // synchronize on mEnabledFunctions when using either of these lists
     private final ArrayList<String> mEnabledFunctions = new ArrayList<String>();
     private final ArrayList<String> mDisabledFunctions = new ArrayList<String>();
 
+    // contains all connected USB devices (for USB host mode)
     private final HashMap<String,UsbDevice> mDevices = new HashMap<String,UsbDevice>();
 
     // USB busses to exclude from USB host support
     private final String[] mHostBlacklist;
 
     private boolean mSystemReady;
+    private UsbAccessory mCurrentAccessory;
 
     private final Context mContext;
 
+    private final void functionEnabled(String function, boolean enabled) {
+        synchronized (mEnabledFunctions) {
+            if (enabled) {
+                if (!mEnabledFunctions.contains(function)) {
+                    mEnabledFunctions.add(function);
+                }
+                mDisabledFunctions.remove(function);
+            } else {
+                if (!mDisabledFunctions.contains(function)) {
+                    mDisabledFunctions.add(function);
+                }
+                mEnabledFunctions.remove(function);
+            }
+        }
+
+        if (enabled && UsbManager.USB_FUNCTION_ACCESSORY.equals(function)) {
+            String[] strings = nativeGetAccessoryStrings();
+            if (strings != null) {
+                Log.d(TAG, "entering USB accessory mode");
+                mCurrentAccessory = new UsbAccessory(strings);
+                Intent intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
+                intent.putExtra(UsbManager.EXTRA_ACCESSORY, mCurrentAccessory);
+                // add strings as separate extras to allow filtering
+                if (strings[0] != null) {
+                    intent.putExtra(UsbManager.EXTRA_ACCESSORY_MANUFACTURER, strings[0]);
+                }
+                if (strings[1] != null) {
+                    intent.putExtra(UsbManager.EXTRA_ACCESSORY_PRODUCT, strings[1]);
+                }
+                if (strings[2] != null) {
+                    intent.putExtra(UsbManager.EXTRA_ACCESSORY_TYPE, strings[2]);
+                }
+                if (strings[3] != null) {
+                    intent.putExtra(UsbManager.EXTRA_ACCESSORY_VERSION, strings[3]);
+                }
+                mContext.sendBroadcast(intent);
+            } else {
+                Log.e(TAG, "nativeGetAccessoryStrings failed");
+            }
+        }
+    }
+
     private final UEventObserver mUEventObserver = new UEventObserver() {
         @Override
         public void onUEvent(UEventObserver.UEvent event) {
@@ -127,17 +173,7 @@
                         // Note: we do not broadcast a change when a function is enabled or disabled.
                         // We just record the state change for the next broadcast.
                         boolean enabled = "1".equals(enabledStr);
-                        if (enabled) {
-                            if (!mEnabledFunctions.contains(function)) {
-                                mEnabledFunctions.add(function);
-                            }
-                            mDisabledFunctions.remove(function);
-                        } else {
-                            if (!mDisabledFunctions.contains(function)) {
-                                mDisabledFunctions.add(function);
-                            }
-                            mEnabledFunctions.remove(function);
-                        }
+                        functionEnabled(function, enabled);
                     }
                 }
             }
@@ -182,18 +218,20 @@
             return;
 
         try {
-            File[] files = new File(USB_COMPOSITE_CLASS_PATH).listFiles();
-            for (int i = 0; i < files.length; i++) {
-                File file = new File(files[i], "enable");
-                FileReader reader = new FileReader(file);
-                int len = reader.read(buffer, 0, 1024);
-                reader.close();
-                int value = Integer.valueOf((new String(buffer, 0, len)).trim());
-                String functionName = files[i].getName();
-                if (value == 1) {
-                    mEnabledFunctions.add(functionName);
-                } else {
-                    mDisabledFunctions.add(functionName);
+            synchronized (mEnabledFunctions) {
+                File[] files = new File(USB_COMPOSITE_CLASS_PATH).listFiles();
+                for (int i = 0; i < files.length; i++) {
+                    File file = new File(files[i], "enable");
+                    FileReader reader = new FileReader(file);
+                    int len = reader.read(buffer, 0, 1024);
+                    reader.close();
+                    int value = Integer.valueOf((new String(buffer, 0, len)).trim());
+                    String functionName = files[i].getName();
+                    if (value == 1) {
+                        mEnabledFunctions.add(functionName);
+                    } else {
+                        mDisabledFunctions.add(functionName);
+                    }
                 }
             }
         } catch (FileNotFoundException e) {
@@ -359,19 +397,32 @@
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_USB, null);
         if (mDevices.get(deviceName) == null) {
             // if it is not in mDevices, it either does not exist or is blacklisted
-            throw new IllegalArgumentException("device " + deviceName + " does not exist or is restricted");
+            throw new IllegalArgumentException(
+                    "device " + deviceName + " does not exist or is restricted");
         }
         return nativeOpenDevice(deviceName);
     }
 
+    public UsbAccessory getCurrentAccessory() {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_USB, null);
+        return mCurrentAccessory;
+    }
+
+    public ParcelFileDescriptor openAccessory() {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_USB, null);
+        return nativeOpenAccessory();
+    }
+
     private final Handler mHandler = new Handler() {
         private void addEnabledFunctions(Intent intent) {
+            synchronized (mEnabledFunctions) {
             // include state of all USB functions in our extras
-            for (int i = 0; i < mEnabledFunctions.size(); i++) {
-                intent.putExtra(mEnabledFunctions.get(i), UsbManager.USB_FUNCTION_ENABLED);
-            }
-            for (int i = 0; i < mDisabledFunctions.size(); i++) {
-                intent.putExtra(mDisabledFunctions.get(i), UsbManager.USB_FUNCTION_DISABLED);
+                for (int i = 0; i < mEnabledFunctions.size(); i++) {
+                    intent.putExtra(mEnabledFunctions.get(i), UsbManager.USB_FUNCTION_ENABLED);
+                }
+                for (int i = 0; i < mDisabledFunctions.size(); i++) {
+                    intent.putExtra(mDisabledFunctions.get(i), UsbManager.USB_FUNCTION_DISABLED);
+                }
             }
         }
 
@@ -381,6 +432,26 @@
                 case MSG_UPDATE:
                     synchronized (this) {
                         if (mConnected != mLastConnected || mConfiguration != mLastConfiguration) {
+                            if (mConnected == 0 && mCurrentAccessory != null) {
+                                // turn off accessory mode when we are disconnected
+                                if (UsbManager.setFunctionEnabled(
+                                        UsbManager.USB_FUNCTION_ACCESSORY, false)) {
+                                    Log.d(TAG, "exited USB accessory mode");
+
+                                    Intent intent = new Intent(
+                                            UsbManager.ACTION_USB_ACCESSORY_DETACHED);
+                                    intent.putExtra(UsbManager.EXTRA_ACCESSORY, mCurrentAccessory);
+                                    mContext.sendBroadcast(intent);
+                                    mCurrentAccessory = null;
+
+                                    // this will cause an immediate reset of the USB bus,
+                                    // so there is no point in sending the
+                                    // function disabled broadcast.
+                                    return;
+                                } else {
+                                    Log.e(TAG, "could not disable USB_FUNCTION_ACCESSORY");
+                                }
+                            }
 
                             final ContentResolver cr = mContext.getContentResolver();
                             if (Settings.Secure.getInt(cr,
@@ -408,4 +479,6 @@
 
     private native void monitorUsbHostBus();
     private native ParcelFileDescriptor nativeOpenDevice(String deviceName);
+    private native String[] nativeGetAccessoryStrings();
+    private native ParcelFileDescriptor nativeOpenAccessory();
 }
diff --git a/services/java/com/android/server/WifiWatchdogService.java b/services/java/com/android/server/WifiWatchdogService.java
index 46d6bef..94531bb 100644
--- a/services/java/com/android/server/WifiWatchdogService.java
+++ b/services/java/com/android/server/WifiWatchdogService.java
@@ -22,8 +22,9 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.database.ContentObserver;
+import android.net.ConnectivityManager;
+import android.net.LinkProperties;
 import android.net.NetworkInfo;
-import android.net.DhcpInfo;
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
@@ -42,6 +43,7 @@
 import java.net.SocketException;
 import java.net.SocketTimeoutException;
 import java.net.UnknownHostException;
+import java.util.Collection;
 import java.util.List;
 import java.util.Random;
 
@@ -77,7 +79,8 @@
     private Context mContext;
     private ContentResolver mContentResolver;
     private WifiManager mWifiManager;
-    
+    private ConnectivityManager mConnectivityManager;
+
     /**
      * The main watchdog thread.
      */
@@ -310,19 +313,26 @@
     }
     
     /**
-     * Gets the DNS of the current AP.
+     * Gets the first DNS of the current AP.
      * 
-     * @return The DNS of the current AP.
+     * @return The first DNS of the current AP.
      */
-    private int getDns() {
-        DhcpInfo addressInfo = mWifiManager.getDhcpInfo();
-        if (addressInfo != null) {
-            return addressInfo.dns1;
-        } else {
-            return -1;
+    private InetAddress getDns() {
+        if (mConnectivityManager == null) {
+            mConnectivityManager = (ConnectivityManager)mContext.getSystemService(
+                    Context.CONNECTIVITY_SERVICE);
         }
+
+        LinkProperties linkProperties = mConnectivityManager.getLinkProperties(
+                ConnectivityManager.TYPE_WIFI);
+        if (linkProperties == null) return null;
+
+        Collection<InetAddress> dnses = linkProperties.getDnses();
+        if (dnses == null || dnses.size() == 0) return null;
+
+        return dnses.iterator().next();
     }
-    
+
     /**
      * Checks whether the DNS can be reached using multiple attempts according
      * to the current setting values.
@@ -330,29 +340,28 @@
      * @return Whether the DNS is reachable
      */
     private boolean checkDnsConnectivity() {
-        int dns = getDns();
-        if (dns == -1) {
+        InetAddress dns = getDns();
+        if (dns == null) {
             if (V) {
                 myLogV("checkDnsConnectivity: Invalid DNS, returning false");
             }
             return false;
         }
-        
+
         if (V) {
-            myLogV("checkDnsConnectivity: Checking 0x" +
-                    Integer.toHexString(Integer.reverseBytes(dns)) + " for connectivity");
+            myLogV("checkDnsConnectivity: Checking " + dns.getHostAddress() + " for connectivity");
         }
 
         int numInitialIgnoredPings = getInitialIgnoredPingCount();
         int numPings = getPingCount();
         int pingDelay = getPingDelayMs();
         int acceptableLoss = getAcceptablePacketLossPercentage();
-        
+
         /** See {@link Secure#WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT} */
         int ignoredPingCounter = 0;
         int pingCounter = 0;
         int successCounter = 0;
-        
+
         // No connectivity check needed
         if (numPings == 0) {
             return true;
@@ -371,20 +380,20 @@
                 pingCounter++;
                 successCounter++;
             }
-            
+
             if (V) {
                 Slog.v(TAG, (dnsAlive ? "  +" : "  Ignored: -"));
             }
 
             if (shouldCancel()) return false;
-            
+
             try {
                 Thread.sleep(pingDelay);
             } catch (InterruptedException e) {
                 Slog.w(TAG, "Interrupted while pausing between pings", e);
             }
         }
-        
+
         // Do the pings that we use to measure packet loss
         for (; pingCounter < numPings; pingCounter++) {
             if (shouldCancel()) return false;
@@ -401,40 +410,41 @@
             }
 
             if (shouldCancel()) return false;
-            
+
             try {
                 Thread.sleep(pingDelay);
             } catch (InterruptedException e) {
                 Slog.w(TAG, "Interrupted while pausing between pings", e);
             }
         }
-        
+
         int packetLossPercentage = 100 * (numPings - successCounter) / numPings;
         if (D) {
             Slog.d(TAG, packetLossPercentage
                     + "% packet loss (acceptable is " + acceptableLoss + "%)");
         }
-        
+
         return !shouldCancel() && (packetLossPercentage <= acceptableLoss);
     }
 
     private boolean backgroundCheckDnsConnectivity() {
-        int dns = getDns();
-        if (false && V) {
-            myLogV("backgroundCheckDnsConnectivity: Background checking " + dns +
-                    " for connectivity");
-        }
-        
-        if (dns == -1) {
+        InetAddress dns = getDns();
+
+        if (dns == null) {
             if (V) {
                 myLogV("backgroundCheckDnsConnectivity: DNS is empty, returning false");
             }
             return false;
         }
-        
+
+        if (false && V) {
+            myLogV("backgroundCheckDnsConnectivity: Background checking " +
+                    dns.getHostAddress() + " for connectivity");
+        }
+
         return DnsPinger.isDnsReachable(dns, getBackgroundCheckTimeoutMs());
     }
-    
+
     /**
      * Signals the current action to cancel.
      */
@@ -1207,43 +1217,37 @@
         
         /** Used to generate IDs */
         private static Random sRandom = new Random();
-        
-        static boolean isDnsReachable(int dns, int timeout) {
+
+        static boolean isDnsReachable(InetAddress dnsAddress, int timeout) {
             DatagramSocket socket = null;
             try {
                 socket = new DatagramSocket();
-                
+
                 // Set some socket properties
                 socket.setSoTimeout(timeout);
-                
+
                 byte[] buf = new byte[DNS_QUERY_BASE_SIZE];
                 fillQuery(buf);
-                
-                // Send the DNS query
-                byte parts[] = new byte[4];
-                parts[0] = (byte)(dns & 0xff);
-                parts[1] = (byte)((dns >> 8) & 0xff);
-                parts[2] = (byte)((dns >> 16) & 0xff);
-                parts[3] = (byte)((dns >> 24) & 0xff);
 
-                InetAddress dnsAddress = InetAddress.getByAddress(parts);
+                // Send the DNS query
+
                 DatagramPacket packet = new DatagramPacket(buf,
                         buf.length, dnsAddress, DNS_PORT);
                 socket.send(packet);
-                
+
                 // Wait for reply (blocks for the above timeout)
                 DatagramPacket replyPacket = new DatagramPacket(buf, buf.length);
                 socket.receive(replyPacket);
 
                 // If a timeout occurred, an exception would have been thrown.  We got a reply!
                 return true;
-                
+
             } catch (SocketException e) {
                 if (V) {
                     Slog.v(TAG, "DnsPinger.isReachable received SocketException", e);
                 }
                 return false;
-                
+
             } catch (UnknownHostException e) {
                 if (V) {
                     Slog.v(TAG, "DnsPinger.isReachable is unable to resolve the DNS host", e);
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index b7a276f..b662c55 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -5889,7 +5889,7 @@
                         outSurface.copyFrom(surface);
                         final IBinder winBinder = window.asBinder();
                         token = new Binder();
-                        mDragState = new DragState(token, surface, flags, winBinder);
+                        mDragState = new DragState(token, surface, /*flags*/ 0, winBinder);
                         mDragState.mSurface = surface;
                         token = mDragState.mToken = new Binder();
 
diff --git a/services/jni/com_android_server_AlarmManagerService.cpp b/services/jni/com_android_server_AlarmManagerService.cpp
index 0e162bd..aa8c9b3 100644
--- a/services/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/jni/com_android_server_AlarmManagerService.cpp
@@ -33,7 +33,7 @@
 #include <errno.h>
 #include <unistd.h>
 
-#if HAVE_ANDROID_OS
+#ifdef HAVE_ANDROID_OS
 #include <linux/ioctl.h>
 #include <linux/android_alarm.h>
 #endif
@@ -42,7 +42,7 @@
 
 static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv* env, jobject obj, jint fd, jint minswest)
 {
-#if HAVE_ANDROID_OS
+#ifdef HAVE_ANDROID_OS
     struct timezone tz;
 
     tz.tz_minuteswest = minswest;
@@ -64,7 +64,7 @@
 
 static jint android_server_AlarmManagerService_init(JNIEnv* env, jobject obj)
 {
-#if HAVE_ANDROID_OS
+#ifdef HAVE_ANDROID_OS
     return open("/dev/alarm", O_RDWR);
 #else
 	return -1;
@@ -73,14 +73,14 @@
 
 static void android_server_AlarmManagerService_close(JNIEnv* env, jobject obj, jint fd)
 {
-#if HAVE_ANDROID_OS
+#ifdef HAVE_ANDROID_OS
 	close(fd);
 #endif
 }
 
 static void android_server_AlarmManagerService_set(JNIEnv* env, jobject obj, jint fd, jint type, jlong seconds, jlong nanoseconds)
 {
-#if HAVE_ANDROID_OS
+#ifdef HAVE_ANDROID_OS
     struct timespec ts;
     ts.tv_sec = seconds;
     ts.tv_nsec = nanoseconds;
@@ -95,7 +95,7 @@
 
 static jint android_server_AlarmManagerService_waitForAlarm(JNIEnv* env, jobject obj, jint fd)
 {
-#if HAVE_ANDROID_OS
+#ifdef HAVE_ANDROID_OS
 	int result = 0;
 	
 	do
diff --git a/services/jni/com_android_server_BatteryService.cpp b/services/jni/com_android_server_BatteryService.cpp
index d4513e9..98d0d92 100644
--- a/services/jni/com_android_server_BatteryService.cpp
+++ b/services/jni/com_android_server_BatteryService.cpp
@@ -33,7 +33,7 @@
 #include <unistd.h>
 #include <dirent.h>
 
-#if HAVE_ANDROID_OS
+#ifdef HAVE_ANDROID_OS
 #include <linux/ioctl.h>
 #endif
 
diff --git a/services/jni/com_android_server_UsbService.cpp b/services/jni/com_android_server_UsbService.cpp
index ef22111..192daaf 100644
--- a/services/jni/com_android_server_UsbService.cpp
+++ b/services/jni/com_android_server_UsbService.cpp
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -26,6 +26,13 @@
 
 #include <stdio.h>
 #include <asm/byteorder.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/usb/f_accessory.h>
+
+#define DRIVER_NAME "/dev/usb_accessory"
 
 namespace android
 {
@@ -164,10 +171,67 @@
         gParcelFileDescriptorOffsets.mConstructor, fileDescriptor);
 }
 
+static void set_accessory_string(JNIEnv *env, int fd, int cmd, jobjectArray strArray, int index)
+{
+    char buffer[256];
+
+    buffer[0] = 0;
+    int length = ioctl(fd, cmd, buffer);
+    LOGD("ioctl returned %d", length);
+    if (buffer[0]) {
+        jstring obj = env->NewStringUTF(buffer);
+        env->SetObjectArrayElement(strArray, index, obj);
+        env->DeleteLocalRef(obj);
+    }
+}
+
+
+static jobjectArray android_server_UsbService_getAccessoryStrings(JNIEnv *env, jobject thiz)
+{
+    int fd = open(DRIVER_NAME, O_RDWR);
+    if (fd < 0) {
+        LOGE("could not open %s", DRIVER_NAME);
+        return NULL;
+    }
+    jclass stringClass = env->FindClass("java/lang/String");
+    jobjectArray strArray = env->NewObjectArray(4, stringClass, NULL);
+    if (!strArray) goto out;
+    set_accessory_string(env, fd, ACCESSORY_GET_STRING_MANUFACTURER, strArray, 0);
+    set_accessory_string(env, fd, ACCESSORY_GET_STRING_MODEL, strArray, 1);
+    set_accessory_string(env, fd, ACCESSORY_GET_STRING_TYPE, strArray, 2);
+    set_accessory_string(env, fd, ACCESSORY_GET_STRING_VERSION, strArray, 3);
+
+out:
+    close(fd);
+    return strArray;
+}
+
+static jobject android_server_UsbService_openAccessory(JNIEnv *env, jobject thiz)
+{
+    int fd = open(DRIVER_NAME, O_RDWR);
+    if (fd < 0) {
+        LOGE("could not open %s", DRIVER_NAME);
+        return NULL;
+    }
+    jobject fileDescriptor = env->NewObject(gFileDescriptorOffsets.mClass,
+        gFileDescriptorOffsets.mConstructor);
+    if (fileDescriptor != NULL) {
+        env->SetIntField(fileDescriptor, gFileDescriptorOffsets.mDescriptor, fd);
+    } else {
+        return NULL;
+    }
+    return env->NewObject(gParcelFileDescriptorOffsets.mClass,
+        gParcelFileDescriptorOffsets.mConstructor, fileDescriptor);
+}
+
 static JNINativeMethod method_table[] = {
     { "monitorUsbHostBus", "()V", (void*)android_server_UsbService_monitorUsbHostBus },
     { "nativeOpenDevice",  "(Ljava/lang/String;)Landroid/os/ParcelFileDescriptor;",
                                   (void*)android_server_UsbService_openDevice },
+    { "nativeGetAccessoryStrings", "()[Ljava/lang/String;",
+                                  (void*)android_server_UsbService_getAccessoryStrings },
+    { "nativeOpenAccessory","()Landroid/os/ParcelFileDescriptor;",
+                                  (void*)android_server_UsbService_openAccessory },
 };
 
 int register_android_server_UsbService(JNIEnv *env)
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index fde8e67..0f7d639 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -142,7 +142,8 @@
 
 sp<LayerBaseClient::Surface> Layer::createSurface() const
 {
-    return mSurface;
+    sp<Surface> sur(new SurfaceLayer(mFlinger, const_cast<Layer *>(this)));
+    return sur;
 }
 
 status_t Layer::ditch()
@@ -152,9 +153,6 @@
     // the layer is not on screen anymore. free as much resources as possible
     mFreezeLock.clear();
 
-    // Free our own reference to ISurface
-    mSurface.clear();
-
     Mutex::Autolock _l(mLock);
     mWidth = mHeight = 0;
     return NO_ERROR;
@@ -202,7 +200,6 @@
     int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED);
     mNeedsDithering = layerRedsize > displayRedSize;
 
-    mSurface = new SurfaceLayer(mFlinger, this);
     return NO_ERROR;
 }
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index d9a8be3..2b38414 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -213,7 +213,6 @@
     ClientRef mUserClientRef;
 
     // constants
-    sp<Surface> mSurface;
     PixelFormat mFormat;
     const GLExtensions& mGLExtensions;
     bool mNeedsBlending;
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 86057f8..6025ed4 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -540,7 +540,9 @@
 
 LayerBaseClient::LayerBaseClient(SurfaceFlinger* flinger, DisplayID display,
         const sp<Client>& client)
-    : LayerBase(flinger, display), mClientRef(client),
+    : LayerBase(flinger, display),
+      mHasSurface(false),
+      mClientRef(client),
       mIdentity(uint32_t(android_atomic_inc(&sIdentity)))
 {
 }
@@ -557,12 +559,13 @@
 {
     sp<Surface> s;
     Mutex::Autolock _l(mLock);
-    s = mClientSurface.promote();
-    if (s == 0) {
-        s = createSurface();
-        mClientSurface = s;
-        mClientSurfaceBinder = s->asBinder();
-    }
+
+    LOG_ALWAYS_FATAL_IF(mHasSurface,
+            "LayerBaseClient::getSurface() has already been called");
+
+    mHasSurface = true;
+    s = createSurface();
+    mClientSurfaceBinder = s->asBinder();
     return s;
 }
 
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index 184edd7..bfe92e6 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -337,7 +337,7 @@
 
 private:
     mutable Mutex mLock;
-    mutable wp<Surface> mClientSurface;
+    mutable bool mHasSurface;
     wp<IBinder> mClientSurfaceBinder;
     const wp<Client> mClientRef;
     // only read
diff --git a/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java b/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java
index 41f3b23..a9efc98 100755
--- a/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java
+++ b/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java
@@ -305,8 +305,15 @@
         fileIds = mPbrFile.mFileIds.get(recNum);
         if (fileIds == null || fileIds.isEmpty()) return;
 
+
+        int extEf = 0;
+        // Only call fileIds.get while EFEXT1_TAG is available
+        if (fileIds.containsKey(USIM_EFEXT1_TAG)) {
+            extEf = fileIds.get(USIM_EFEXT1_TAG);
+        }
+
         mAdnCache.requestLoadAllAdnLike(fileIds.get(USIM_EFADN_TAG),
-            fileIds.get(USIM_EFEXT1_TAG), obtainMessage(EVENT_USIM_ADN_LOAD_DONE));
+            extEf, obtainMessage(EVENT_USIM_ADN_LOAD_DONE));
         try {
             mLock.wait();
         } catch (InterruptedException e) {
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index d05918f..4ac03a8 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -356,16 +356,6 @@
     public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
 
     /**
-     * In this Wi-Fi lock mode, Wi-Fi will behave as in the mode
-     * {@link #WIFI_MODE_FULL} but it operates at high performance
-     * at the expense of power. This mode should be used
-     * only when the wifi connection needs to have minimum loss and low
-     * latency as it can impact the battery life.
-     * @hide
-     */
-    public static final int WIFI_MODE_FULL_HIGH_PERF = 3;
-
-    /**
      * In this Wi-Fi lock mode, Wi-Fi will be kept active,
      * and will behave normally, i.e., it will attempt to automatically
      * establish a connection to a remembered access point that is
@@ -383,10 +373,29 @@
      * an application in this mode.
      */
     public static final int WIFI_MODE_SCAN_ONLY = 2;
+    /**
+     * In this Wi-Fi lock mode, Wi-Fi will be kept active as in mode
+     * {@link #WIFI_MODE_FULL} but it operates at high performance
+     * with minimum packet loss and low packet latency even when
+     * the device screen is off. This mode will consume more power
+     * and hence should be used only when there is a need for such
+     * an active connection.
+     * <p>
+     * An example use case is when a voice connection needs to be
+     * kept active even after the device screen goes off. Holding the
+     * regular {@link #WIFI_MODE_FULL} lock will keep the wifi
+     * connection active, but the connection can be lossy.
+     * Holding a {@link #WIFI_MODE_FULL_HIGH_PERF} lock for the
+     * duration of the voice call will improve the call quality.
+     * <p>
+     * When there is no support from the hardware, this lock mode
+     * will have the same behavior as {@link #WIFI_MODE_FULL}
+     */
+    public static final int WIFI_MODE_FULL_HIGH_PERF = 3;
 
     /** Anything worse than or equal to this will show 0 bars. */
     private static final int MIN_RSSI = -100;
-    
+
     /** Anything better than or equal to this will show the max bars. */
     private static final int MAX_RSSI = -55;
 
@@ -1288,9 +1297,10 @@
      * Creates a new WifiLock.
      *
      * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL},
-     * and {@link #WIFI_MODE_SCAN_ONLY} for descriptions of the types of Wi-Fi locks.
-     * @param tag a tag for the WifiLock to identify it in debugging messages.  This string is 
-     *            never shown to the user under normal conditions, but should be descriptive 
+     * {@link #WIFI_MODE_FULL_HIGH_PERF} and {@link #WIFI_MODE_SCAN_ONLY} for
+     * descriptions of the types of Wi-Fi locks.
+     * @param tag a tag for the WifiLock to identify it in debugging messages.  This string is
+     *            never shown to the user under normal conditions, but should be descriptive
      *            enough to identify your application and the specific WifiLock within it, if it
      *            holds multiple WifiLocks.
      *
@@ -1301,7 +1311,7 @@
     public WifiLock createWifiLock(int lockType, String tag) {
         return new WifiLock(lockType, tag);
     }
-    
+
     /**
      * Creates a new WifiLock.
      *
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 030048f..d920108 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -163,10 +163,6 @@
 
     public native static String startWpsWithPinFromDeviceCommand(String bssid);
 
-    public native static boolean doDhcpRequest(DhcpInfo results);
-
-    public native static String getDhcpError();
-
     public native static boolean setSuspendOptimizationsCommand(boolean enabled);
 
     public native static boolean setCountryCodeCommand(String countryCode);