Merge "Support more MPEG4-LATM audio functionality."
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index e3d8e20..1e8743c 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -117,6 +117,40 @@
     }
 
     /**
+     * isKeyguardLocked
+     *
+     * Return whether the keyguard is currently locked.
+     *
+     * @return true if in keyguard is locked.
+     *
+     * @hide
+     */
+    public boolean isKeyguardLocked() {
+        try {
+            return mWM.isKeyguardSecure();
+        } catch (RemoteException ex) {
+            return false;
+        }
+    }
+
+    /**
+     * isKeyguardSecure
+     *
+     * Return whether the keyguard requires a password to unlock.
+     *
+     * @return true if in keyguard is secure.
+     *
+     * @hide
+     */
+    public boolean isKeyguardSecure() {
+        try {
+            return mWM.isKeyguardSecure();
+        } catch (RemoteException ex) {
+            return false;
+        }
+    }
+
+    /**
      * If keyguard screen is showing or in restricted key input mode (i.e. in
      * keyguard password emergency screen). When in such mode, certain keys,
      * such as the Home key and the right soft keys, don't work.
diff --git a/core/java/android/app/ListActivity.java b/core/java/android/app/ListActivity.java
index d49968f..2162521 100644
--- a/core/java/android/app/ListActivity.java
+++ b/core/java/android/app/ListActivity.java
@@ -43,7 +43,7 @@
  * <p>
  * Optionally, your custom view can contain another view object of any type to
  * display when the list view is empty. This "empty list" notifier must have an
- * id "android:empty". Note that when an empty view is present, the list view
+ * id "android:id/empty". Note that when an empty view is present, the list view
  * will be hidden when there is no data to display.
  * <p>
  * The following code demonstrates an (ugly) custom screen layout. It has a list
@@ -59,14 +59,14 @@
  *         android:paddingLeft=&quot;8dp&quot;
  *         android:paddingRight=&quot;8dp&quot;&gt;
  *
- *     &lt;ListView android:id=&quot;@id/android:list&quot;
+ *     &lt;ListView android:id=&quot;@android:id/list&quot;
  *               android:layout_width=&quot;match_parent&quot;
  *               android:layout_height=&quot;match_parent&quot;
  *               android:background=&quot;#00FF00&quot;
  *               android:layout_weight=&quot;1&quot;
  *               android:drawSelectorOnTop=&quot;false&quot;/&gt;
  *
- *     &lt;TextView android:id=&quot;@id/android:empty&quot;
+ *     &lt;TextView android:id=&quot;@android:id/empty&quot;
  *               android:layout_width=&quot;match_parent&quot;
  *               android:layout_height=&quot;match_parent&quot;
  *               android:background=&quot;#FF0000&quot;
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 4656e15..1f4fe80 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1049,6 +1049,9 @@
         } else if (profile == BluetoothProfile.A2DP) {
             BluetoothA2dp a2dp = new BluetoothA2dp(context, listener);
             return true;
+        } else if (profile == BluetoothProfile.INPUT_DEVICE) {
+            BluetoothInputDevice iDev = new BluetoothInputDevice(context, listener);
+            return true;
         } else {
             return false;
         }
diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
index 6ec347f..116a068 100644
--- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java
+++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
@@ -136,17 +136,17 @@
                     newState == BluetoothProfile.STATE_DISCONNECTED) {
                     sendMessage(TRANSITION_TO_STABLE);
                 }
-            } else if (action.equals(BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED)) {
-                int newState = intent.getIntExtra(BluetoothInputDevice.EXTRA_INPUT_DEVICE_STATE, 0);
+            } else if (action.equals(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED)) {
+                int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
                 int oldState =
-                    intent.getIntExtra(BluetoothInputDevice.EXTRA_PREVIOUS_INPUT_DEVICE_STATE, 0);
+                    intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0);
 
-                if (oldState == BluetoothInputDevice.STATE_CONNECTED &&
-                    newState == BluetoothInputDevice.STATE_DISCONNECTED) {
+                if (oldState == BluetoothProfile.STATE_CONNECTED &&
+                    newState == BluetoothProfile.STATE_DISCONNECTED) {
                     sendMessage(DISCONNECT_HID_INCOMING);
                 }
-                if (newState == BluetoothInputDevice.STATE_CONNECTED ||
-                    newState == BluetoothInputDevice.STATE_DISCONNECTED) {
+                if (newState == BluetoothProfile.STATE_CONNECTED ||
+                    newState == BluetoothProfile.STATE_DISCONNECTED) {
                     sendMessage(TRANSITION_TO_STABLE);
                 }
             } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
@@ -194,7 +194,7 @@
         filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
         filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
         filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
-        filter.addAction(BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED);
+        filter.addAction(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED);
         filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
 
         mContext.registerReceiver(mBroadcastReceiver, filter);
@@ -286,7 +286,7 @@
                         sendMessage(DISCONNECT_A2DP_OUTGOING);
                         deferMessage(message);
                         break;
-                    } else if (mService.getInputDeviceState(mDevice) !=
+                    } else if (mService.getInputDeviceConnectionState(mDevice) !=
                             BluetoothInputDevice.STATE_DISCONNECTED) {
                         sendMessage(DISCONNECT_HID_OUTGOING);
                         deferMessage(message);
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java
index a70de59..df212a8 100644
--- a/core/java/android/bluetooth/BluetoothInputDevice.java
+++ b/core/java/android/bluetooth/BluetoothInputDevice.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 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.
@@ -27,91 +27,88 @@
 import java.util.ArrayList;
 import java.util.List;
 
+
 /**
- * Public API for controlling the Bluetooth HID (Input Device) Profile
+ * This class provides the public APIs to control the Bluetooth Input
+ * Device Profile.
  *
- * BluetoothInputDevice is a proxy object used to make calls to Bluetooth Service
- * which handles the HID profile.
+ *<p>BluetoothInputDevice is a proxy object for controlling the Bluetooth
+ * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
+ * the BluetoothInputDevice proxy object.
  *
- * Creating a BluetoothInputDevice object will initiate a binding with the
- * Bluetooth service. Users of this object should call close() when they
- * are finished, so that this proxy object can unbind from the service.
- *
- * Currently the Bluetooth service runs in the system server and this
- * proxy object will be immediately bound to the service on construction.
- *
- *  @hide
+ *<p>Each method is protected with its appropriate permission.
+ *@hide
  */
-public final class BluetoothInputDevice {
+public final class BluetoothInputDevice implements BluetoothProfile {
     private static final String TAG = "BluetoothInputDevice";
     private static final boolean DBG = false;
 
-    /** int extra for ACTION_INPUT_DEVICE_STATE_CHANGED */
-    public static final String EXTRA_INPUT_DEVICE_STATE =
-        "android.bluetooth.inputdevice.extra.INPUT_DEVICE_STATE";
-    /** int extra for ACTION_INPUT_DEVICE_STATE_CHANGED */
-    public static final String EXTRA_PREVIOUS_INPUT_DEVICE_STATE =
-        "android.bluetooth.inputdevice.extra.PREVIOUS_INPUT_DEVICE_STATE";
-
-    /** Indicates the state of an input device has changed.
-     * This intent will always contain EXTRA_INPUT_DEVICE_STATE,
-     * EXTRA_PREVIOUS_INPUT_DEVICE_STATE and BluetoothDevice.EXTRA_DEVICE
-     * extras.
+    /**
+     * Intent used to broadcast the change in connection state of the Input
+     * Device profile.
+     *
+     * <p>This intent will have 3 extras:
+     * <ul>
+     *   <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
+     *   <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
+     *   <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
+     * </ul>
+     *
+     * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
+     * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
+     * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+     * receive.
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_INPUT_DEVICE_STATE_CHANGED =
-        "android.bluetooth.inputdevice.action.INPUT_DEVICE_STATE_CHANGED";
-
-    public static final int STATE_DISCONNECTED = 0;
-    public static final int STATE_CONNECTING   = 1;
-    public static final int STATE_CONNECTED    = 2;
-    public static final int STATE_DISCONNECTING = 3;
-
-    /**
-     * Auto connection, incoming and outgoing connection are allowed at this
-     * priority level.
-     */
-    public static final int PRIORITY_AUTO_CONNECT = 1000;
-    /**
-     * Incoming and outgoing connection are allowed at this priority level
-     */
-    public static final int PRIORITY_ON = 100;
-    /**
-     * Connections to the device are not allowed at this priority level.
-     */
-    public static final int PRIORITY_OFF = 0;
-    /**
-     * Default priority level when the device is unpaired.
-     */
-    public static final int PRIORITY_UNDEFINED = -1;
+    public static final String ACTION_CONNECTION_STATE_CHANGED =
+        "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED";
 
     /**
      * Return codes for the connect and disconnect Bluez / Dbus calls.
+     * @hide
      */
     public static final int INPUT_DISCONNECT_FAILED_NOT_CONNECTED = 5000;
 
+    /**
+     * @hide
+     */
     public static final int INPUT_CONNECT_FAILED_ALREADY_CONNECTED = 5001;
 
+    /**
+     * @hide
+     */
     public static final int INPUT_CONNECT_FAILED_ATTEMPT_FAILED = 5002;
 
+    /**
+     * @hide
+     */
     public static final int INPUT_OPERATION_GENERIC_FAILURE = 5003;
 
+    /**
+     * @hide
+     */
     public static final int INPUT_OPERATION_SUCCESS = 5004;
 
-    private final IBluetooth mService;
-    private final Context mContext;
+    private ServiceListener mServiceListener;
+    private BluetoothAdapter mAdapter;
+    private IBluetooth mService;
 
     /**
      * Create a BluetoothInputDevice proxy object for interacting with the local
-     * Bluetooth Service which handle the HID profile.
-     * @param c Context
+     * Bluetooth Service which handles the InputDevice profile
+     *
      */
-    public BluetoothInputDevice(Context c) {
-        mContext = c;
-
+    /*package*/ BluetoothInputDevice(Context mContext, ServiceListener l) {
         IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE);
+        mServiceListener = l;
+        mAdapter = BluetoothAdapter.getDefaultAdapter();
         if (b != null) {
             mService = IBluetooth.Stub.asInterface(b);
+            if (mServiceListener != null) {
+                mServiceListener.onServiceConnected(BluetoothProfile.INPUT_DEVICE, this);
+            }
         } else {
             Log.w(TAG, "Bluetooth Service not available!");
 
@@ -121,130 +118,151 @@
         }
     }
 
-    /** Initiate a connection to an Input device.
-     *
-     *  This function returns false on error and true if the connection
-     *  attempt is being made.
-     *
-     *  Listen for INPUT_DEVICE_STATE_CHANGED_ACTION to find out when the
-     *  connection is completed.
-     *  @param device Remote BT device.
-     *  @return false on immediate error, true otherwise
-     *  @hide
+    /**
+     * {@inheritDoc}
+     * @hide
      */
-    public boolean connectInputDevice(BluetoothDevice device) {
-        if (DBG) log("connectInputDevice(" + device + ")");
-        try {
-            return mService.connectInputDevice(device);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return false;
+    public boolean connect(BluetoothDevice device) {
+        if (DBG) log("connect(" + device + ")");
+        if (mService != null && isEnabled() &&
+            isValidDevice(device)) {
+            try {
+                return mService.connectInputDevice(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+                return false;
+            }
         }
-    }
-
-    /** Initiate disconnect from an Input Device.
-     *  This function return false on error and true if the disconnection
-     *  attempt is being made.
-     *
-     *  Listen for INPUT_DEVICE_STATE_CHANGED_ACTION to find out when
-     *  disconnect is completed.
-     *
-     *  @param device Remote BT device.
-     *  @return false on immediate error, true otherwise
-     *  @hide
-     */
-    public boolean disconnectInputDevice(BluetoothDevice device) {
-        if (DBG) log("disconnectInputDevice(" + device + ")");
-        try {
-            return mService.disconnectInputDevice(device);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return false;
-        }
-    }
-
-    /** Check if a specified InputDevice is connected.
-     *
-     *  @param device Remote BT device.
-     *  @return True if connected , false otherwise and on error.
-     *  @hide
-     */
-    public boolean isInputDeviceConnected(BluetoothDevice device) {
-        if (DBG) log("isInputDeviceConnected(" + device + ")");
-        int state = getInputDeviceState(device);
-        if (state == STATE_CONNECTED) return true;
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
-    /** Check if any Input Device is connected.
-     *
-     * @return List of devices, empty List on error.
+    /**
+     * {@inheritDoc}
      * @hide
      */
-    public List<BluetoothDevice> getConnectedInputDevices() {
-        if (DBG) log("getConnectedInputDevices()");
-        try {
-            return mService.getConnectedInputDevices();
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return new ArrayList<BluetoothDevice>();
+    public boolean disconnect(BluetoothDevice device) {
+        if (DBG) log("disconnect(" + device + ")");
+        if (mService != null && isEnabled() &&
+            isValidDevice(device)) {
+            try {
+                return mService.disconnectInputDevice(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+                return false;
+            }
         }
-    }
-
-    /** Get the state of an Input Device.
-     *
-     *  @param device Remote BT device.
-     *  @return The current state of the Input Device
-     *  @hide
-     */
-    public int getInputDeviceState(BluetoothDevice device) {
-        if (DBG) log("getInputDeviceState(" + device + ")");
-        try {
-            return mService.getInputDeviceState(device);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return STATE_DISCONNECTED;
-        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return false;
     }
 
     /**
-     * Set priority of an input device.
-     *
-     * Priority is a non-negative integer. Priority can take the following
-     * values:
-     * {@link PRIORITY_ON}, {@link PRIORITY_OFF}, {@link PRIORITY_AUTO_CONNECT}
-     *
-     * @param device Paired device.
-     * @param priority Integer priority
-     * @return true if priority is set, false on error
+     * {@inheritDoc}
      */
-    public boolean setInputDevicePriority(BluetoothDevice device, int priority) {
-        if (DBG) log("setInputDevicePriority(" + device + ", " + priority + ")");
-        try {
-            return mService.setInputDevicePriority(device, priority);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return false;
+    public List<BluetoothDevice> getConnectedDevices() {
+        if (DBG) log("getConnectedDevices()");
+        if (mService != null && isEnabled()) {
+            try {
+                return mService.getConnectedInputDevices();
+            } catch (RemoteException e) {
+                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+                return new ArrayList<BluetoothDevice>();
+            }
         }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return new ArrayList<BluetoothDevice>();
     }
 
     /**
-     * Get the priority associated with an Input Device.
-     *
-     * @param device Input Device
-     * @return non-negative priority, or negative error code on error.
+     * {@inheritDoc}
      */
-    public int getInputDevicePriority(BluetoothDevice device) {
-        if (DBG) log("getInputDevicePriority(" + device + ")");
-        try {
-            return mService.getInputDevicePriority(device);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-            return PRIORITY_OFF;
+    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+        if (DBG) log("getDevicesMatchingStates()");
+        if (mService != null && isEnabled()) {
+            try {
+                return mService.getInputDevicesMatchingConnectionStates(states);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+                return new ArrayList<BluetoothDevice>();
+            }
         }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return new ArrayList<BluetoothDevice>();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int getConnectionState(BluetoothDevice device) {
+        if (DBG) log("getState(" + device + ")");
+        if (mService != null && isEnabled()
+            && isValidDevice(device)) {
+            try {
+                return mService.getInputDeviceConnectionState(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+                return BluetoothProfile.STATE_DISCONNECTED;
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return BluetoothProfile.STATE_DISCONNECTED;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @hide
+     */
+    public boolean setPriority(BluetoothDevice device, int priority) {
+        if (DBG) log("setPriority(" + device + ", " + priority + ")");
+        if (mService != null && isEnabled()
+            && isValidDevice(device)) {
+            if (priority != BluetoothProfile.PRIORITY_OFF &&
+                priority != BluetoothProfile.PRIORITY_ON) {
+              return false;
+            }
+            try {
+                return mService.setInputDevicePriority(device, priority);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+                return false;
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @hide
+     */
+    public int getPriority(BluetoothDevice device) {
+        if (DBG) log("getPriority(" + device + ")");
+        if (mService != null && isEnabled()
+            && isValidDevice(device)) {
+            try {
+                return mService.getInputDevicePriority(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+                return BluetoothProfile.PRIORITY_OFF;
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return BluetoothProfile.PRIORITY_OFF;
+    }
+
+    private boolean isEnabled() {
+       if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
+       return false;
+    }
+
+    private boolean isValidDevice(BluetoothDevice device) {
+       if (device == null) return false;
+
+       if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
+       return false;
     }
 
     private static void log(String msg) {
-        Log.d(TAG, msg);
+      Log.d(TAG, msg);
     }
 }
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index ef80195d..1ffee72 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -62,6 +62,11 @@
      * A2DP profile.
      */
     public static final int A2DP = 2;
+    /**
+     * Input Device Profile
+     * @hide
+     */
+    public static final int INPUT_DEVICE = 3;
 
     /**
      * Default priority for devices that we try to auto-connect to and
diff --git a/core/java/android/bluetooth/BluetoothProfileState.java b/core/java/android/bluetooth/BluetoothProfileState.java
index 3f36926..18060a0 100644
--- a/core/java/android/bluetooth/BluetoothProfileState.java
+++ b/core/java/android/bluetooth/BluetoothProfileState.java
@@ -72,10 +72,10 @@
                     newState == BluetoothProfile.STATE_DISCONNECTED)) {
                     sendMessage(TRANSITION_TO_STABLE);
                 }
-            } else if (action.equals(BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED)) {
-                int newState = intent.getIntExtra(BluetoothInputDevice.EXTRA_INPUT_DEVICE_STATE, 0);
-                if (mProfile == HID && (newState == BluetoothInputDevice.STATE_CONNECTED ||
-                    newState == BluetoothInputDevice.STATE_DISCONNECTED)) {
+            } else if (action.equals(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED)) {
+                int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
+                if (mProfile == HID && (newState == BluetoothProfile.STATE_CONNECTED ||
+                    newState == BluetoothProfile.STATE_DISCONNECTED)) {
                     sendMessage(TRANSITION_TO_STABLE);
                 }
             } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
@@ -96,7 +96,7 @@
         IntentFilter filter = new IntentFilter();
         filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
         filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
-        filter.addAction(BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED);
+        filter.addAction(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED);
         filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
         context.registerReceiver(mBroadcastReceiver, filter);
     }
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index f3e73cf..69fb06a 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -85,7 +85,8 @@
     boolean connectInputDevice(in BluetoothDevice device);
     boolean disconnectInputDevice(in BluetoothDevice device);
     List<BluetoothDevice> getConnectedInputDevices();
-    int getInputDeviceState(in BluetoothDevice device);
+    List<BluetoothDevice> getInputDevicesMatchingConnectionStates(in int[] states);
+    int getInputDeviceConnectionState(in BluetoothDevice device);
     boolean setInputDevicePriority(in BluetoothDevice device, int priority);
     int getInputDevicePriority(in BluetoothDevice device);
 
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 85f64d0..81eb09c 100755
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -115,7 +115,7 @@
     private CompatibilityInfo mCompatibilityInfo;
     private Display mDefaultDisplay;
 
-    private static final LongSparseArray<Object> EMPTY_ARRAY = new LongSparseArray<Object>() {
+    private static final LongSparseArray<Object> EMPTY_ARRAY = new LongSparseArray<Object>(0) {
         @Override
         public void put(long k, Object o) {
             throw new UnsupportedOperationException();
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index 3316ea5..c0b3cc8 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -57,6 +57,7 @@
     private final BluetoothService mBluetoothService;
     private final BluetoothAdapter mAdapter;
     private BluetoothA2dp mA2dp;
+    private BluetoothInputDevice mInputDevice;
     private final Context mContext;
     // The WakeLock is used for bringing up the LCD during a pairing request
     // from remote device when Android is in Suspend state.
@@ -125,15 +126,24 @@
 
     /*package*/ void getProfileProxy() {
         mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.A2DP);
+        mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.INPUT_DEVICE);
     }
 
     private BluetoothProfile.ServiceListener mProfileServiceListener =
         new BluetoothProfile.ServiceListener() {
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mA2dp = (BluetoothA2dp) proxy;
+            if (profile == BluetoothProfile.A2DP) {
+                mA2dp = (BluetoothA2dp) proxy;
+            } else if (profile == BluetoothProfile.INPUT_DEVICE) {
+                mInputDevice = (BluetoothInputDevice) proxy;
+            }
         }
         public void onServiceDisconnected(int profile) {
-            mA2dp = null;
+            if (profile == BluetoothProfile.A2DP) {
+                mA2dp = null;
+            } else if (profile == BluetoothProfile.INPUT_DEVICE) {
+                mInputDevice = null;
+            }
         }
     };
 
@@ -651,10 +661,9 @@
             } else {
                 Log.i(TAG, "Rejecting incoming A2DP / AVRCP connection from " + address);
             }
-        } else if (BluetoothUuid.isInputDevice(uuid) && !isOtherInputDeviceConnected(address)) {
-            BluetoothInputDevice inputDevice = new BluetoothInputDevice(mContext);
-            authorized = inputDevice.getInputDevicePriority(device) >
-                         BluetoothInputDevice.PRIORITY_OFF;
+        } else if (mInputDevice != null && BluetoothUuid.isInputDevice(uuid)) {
+            // We can have more than 1 input device connected.
+            authorized = mInputDevice.getPriority(device) > BluetoothInputDevice.PRIORITY_OFF;
              if (authorized) {
                  Log.i(TAG, "Allowing incoming HID connection from " + address);
              } else {
@@ -669,18 +678,6 @@
         return authorized;
     }
 
-    private boolean isOtherInputDeviceConnected(String address) {
-        List<BluetoothDevice> devices =
-            mBluetoothService.lookupInputDevicesMatchingStates(new int[] {
-                                                BluetoothInputDevice.STATE_CONNECTING,
-                                                BluetoothInputDevice.STATE_CONNECTED});
-
-        for (BluetoothDevice device : devices) {
-            if (!device.getAddress().equals(address)) return true;
-        }
-        return false;
-    }
-
     private boolean onAgentOutOfBandDataAvailable(String objectPath) {
         if (!mBluetoothService.isEnabled()) return false;
 
@@ -758,7 +755,7 @@
 
             boolean connected = false;
             BluetoothDevice device = mAdapter.getRemoteDevice(address);
-            int state = mBluetoothService.getInputDeviceState(device);
+            int state = mBluetoothService.getInputDeviceConnectionState(device);
             if (state == BluetoothInputDevice.STATE_CONNECTING) {
                 if (result == BluetoothInputDevice.INPUT_CONNECT_FAILED_ALREADY_CONNECTED) {
                     connected = true;
diff --git a/core/java/android/server/BluetoothInputProfileHandler.java b/core/java/android/server/BluetoothInputProfileHandler.java
index 7ffa5ae..cdc0f2d 100644
--- a/core/java/android/server/BluetoothInputProfileHandler.java
+++ b/core/java/android/server/BluetoothInputProfileHandler.java
@@ -64,7 +64,7 @@
                                             BluetoothDeviceProfileState state) {
         String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
         if (objectPath == null ||
-            getInputDeviceState(device) != BluetoothInputDevice.STATE_DISCONNECTED ||
+            getInputDeviceConnectionState(device) != BluetoothInputDevice.STATE_DISCONNECTED ||
             getInputDevicePriority(device) == BluetoothInputDevice.PRIORITY_OFF) {
             return false;
         }
@@ -92,7 +92,7 @@
                                                BluetoothDeviceProfileState state) {
         String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
         if (objectPath == null ||
-                getInputDeviceState(device) == BluetoothInputDevice.STATE_DISCONNECTED) {
+                getInputDeviceConnectionState(device) == BluetoothInputDevice.STATE_DISCONNECTED) {
             return false;
         }
         if (state != null) {
@@ -115,7 +115,7 @@
         return true;
     }
 
-    synchronized int getInputDeviceState(BluetoothDevice device) {
+    synchronized int getInputDeviceConnectionState(BluetoothDevice device) {
         if (mInputDevices.get(device) == null) {
             return BluetoothInputDevice.STATE_DISCONNECTED;
         }
@@ -128,6 +128,11 @@
         return devices;
     }
 
+    synchronized List<BluetoothDevice> getInputDevicesMatchingConnectionStates(int[] states) {
+        List<BluetoothDevice> devices = lookupInputDevicesMatchingStates(states);
+        return devices;
+    }
+
     synchronized int getInputDevicePriority(BluetoothDevice device) {
         return Settings.Secure.getInt(mContext.getContentResolver(),
                 Settings.Secure.getBluetoothInputDevicePriorityKey(device.getAddress()),
@@ -147,7 +152,7 @@
         List<BluetoothDevice> inputDevices = new ArrayList<BluetoothDevice>();
 
         for (BluetoothDevice device: mInputDevices.keySet()) {
-            int inputDeviceState = getInputDeviceState(device);
+            int inputDeviceState = getInputDeviceConnectionState(device);
             for (int state : states) {
                 if (state == inputDeviceState) {
                     inputDevices.add(device);
@@ -178,10 +183,10 @@
             setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_AUTO_CONNECT);
         }
 
-        Intent intent = new Intent(BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED);
+        Intent intent = new Intent(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED);
         intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
-        intent.putExtra(BluetoothInputDevice.EXTRA_PREVIOUS_INPUT_DEVICE_STATE, prevState);
-        intent.putExtra(BluetoothInputDevice.EXTRA_INPUT_DEVICE_STATE, state);
+        intent.putExtra(BluetoothInputDevice.EXTRA_PREVIOUS_STATE, prevState);
+        intent.putExtra(BluetoothInputDevice.EXTRA_STATE, state);
         mContext.sendBroadcast(intent, BluetoothService.BLUETOOTH_PERM);
 
         debugLog("InputDevice state : device: " + device + " State:" + prevState + "->" + state);
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index a295de5..70aaf0a 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -31,6 +31,7 @@
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothDeviceProfileState;
 import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothInputDevice;
 import android.bluetooth.BluetoothPan;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothProfileState;
@@ -83,6 +84,7 @@
     private int mNativeData;
     private BluetoothEventLoop mEventLoop;
     private BluetoothHeadset mBluetoothHeadset;
+    private BluetoothInputDevice mInputDevice;
     private boolean mIsAirplaneSensitive;
     private boolean mIsAirplaneToggleable;
     private int mBluetoothState;
@@ -2078,6 +2080,8 @@
 
         mAdapter.getProfileProxy(mContext,
                                  mBluetoothProfileServiceListener, BluetoothProfile.HEADSET);
+        mAdapter.getProfileProxy(mContext,
+                mBluetoothProfileServiceListener, BluetoothProfile.INPUT_DEVICE);
 
         pw.println("\n--Known devices--");
         for (String address : mDeviceProperties.keySet()) {
@@ -2119,8 +2123,17 @@
             }
         }
 
-        // Rather not do this from here, but no-where else and I need this
-        // dump
+        dumpHeadsetProfile(pw);
+        dumpInputDeviceProfile(pw);
+
+        pw.println("\n--Application Service Records--");
+        for (Integer handle : mServiceRecordToPid.keySet()) {
+            Integer pid = mServiceRecordToPid.get(handle);
+            pw.println("\tpid " + pid + " handle " + Integer.toHexString(handle));
+        }
+    }
+
+    private void dumpHeadsetProfile(PrintWriter pw) {
         pw.println("\n--Headset Service--");
         if (mBluetoothHeadset != null) {
             List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices();
@@ -2158,24 +2171,60 @@
                     pw.println("SCO audio connected to device:" + device);
                 }
             }
-
-            mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
         }
+        mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
+    }
 
-        pw.println("\n--Application Service Records--");
-        for (Integer handle : mServiceRecordToPid.keySet()) {
-            Integer pid = mServiceRecordToPid.get(handle);
-            pw.println("\tpid " + pid + " handle " + Integer.toHexString(handle));
+    private void dumpInputDeviceProfile(PrintWriter pw) {
+        pw.println("\n--Bluetooth Service- Input Device Profile");
+        if (mInputDevice != null) {
+            List<BluetoothDevice> deviceList = mInputDevice.getConnectedDevices();
+            if (deviceList.size() == 0) {
+                pw.println("\nNo input devices connected--");
+            } else {
+                pw.println("\nNumber of connected devices:" + deviceList.size());
+                BluetoothDevice device = deviceList.get(0);
+                pw.println("getConnectedDevices[0] = " + device);
+                pw.println("Priority of Connected device = " + mInputDevice.getPriority(device));
+
+                switch (mInputDevice.getConnectionState(device)) {
+                    case BluetoothInputDevice.STATE_CONNECTING:
+                        pw.println("getConnectionState() = STATE_CONNECTING");
+                        break;
+                    case BluetoothInputDevice.STATE_CONNECTED:
+                        pw.println("getConnectionState() = STATE_CONNECTED");
+                        break;
+                    case BluetoothInputDevice.STATE_DISCONNECTING:
+                        pw.println("getConnectionState() = STATE_DISCONNECTING");
+                        break;
+                }
+            }
+            deviceList.clear();
+            deviceList = mInputDevice.getDevicesMatchingConnectionStates(new int[] {
+                     BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED});
+            pw.println("--Connected and Disconnected input devices");
+            for (BluetoothDevice device: deviceList) {
+                pw.println(device);
+            }
         }
+        mAdapter.closeProfileProxy(BluetoothProfile.INPUT_DEVICE, mBluetoothHeadset);
     }
 
     private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
         new BluetoothProfile.ServiceListener() {
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mBluetoothHeadset = (BluetoothHeadset) proxy;
-    }
+            if (profile == BluetoothProfile.HEADSET) {
+                mBluetoothHeadset = (BluetoothHeadset) proxy;
+            } else if (profile == BluetoothProfile.INPUT_DEVICE) {
+                mInputDevice = (BluetoothInputDevice) proxy;
+            }
+        }
         public void onServiceDisconnected(int profile) {
-            mBluetoothHeadset = null;
+            if (profile == BluetoothProfile.HEADSET) {
+                mBluetoothHeadset = null;
+            } else if (profile == BluetoothProfile.INPUT_DEVICE) {
+                mInputDevice = null;
+            }
         }
     };
 
@@ -2311,9 +2360,9 @@
         return mBluetoothInputProfileHandler.disconnectInputDeviceInternal(device);
     }
 
-    public synchronized int getInputDeviceState(BluetoothDevice device) {
+    public synchronized int getInputDeviceConnectionState(BluetoothDevice device) {
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        return mBluetoothInputProfileHandler.getInputDeviceState(device);
+        return mBluetoothInputProfileHandler.getInputDeviceConnectionState(device);
 
     }
 
@@ -2322,6 +2371,13 @@
         return mBluetoothInputProfileHandler.getConnectedInputDevices();
     }
 
+    public synchronized List<BluetoothDevice> getInputDevicesMatchingConnectionStates(
+            int[] states) {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+        return mBluetoothInputProfileHandler.getInputDevicesMatchingConnectionStates(states);
+    }
+
+
     public synchronized int getInputDevicePriority(BluetoothDevice device) {
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
         return mBluetoothInputProfileHandler.getInputDevicePriority(device);
diff --git a/core/java/android/util/AttributeSet.java b/core/java/android/util/AttributeSet.java
index 82592b9..470526c 100644
--- a/core/java/android/util/AttributeSet.java
+++ b/core/java/android/util/AttributeSet.java
@@ -56,10 +56,53 @@
  * identifier associated with a particular XML attribute name.
  */
 public interface AttributeSet {
+    /**
+     * Returns the number of attributes available in the set.
+     * 
+     * @return A positive integer, or 0 if the set is empty.
+     */
     public int getAttributeCount();
+
+    /**
+     * Returns the name of the specified attribute.
+     * 
+     * @param index Index of the desired attribute, 0...count-1.
+     * 
+     * @return A String containing the name of the attribute, or null if the
+     *         attribute cannot be found.
+     */
     public String getAttributeName(int index);
+
+    /**
+     * Returns the value of the specified attribute as a string representation.
+     * 
+     * @param index Index of the desired attribute, 0...count-1.
+     * 
+     * @return A String containing the value of the attribute, or null if the
+     *         attribute cannot be found.
+     */
     public String getAttributeValue(int index);
+
+    /**
+     * Returns the value of the specified attribute as a string representation.
+     * The lookup is performed using the attribute name.
+     * 
+     * @param namespace The namespace of the attribute to get the value from.
+     * @param name The name of the attribute to get the value from.
+     * 
+     * @return A String containing the value of the attribute, or null if the
+     *         attribute cannot be found.
+     */
     public String getAttributeValue(String namespace, String name);
+
+    /**
+     * Returns a description of the current position of the attribute set.
+     * For instance, if the attribute set is loaded from an XML document,
+     * the position description could indicate the current line number.
+     * 
+     * @return A string representation of the current position in the set,
+     *         may be null.
+     */
     public String getPositionDescription();
 
     /**
@@ -80,7 +123,8 @@
 
     /**
      * Return the index of the value of 'attribute' in the list 'options'.
-     * 
+     *
+     * @param namespace Namespace of attribute to retrieve. 
      * @param attribute Name of attribute to retrieve.
      * @param options List of strings whose values we are checking against.
      * @param defaultValue Value returned if attribute doesn't exist or no
@@ -94,6 +138,7 @@
     /**
      * Return the boolean value of 'attribute'.
      * 
+     * @param namespace Namespace of attribute to retrieve.
      * @param attribute The attribute to retrieve.
      * @param defaultValue What to return if the attribute isn't found.
      * 
@@ -111,6 +156,7 @@
      * "@package:type/resource"); the other method returns a resource
      * identifier that identifies the name of the attribute.
      * 
+     * @param namespace Namespace of attribute to retrieve.
      * @param attribute The attribute to retrieve.
      * @param defaultValue What to return if the attribute isn't found.
      * 
@@ -122,6 +168,7 @@
     /**
      * Return the integer value of 'attribute'.
      * 
+     * @param namespace Namespace of attribute to retrieve.
      * @param attribute The attribute to retrieve.
      * @param defaultValue What to return if the attribute isn't found.
      * 
@@ -135,6 +182,7 @@
      * unsigned value.  In particular, the formats 0xn...n and #n...n are
      * handled.
      * 
+     * @param namespace Namespace of attribute to retrieve.
      * @param attribute The attribute to retrieve.
      * @param defaultValue What to return if the attribute isn't found.
      * 
@@ -146,6 +194,7 @@
     /**
      * Return the float value of 'attribute'.
      * 
+     * @param namespace Namespace of attribute to retrieve.
      * @param attribute The attribute to retrieve.
      * @param defaultValue What to return if the attribute isn't found.
      * 
@@ -165,8 +214,7 @@
      * 
      * @return Index in to 'options' or defaultValue.
      */
-    public int getAttributeListValue(int index,
-                                     String[] options, int defaultValue);
+    public int getAttributeListValue(int index, String[] options, int defaultValue);
 
     /**
      * Return the boolean value of attribute at 'index'.
@@ -176,8 +224,7 @@
      * 
      * @return Resulting value.
      */
-    public boolean getAttributeBooleanValue(int index,
-                                            boolean defaultValue);
+    public boolean getAttributeBooleanValue(int index, boolean defaultValue);
 
     /**
      * Return the value of attribute at 'index' as a resource identifier.
@@ -193,8 +240,7 @@
      * 
      * @return Resulting value.
      */
-    public int getAttributeResourceValue(int index,
-                                         int defaultValue);
+    public int getAttributeResourceValue(int index, int defaultValue);
 
     /**
      * Return the integer value of attribute at 'index'.
@@ -204,8 +250,7 @@
      * 
      * @return Resulting value.
      */
-    public int getAttributeIntValue(int index,
-                                    int defaultValue);
+    public int getAttributeIntValue(int index, int defaultValue);
 
     /**
      * Return the integer value of attribute at 'index' that is formatted as an
@@ -217,8 +262,7 @@
      * 
      * @return Resulting value.
      */
-    public int getAttributeUnsignedIntValue(int index,
-                                            int defaultValue);
+    public int getAttributeUnsignedIntValue(int index, int defaultValue);
 
     /**
      * Return the float value of attribute at 'index'.
@@ -228,8 +272,7 @@
      * 
      * @return Resulting value.
      */
-    public float getAttributeFloatValue(int index,
-                                        float defaultValue);
+    public float getAttributeFloatValue(int index, float defaultValue);
 
     /**
      * Return the value of the "id" attribute or null if there is not one.
@@ -266,4 +309,3 @@
      */
     public int getStyleAttribute();
 }
-
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 51653df..dd8242a 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -100,6 +100,8 @@
     void disableKeyguard(IBinder token, String tag);
     void reenableKeyguard(IBinder token);
     void exitKeyguardSecurely(IOnKeyguardExitResult callback);
+    boolean isKeyguardLocked();
+    boolean isKeyguardSecure();
     boolean inKeyguardRestrictedInputMode();
 
     void closeSystemDialogs(String reason);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index eefce06..ae06888 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6665,7 +6665,14 @@
      * view specifying how it should be arranged. There are many subclasses of
      * ViewGroup.LayoutParams, and these correspond to the different subclasses
      * of ViewGroup that are responsible for arranging their children.
-     * @return The LayoutParams associated with this view
+     *
+     * This method may return null if this View is not attached to a parent
+     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
+     * was not invoked successfully. When a View is attached to a parent
+     * ViewGroup, this method must not return null.
+     *
+     * @return The LayoutParams associated with this view, or null if no
+     *         parameters have been set yet
      */
     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
     public ViewGroup.LayoutParams getLayoutParams() {
@@ -6679,11 +6686,11 @@
      * correspond to the different subclasses of ViewGroup that are responsible
      * for arranging their children.
      *
-     * @param params the layout parameters for this view
+     * @param params The layout parameters for this view, cannot be null
      */
     public void setLayoutParams(ViewGroup.LayoutParams params) {
         if (params == null) {
-            throw new NullPointerException("params == null");
+            throw new NullPointerException("Layout parameters cannot be null");
         }
         mLayoutParams = params;
         requestLayout();
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index ad06902..be68cb9 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -754,6 +754,24 @@
     void exitKeyguardSecurely(OnKeyguardExitResult callback);
 
     /**
+     * isKeyguardLocked
+     *
+     * Return whether the keyguard is currently locked.
+     *
+     * @return true if in keyguard is locked.
+     */
+    public boolean isKeyguardLocked();
+
+    /**
+     * isKeyguardSecure
+     *
+     * Return whether the keyguard requires a password to unlock.
+     *
+     * @return true if in keyguard is secure.
+     */
+    public boolean isKeyguardSecure();
+
+    /**
      * inKeyguardRestrictedKeyInputMode
      *
      * if keyguard screen is showing or in restricted key input mode (i.e. in
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 74e6628..d9f050b 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -5531,6 +5531,8 @@
                         ted.mPoints[0] = new Point(contentX, contentY);
                         ted.mMetaState = ev.getMetaState();
                         ted.mReprocess = mDeferTouchProcess;
+                        ted.mNativeLayer = nativeScrollableLayer(
+                                contentX, contentY, ted.mNativeLayerRect, null);
                         mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
                         if (mDeferTouchProcess) {
                             // still needs to set them for compute deltaX/Y
@@ -5575,6 +5577,8 @@
                     ted.mPoints[0] = new Point(contentX, contentY);
                     ted.mMetaState = ev.getMetaState();
                     ted.mReprocess = mDeferTouchProcess;
+                    ted.mNativeLayer = mScrollingLayer;
+                    ted.mNativeLayerRect.set(mScrollingLayerRect);
                     mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
                     mLastSentTouchTime = eventTime;
                     if (mDeferTouchProcess) {
@@ -5754,6 +5758,8 @@
                     ted.mPoints[0] = new Point(contentX, contentY);
                     ted.mMetaState = ev.getMetaState();
                     ted.mReprocess = mDeferTouchProcess;
+                    ted.mNativeLayer = mScrollingLayer;
+                    ted.mNativeLayerRect.set(mScrollingLayerRect);
                     mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
                 }
                 mLastTouchUpTime = eventTime;
@@ -5773,6 +5779,9 @@
                             ted.mPoints[0] = new Point(contentX, contentY);
                             ted.mMetaState = ev.getMetaState();
                             ted.mReprocess = mDeferTouchProcess;
+                            ted.mNativeLayer = nativeScrollableLayer(
+                                    contentX, contentY,
+                                    ted.mNativeLayerRect, null);
                             mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
                         } else if (mPreventDefault != PREVENT_DEFAULT_YES){
                             mZoomManager.handleDoubleTap(mLastTouchX, mLastTouchY);
@@ -6004,6 +6013,8 @@
             ted.mPoints = new Point[1];
             ted.mPoints[0] = new Point(x, y);
             ted.mAction = MotionEvent.ACTION_CANCEL;
+            ted.mNativeLayer = nativeScrollableLayer(
+                    x, y, ted.mNativeLayerRect, null);
             mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
             mPreventDefault = PREVENT_DEFAULT_IGNORE;
         }
@@ -6643,8 +6654,9 @@
         // mLastTouchX and mLastTouchY are the point in the current viewport
         int contentX = viewToContentX(mLastTouchX + mScrollX);
         int contentY = viewToContentY(mLastTouchY + mScrollY);
-        Rect rect = new Rect(contentX - mNavSlop, contentY - mNavSlop,
-                contentX + mNavSlop, contentY + mNavSlop);
+        int slop = viewToContentDimension(mNavSlop);
+        Rect rect = new Rect(contentX - slop, contentY - slop,
+                contentX + slop, contentY + slop);
         nativeSelectBestAt(rect);
         mInitialHitTestResult = hitTestResult(null);
     }
@@ -6718,7 +6730,8 @@
         }
         int x = viewToContentX((int) event.getX() + mWebTextView.getLeft());
         int y = viewToContentY((int) event.getY() + mWebTextView.getTop());
-        nativeMotionUp(x, y, mNavSlop);
+        int slop = viewToContentDimension(mNavSlop);
+        nativeMotionUp(x, y, slop);
     }
 
     /**
@@ -6741,6 +6754,7 @@
         // mLastTouchX and mLastTouchY are the point in the current viewport
         int contentX = viewToContentX(mLastTouchX + mScrollX);
         int contentY = viewToContentY(mLastTouchY + mScrollY);
+        int slop = viewToContentDimension(mNavSlop);
         if (getSettings().supportTouchOnly()) {
             removeTouchHighlight(false);
             WebViewCore.TouchUpData touchUpData = new WebViewCore.TouchUpData();
@@ -6748,7 +6762,7 @@
             // it used when processing GET_TOUCH_HIGHLIGHT_RECTS
             touchUpData.mMoveGeneration = 0;
             mWebViewCore.sendMessage(EventHub.TOUCH_UP, touchUpData);
-        } else if (nativePointInNavCache(contentX, contentY, mNavSlop)) {
+        } else if (nativePointInNavCache(contentX, contentY, slop)) {
             WebViewCore.MotionUpData motionUpData = new WebViewCore
                     .MotionUpData();
             motionUpData.mFrame = nativeCacheHitFramePointer();
@@ -6764,7 +6778,8 @@
     }
 
     private void doMotionUp(int contentX, int contentY) {
-        if (nativeMotionUp(contentX, contentY, mNavSlop) && mLogEvent) {
+        int slop = viewToContentDimension(mNavSlop);
+        if (nativeMotionUp(contentX, contentY, slop) && mLogEvent) {
             EventLog.writeEvent(EventLogTags.BROWSER_SNAP_CENTER);
         }
         if (nativeHasCursorNode() && !nativeCursorIsTextInput()) {
@@ -6777,7 +6792,8 @@
      * plugin. Otherwise a NULL rectangle is returned.
      */
     Rect getPluginBounds(int x, int y) {
-        if (nativePointInNavCache(x, y, mNavSlop) && nativeCacheHitIsPlugin()) {
+        int slop = viewToContentDimension(mNavSlop);
+        if (nativePointInNavCache(x, y, slop) && nativeCacheHitIsPlugin()) {
             return nativeCacheHitNodeBounds();
         } else {
             return null;
@@ -7161,6 +7177,9 @@
                         // simplicity for now, we don't set it.
                         ted.mMetaState = 0;
                         ted.mReprocess = mDeferTouchProcess;
+                        ted.mNativeLayer = nativeScrollableLayer(
+                                ted.mPoints[0].x, ted.mPoints[0].y,
+                                ted.mNativeLayerRect, null);
                         mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
                     } else if (mPreventDefault != PREVENT_DEFAULT_YES) {
                         mTouchMode = TOUCH_DONE_MODE;
@@ -8033,6 +8052,8 @@
         touchUpData.mNode = node;
         touchUpData.mX = x;
         touchUpData.mY = y;
+        touchUpData.mNativeLayer = nativeScrollableLayer(
+                x, y, touchUpData.mNativeLayerRect, null);
         mWebViewCore.sendMessage(EventHub.TOUCH_UP, touchUpData);
     }
 
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index da4ce43..fb0f61c 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -778,6 +778,8 @@
         int mNode;
         int mX;
         int mY;
+        int mNativeLayer;
+        Rect mNativeLayerRect = new Rect();
     }
 
     static class TouchHighlightData {
@@ -821,6 +823,8 @@
         int mMetaState;
         boolean mReprocess;
         MotionEvent mMotionEvent;
+        int mNativeLayer;
+        Rect mNativeLayerRect = new Rect();
     }
 
     static class GeolocationPermissionsData {
@@ -1304,6 +1308,10 @@
 
                         case TOUCH_UP:
                             TouchUpData touchUpData = (TouchUpData) msg.obj;
+                            if (touchUpData.mNativeLayer != 0) {
+                                nativeScrollLayer(touchUpData.mNativeLayer,
+                                        touchUpData.mNativeLayerRect);
+                            }
                             nativeTouchUp(touchUpData.mMoveGeneration,
                                     touchUpData.mFrame, touchUpData.mNode,
                                     touchUpData.mX, touchUpData.mY);
@@ -1318,6 +1326,10 @@
                                 xArray[c] = ted.mPoints[c].x;
                                 yArray[c] = ted.mPoints[c].y;
                             }
+                            if (ted.mNativeLayer != 0) {
+                                nativeScrollLayer(ted.mNativeLayer,
+                                        ted.mNativeLayerRect);
+                            }
                             Message.obtain(
                                     mWebView.mPrivateHandler,
                                     WebView.PREVENT_TOUCH_ID,
@@ -2702,4 +2714,5 @@
             int slop);
 
    private native void nativeAutoFillForm(int queryId);
+   private native void nativeScrollLayer(int layer, Rect rect);
 }
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index a84df16..0383b5c 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -37,14 +37,46 @@
  *
  * <p>See the <a href="{@docRoot}resources/tutorials/views/hello-gridview.html">Grid
  * View tutorial</a>.</p>
+ * 
+ * @attr ref android.R.styleable#GridView_horizontalSpacing
+ * @attr ref android.R.styleable#GridView_verticalSpacing
+ * @attr ref android.R.styleable#GridView_stretchMode
+ * @attr ref android.R.styleable#GridView_columnWidth
+ * @attr ref android.R.styleable#GridView_numColumns
+ * @attr ref android.R.styleable#GridView_gravity
  */
 @RemoteView
 public class GridView extends AbsListView {
+    /**
+     * Disables stretching.
+     * 
+     * @see #setStretchMode(int) 
+     */
     public static final int NO_STRETCH = 0;
+    /**
+     * Stretches the spacing between columns.
+     * 
+     * @see #setStretchMode(int) 
+     */
     public static final int STRETCH_SPACING = 1;
+    /**
+     * Stretches columns.
+     * 
+     * @see #setStretchMode(int) 
+     */
     public static final int STRETCH_COLUMN_WIDTH = 2;
+    /**
+     * Stretches the spacing between columns. The spacing is uniform.
+     * 
+     * @see #setStretchMode(int) 
+     */
     public static final int STRETCH_SPACING_UNIFORM = 3;
-    
+
+    /**
+     * Creates as many columns as can fit on screen.
+     * 
+     * @see #setNumColumns(int) 
+     */
     public static final int AUTO_FIT = -1;
 
     private int mNumColumns = AUTO_FIT;
diff --git a/core/jni/android_bluetooth_BluetoothAudioGateway.cpp b/core/jni/android_bluetooth_BluetoothAudioGateway.cpp
index bf23650..acf858a 100755
--- a/core/jni/android_bluetooth_BluetoothAudioGateway.cpp
+++ b/core/jni/android_bluetooth_BluetoothAudioGateway.cpp
@@ -89,40 +89,40 @@
 #endif
 
 static void classInitNative(JNIEnv* env, jclass clazz) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
 
     /* in */
     field_mNativeData = get_field(env, clazz, "mNativeData", "I");
-    field_mHandsfreeAgRfcommChannel = 
+    field_mHandsfreeAgRfcommChannel =
         get_field(env, clazz, "mHandsfreeAgRfcommChannel", "I");
-    field_mHeadsetAgRfcommChannel = 
+    field_mHeadsetAgRfcommChannel =
         get_field(env, clazz, "mHeadsetAgRfcommChannel", "I");
 
     /* out */
-    field_mConnectingHeadsetAddress = 
-        get_field(env, clazz, 
+    field_mConnectingHeadsetAddress =
+        get_field(env, clazz,
                   "mConnectingHeadsetAddress", "Ljava/lang/String;");
-    field_mConnectingHeadsetRfcommChannel = 
+    field_mConnectingHeadsetRfcommChannel =
         get_field(env, clazz, "mConnectingHeadsetRfcommChannel", "I");
-    field_mConnectingHeadsetSocketFd = 
+    field_mConnectingHeadsetSocketFd =
         get_field(env, clazz, "mConnectingHeadsetSocketFd", "I");
 
-    field_mConnectingHandsfreeAddress = 
-        get_field(env, clazz, 
+    field_mConnectingHandsfreeAddress =
+        get_field(env, clazz,
                   "mConnectingHandsfreeAddress", "Ljava/lang/String;");
-    field_mConnectingHandsfreeRfcommChannel = 
+    field_mConnectingHandsfreeRfcommChannel =
         get_field(env, clazz, "mConnectingHandsfreeRfcommChannel", "I");
-    field_mConnectingHandsfreeSocketFd = 
+    field_mConnectingHandsfreeSocketFd =
         get_field(env, clazz, "mConnectingHandsfreeSocketFd", "I");
 
-    field_mTimeoutRemainingMs = 
+    field_mTimeoutRemainingMs =
         get_field(env, clazz, "mTimeoutRemainingMs", "I");
 #endif
 }
 
 static void initializeNativeDataNative(JNIEnv* env, jobject object) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t));
     if (NULL == nat) {
@@ -150,7 +150,7 @@
 }
 
 static void cleanupNativeDataNative(JNIEnv* env, jobject object) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = get_native_data(env, object);
     if (nat) {
@@ -165,7 +165,7 @@
 static int set_nb(int sk, bool nb) {
     int flags = fcntl(sk, F_GETFL);
     if (flags < 0) {
-        LOGE("Can't get socket flags with fcntl(): %s (%d)", 
+        LOGE("Can't get socket flags with fcntl(): %s (%d)",
              strerror(errno), errno);
         close(sk);
         return -1;
@@ -255,7 +255,7 @@
 
 static jboolean waitForHandsfreeConnectNative(JNIEnv* env, jobject object,
                                               jint timeout_ms) {
-//    LOGV(__FUNCTION__);
+//    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
 
     env->SetIntField(object, field_mTimeoutRemainingMs, timeout_ms);
@@ -264,11 +264,11 @@
     native_data_t *nat = get_native_data(env, object);
 #if USE_ACCEPT_DIRECTLY
     if (nat->hf_ag_rfcomm_channel > 0) {
-        LOGI("Setting HF AG server socket to RFCOMM port %d!", 
+        LOGI("Setting HF AG server socket to RFCOMM port %d!",
              nat->hf_ag_rfcomm_channel);
         struct timeval tv;
         int len = sizeof(tv);
-        if (getsockopt(nat->hf_ag_rfcomm_channel, 
+        if (getsockopt(nat->hf_ag_rfcomm_channel,
                        SOL_SOCKET, SO_RCVTIMEO, &tv, &len) < 0) {
             LOGE("getsockopt(%d, SOL_SOCKET, SO_RCVTIMEO): %s (%d)",
                  nat->hf_ag_rfcomm_channel,
@@ -276,12 +276,12 @@
                  errno);
             return JNI_FALSE;
         }
-        LOGI("Current HF AG server socket RCVTIMEO is (%d(s), %d(us))!", 
+        LOGI("Current HF AG server socket RCVTIMEO is (%d(s), %d(us))!",
              (int)tv.tv_sec, (int)tv.tv_usec);
         if (timeout_ms >= 0) {
             tv.tv_sec = timeout_ms / 1000;
             tv.tv_usec = 1000 * (timeout_ms % 1000);
-            if (setsockopt(nat->hf_ag_rfcomm_channel, 
+            if (setsockopt(nat->hf_ag_rfcomm_channel,
                            SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
                 LOGE("setsockopt(%d, SOL_SOCKET, SO_RCVTIMEO): %s (%d)",
                      nat->hf_ag_rfcomm_channel,
@@ -289,11 +289,11 @@
                      errno);
                 return JNI_FALSE;
             }
-            LOGI("Changed HF AG server socket RCVTIMEO to (%d(s), %d(us))!", 
+            LOGI("Changed HF AG server socket RCVTIMEO to (%d(s), %d(us))!",
                  (int)tv.tv_sec, (int)tv.tv_usec);
         }
 
-        if (!do_accept(env, object, nat->hf_ag_rfcomm_sock, 
+        if (!do_accept(env, object, nat->hf_ag_rfcomm_sock,
                        field_mConnectingHandsfreeSocketFd,
                        field_mConnectingHandsfreeAddress,
                        field_mConnectingHandsfreeRfcommChannel))
@@ -309,13 +309,13 @@
     FD_ZERO(&rset);
     int cnt = 0;
     if (nat->hf_ag_rfcomm_channel > 0) {
-        LOGI("Setting HF AG server socket to RFCOMM port %d!", 
+        LOGI("Setting HF AG server socket to RFCOMM port %d!",
              nat->hf_ag_rfcomm_channel);
         cnt++;
         FD_SET(nat->hf_ag_rfcomm_sock, &rset);
     }
     if (nat->hs_ag_rfcomm_channel > 0) {
-        LOGI("Setting HS AG server socket to RFCOMM port %d!", 
+        LOGI("Setting HS AG server socket to RFCOMM port %d!",
              nat->hs_ag_rfcomm_channel);
         cnt++;
         FD_SET(nat->hs_ag_rfcomm_sock, &rset);
@@ -330,7 +330,7 @@
         to.tv_sec = timeout_ms / 1000;
         to.tv_usec = 1000 * (timeout_ms % 1000);
     }
-    n = select(MAX(nat->hf_ag_rfcomm_sock, 
+    n = select(MAX(nat->hf_ag_rfcomm_sock,
                        nat->hs_ag_rfcomm_sock) + 1,
                    &rset,
                    NULL,
@@ -354,7 +354,7 @@
         return JNI_FALSE;
     }
 
-    n = on_accept_set_fields(env, object, 
+    n = on_accept_set_fields(env, object,
                              &rset, nat->hf_ag_rfcomm_sock,
                              field_mConnectingHandsfreeSocketFd,
                              field_mConnectingHandsfreeAddress,
@@ -371,7 +371,7 @@
     struct pollfd fds[2];
     int cnt = 0;
     if (nat->hf_ag_rfcomm_channel > 0) {
-//        LOGI("Setting HF AG server socket %d to RFCOMM port %d!", 
+//        LOGI("Setting HF AG server socket %d to RFCOMM port %d!",
 //             nat->hf_ag_rfcomm_sock,
 //             nat->hf_ag_rfcomm_channel);
         fds[cnt].fd = nat->hf_ag_rfcomm_sock;
@@ -379,7 +379,7 @@
         cnt++;
     }
     if (nat->hs_ag_rfcomm_channel > 0) {
-//        LOGI("Setting HS AG server socket %d to RFCOMM port %d!", 
+//        LOGI("Setting HS AG server socket %d to RFCOMM port %d!",
 //             nat->hs_ag_rfcomm_sock,
 //             nat->hs_ag_rfcomm_channel);
         fds[cnt].fd = nat->hs_ag_rfcomm_sock;
@@ -411,7 +411,7 @@
         if (fds[cnt].fd == nat->hf_ag_rfcomm_sock) {
             if (fds[cnt].revents & (POLLIN | POLLPRI | POLLOUT)) {
                 LOGI("Accepting HF connection.\n");
-                err += do_accept(env, object, fds[cnt].fd, 
+                err += do_accept(env, object, fds[cnt].fd,
                                field_mConnectingHandsfreeSocketFd,
                                field_mConnectingHandsfreeAddress,
                                field_mConnectingHandsfreeRfcommChannel);
@@ -421,7 +421,7 @@
         else if (fds[cnt].fd == nat->hs_ag_rfcomm_sock) {
             if (fds[cnt].revents & (POLLIN | POLLPRI | POLLOUT)) {
                 LOGI("Accepting HS connection.\n");
-                err += do_accept(env, object, fds[cnt].fd, 
+                err += do_accept(env, object, fds[cnt].fd,
                                field_mConnectingHeadsetSocketFd,
                                field_mConnectingHeadsetAddress,
                                field_mConnectingHeadsetRfcommChannel);
@@ -444,7 +444,7 @@
 }
 
 static jboolean setUpListeningSocketsNative(JNIEnv* env, jobject object) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = get_native_data(env, object);
 
@@ -509,7 +509,7 @@
     private native void tearDownListeningSocketsNative();
 */
 static void tearDownListeningSocketsNative(JNIEnv *env, jobject object) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = get_native_data(env, object);
 
diff --git a/core/jni/android_bluetooth_BluetoothSocket.cpp b/core/jni/android_bluetooth_BluetoothSocket.cpp
index 31ebf8c..b87f7c4 100644
--- a/core/jni/android_bluetooth_BluetoothSocket.cpp
+++ b/core/jni/android_bluetooth_BluetoothSocket.cpp
@@ -66,7 +66,7 @@
 
 static void initSocketFromFdNative(JNIEnv *env, jobject obj, jint fd) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 
     struct asocket *s = asocket_init(fd);
 
@@ -85,7 +85,7 @@
 
 static void initSocketNative(JNIEnv *env, jobject obj) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 
     int fd;
     int lm = 0;
@@ -161,7 +161,7 @@
 
 static void connectNative(JNIEnv *env, jobject obj) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 
     int ret;
     jint type;
@@ -240,7 +240,7 @@
 /* Returns errno instead of throwing, so java can check errno */
 static int bindListenNative(JNIEnv *env, jobject obj) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 
     jint type;
     socklen_t addr_sz;
@@ -307,7 +307,7 @@
 
 static jobject acceptNative(JNIEnv *env, jobject obj, int timeout) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 
     int fd;
     jint type;
@@ -380,7 +380,7 @@
 
 static jint availableNative(JNIEnv *env, jobject obj) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 
     int available;
     struct asocket *s = get_socketData(env, obj);
@@ -403,7 +403,7 @@
 static jint readNative(JNIEnv *env, jobject obj, jbyteArray jb, jint offset,
         jint length) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 
     int ret;
     jbyte *b;
@@ -446,7 +446,7 @@
 static jint writeNative(JNIEnv *env, jobject obj, jbyteArray jb, jint offset,
         jint length) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 
     int ret;
     jbyte *b;
@@ -488,7 +488,7 @@
 
 static void abortNative(JNIEnv *env, jobject obj) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     struct asocket *s = get_socketData(env, obj);
 
     if (!s)
@@ -504,7 +504,7 @@
 
 static void destroyNative(JNIEnv *env, jobject obj) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     struct asocket *s = get_socketData(env, obj);
     int fd = s->fd;
 
diff --git a/core/jni/android_bluetooth_HeadsetBase.cpp b/core/jni/android_bluetooth_HeadsetBase.cpp
index 4e9fbaf..bbf1ae5 100644
--- a/core/jni/android_bluetooth_HeadsetBase.cpp
+++ b/core/jni/android_bluetooth_HeadsetBase.cpp
@@ -180,7 +180,7 @@
 #endif
 
 static void classInitNative(JNIEnv* env, jclass clazz) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     field_mNativeData = get_field(env, clazz, "mNativeData", "I");
     field_mAddress = get_field(env, clazz, "mAddress", "Ljava/lang/String;");
@@ -191,7 +191,7 @@
 
 static void initializeNativeDataNative(JNIEnv* env, jobject object,
                                        jint socketFd) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t));
     if (NULL == nat) {
@@ -213,7 +213,7 @@
 }
 
 static void cleanupNativeDataNative(JNIEnv* env, jobject object) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat =
         (native_data_t *)env->GetIntField(object, field_mNativeData);
@@ -226,7 +226,7 @@
 
 static jboolean connectNative(JNIEnv *env, jobject obj)
 {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     int lm;
     struct sockaddr_rc addr;
@@ -278,7 +278,7 @@
 }
 
 static jint connectAsyncNative(JNIEnv *env, jobject obj) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     struct sockaddr_rc addr;
     native_data_t *nat = get_native_data(env, obj);
@@ -357,7 +357,7 @@
 
 static jint waitForAsyncConnectNative(JNIEnv *env, jobject obj,
                                            jint timeout_ms) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     struct sockaddr_rc addr;
     native_data_t *nat = get_native_data(env, obj);
@@ -463,7 +463,7 @@
 }
 
 static void disconnectNative(JNIEnv *env, jobject obj) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = get_native_data(env, obj);
     if (nat->rfcomm_sock >= 0) {
diff --git a/core/jni/android_server_BluetoothA2dpService.cpp b/core/jni/android_server_BluetoothA2dpService.cpp
index 8c795af..1851ad6 100644
--- a/core/jni/android_server_BluetoothA2dpService.cpp
+++ b/core/jni/android_server_BluetoothA2dpService.cpp
@@ -61,7 +61,7 @@
  * Return false if dbus is down, or another serious error (out of memory)
 */
 static bool initNative(JNIEnv* env, jobject object) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     nat = (native_data_t *)calloc(1, sizeof(native_data_t));
     if (NULL == nat) {
@@ -88,7 +88,7 @@
 
 static void cleanupNative(JNIEnv* env, jobject object) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     if (nat) {
         dbus_connection_close(nat->conn);
         env->DeleteGlobalRef(nat->me);
@@ -101,7 +101,7 @@
 static jobjectArray getSinkPropertiesNative(JNIEnv *env, jobject object,
                                             jstring path) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     if (nat) {
         DBusMessage *msg, *reply;
         DBusError err;
@@ -132,7 +132,7 @@
 
 static jboolean connectSinkNative(JNIEnv *env, jobject object, jstring path) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     if (nat) {
         const char *c_path = env->GetStringUTFChars(path, NULL);
         int len = env->GetStringLength(path) + 1;
@@ -153,7 +153,7 @@
 static jboolean disconnectSinkNative(JNIEnv *env, jobject object,
                                      jstring path) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     if (nat) {
         const char *c_path = env->GetStringUTFChars(path, NULL);
 
@@ -171,7 +171,7 @@
 static jboolean suspendSinkNative(JNIEnv *env, jobject object,
                                      jstring path) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     if (nat) {
         const char *c_path = env->GetStringUTFChars(path, NULL);
         bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,
@@ -187,7 +187,7 @@
 static jboolean resumeSinkNative(JNIEnv *env, jobject object,
                                      jstring path) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     if (nat) {
         const char *c_path = env->GetStringUTFChars(path, NULL);
         bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,
@@ -203,7 +203,7 @@
 static jboolean avrcpVolumeUpNative(JNIEnv *env, jobject object,
                                      jstring path) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     if (nat) {
         const char *c_path = env->GetStringUTFChars(path, NULL);
         bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,
@@ -219,7 +219,7 @@
 static jboolean avrcpVolumeDownNative(JNIEnv *env, jobject object,
                                      jstring path) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     if (nat) {
         const char *c_path = env->GetStringUTFChars(path, NULL);
         bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,
@@ -278,7 +278,7 @@
 }
 
 void onConnectSinkResult(DBusMessage *msg, void *user, void *n) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 
     native_data_t *nat = (native_data_t *)n;
     const char *path = (const char *)user;
diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
index fd12c2d7..afaade8 100644
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ b/core/jni/android_server_BluetoothEventLoop.cpp
@@ -88,7 +88,7 @@
 
 #endif
 static void classInitNative(JNIEnv* env, jclass clazz) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 
 #ifdef HAVE_BLUETOOTH
     method_onPropertyChanged = env->GetMethodID(clazz, "onPropertyChanged",
@@ -147,7 +147,7 @@
 }
 
 static void initializeNativeDataNative(JNIEnv* env, jobject object) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t));
     if (NULL == nat) {
@@ -175,7 +175,7 @@
 }
 
 static void cleanupNativeDataNative(JNIEnv* env, jobject object) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat =
             (native_data_t *)env->GetIntField(object, field_mNativeData);
@@ -216,7 +216,7 @@
 }
 
 static jboolean setUpEventLoop(native_data_t *nat) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 
     if (nat != NULL && nat->conn != NULL) {
         dbus_threads_init_default();
@@ -395,7 +395,7 @@
 }
 
 static void tearDownEventLoop(native_data_t *nat) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     if (nat != NULL && nat->conn != NULL) {
 
         DBusMessage *msg, *reply;
@@ -1229,7 +1229,7 @@
 #ifdef HAVE_BLUETOOTH
 
 void onCreatePairedDeviceResult(DBusMessage *msg, void *user, void *n) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 
     native_data_t *nat = (native_data_t *)n;
     const char *address = (const char *)user;
@@ -1298,7 +1298,7 @@
 }
 
 void onCreateDeviceResult(DBusMessage *msg, void *user, void *n) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 
     native_data_t *nat = (native_data_t *)n;
     const char *address= (const char *)user;
@@ -1328,7 +1328,7 @@
 }
 
 void onDiscoverServicesResult(DBusMessage *msg, void *user, void *n) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 
     native_data_t *nat = (native_data_t *)n;
     const char *path = (const char *)user;
@@ -1354,7 +1354,7 @@
 }
 
 void onGetDeviceServiceChannelResult(DBusMessage *msg, void *user, void *n) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 
     const char *address = (const char *) user;
     native_data_t *nat = (native_data_t *) n;
@@ -1387,7 +1387,7 @@
 }
 
 void onInputDeviceConnectionResult(DBusMessage *msg, void *user, void *n) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 
     native_data_t *nat = (native_data_t *)n;
     const char *path = (const char *)user;
@@ -1426,7 +1426,7 @@
 }
 
 void onPanDeviceConnectionResult(DBusMessage *msg, void *user, void *n) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 
     native_data_t *nat = (native_data_t *)n;
     const char *path = (const char *)user;
diff --git a/core/jni/android_server_BluetoothService.cpp b/core/jni/android_server_BluetoothService.cpp
index bf0504f..158e475 100644
--- a/core/jni/android_server_BluetoothService.cpp
+++ b/core/jni/android_server_BluetoothService.cpp
@@ -1,16 +1,16 @@
 /*
 ** Copyright 2006, The Android Open Source Project
 **
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
 **
-**     http://www.apache.org/licenses/LICENSE-2.0 
+**     http://www.apache.org/licenses/LICENSE-2.0
 **
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
 
@@ -93,7 +93,7 @@
 #endif
 
 static void classInitNative(JNIEnv* env, jclass clazz) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     field_mNativeData = get_field(env, clazz, "mNativeData", "I");
     field_mEventLoop = get_field(env, clazz, "mEventLoop",
@@ -105,7 +105,7 @@
  * Return false if dbus is down, or another serious error (out of memory)
 */
 static bool initializeNativeDataNative(JNIEnv* env, jobject object) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = (native_data_t *)calloc(1, sizeof(native_data_t));
     if (NULL == nat) {
@@ -144,7 +144,7 @@
 
 // This function is called when the adapter is enabled.
 static jboolean setupNativeDataNative(JNIEnv* env, jobject object) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat =
         (native_data_t *)env->GetIntField(object, field_mNativeData);
@@ -167,7 +167,7 @@
 }
 
 static jboolean tearDownNativeDataNative(JNIEnv *env, jobject object) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat =
                (native_data_t *)env->GetIntField(object, field_mNativeData);
@@ -181,7 +181,7 @@
 }
 
 static void cleanupNativeDataNative(JNIEnv* env, jobject object) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat =
         (native_data_t *)env->GetIntField(object, field_mNativeData);
@@ -193,7 +193,7 @@
 }
 
 static jstring getAdapterPathNative(JNIEnv *env, jobject object) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = get_native_data(env, object);
     if (nat) {
@@ -205,7 +205,7 @@
 
 
 static jboolean startDiscoveryNative(JNIEnv *env, jobject object) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     DBusMessage *msg = NULL;
     DBusMessage *reply = NULL;
@@ -251,7 +251,7 @@
 }
 
 static void stopDiscoveryNative(JNIEnv *env, jobject object) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     DBusMessage *msg = NULL;
     DBusMessage *reply = NULL;
@@ -297,7 +297,7 @@
 }
 
 static jbyteArray readAdapterOutOfBandDataNative(JNIEnv *env, jobject object) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = get_native_data(env, object);
     DBusError err;
@@ -338,7 +338,7 @@
 
 static jboolean createPairedDeviceNative(JNIEnv *env, jobject object,
                                          jstring address, jint timeout_ms) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = get_native_data(env, object);
     jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
@@ -374,7 +374,7 @@
 
 static jboolean createPairedDeviceOutOfBandNative(JNIEnv *env, jobject object,
                                                 jstring address, jint timeout_ms) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = get_native_data(env, object);
     jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
@@ -411,7 +411,7 @@
                                           jstring path,
                                           jstring pattern, jint attr_id) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     native_data_t *nat = get_native_data(env, object);
     jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
     struct event_loop_native_data_t *eventLoopNat =
@@ -437,7 +437,7 @@
 
 static jboolean cancelDeviceCreationNative(JNIEnv *env, jobject object,
                                            jstring address) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     jboolean result = JNI_FALSE;
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = get_native_data(env, object);
@@ -469,7 +469,7 @@
 }
 
 static jboolean removeDeviceNative(JNIEnv *env, jobject object, jstring object_path) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = get_native_data(env, object);
     if (nat) {
@@ -492,7 +492,7 @@
 
 static jint enableNative(JNIEnv *env, jobject object) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     return bt_enable();
 #endif
     return -1;
@@ -500,7 +500,7 @@
 
 static jint disableNative(JNIEnv *env, jobject object) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     return bt_disable();
 #endif
     return -1;
@@ -508,7 +508,7 @@
 
 static jint isEnabledNative(JNIEnv *env, jobject object) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     return bt_is_enabled();
 #endif
     return -1;
@@ -518,7 +518,7 @@
                                              jstring address, bool confirm,
                                              int nativeData) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     native_data_t *nat = get_native_data(env, object);
     if (nat) {
         DBusMessage *msg = (DBusMessage *)nativeData;
@@ -549,7 +549,7 @@
 static jboolean setPasskeyNative(JNIEnv *env, jobject object, jstring address,
                          int passkey, int nativeData) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     native_data_t *nat = get_native_data(env, object);
     if (nat) {
         DBusMessage *msg = (DBusMessage *)nativeData;
@@ -576,7 +576,7 @@
 static jboolean setRemoteOutOfBandDataNative(JNIEnv *env, jobject object, jstring address,
                          jbyteArray hash, jbyteArray randomizer, int nativeData) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     native_data_t *nat = get_native_data(env, object);
     if (nat) {
         DBusMessage *msg = (DBusMessage *)nativeData;
@@ -610,7 +610,7 @@
 static jboolean setPinNative(JNIEnv *env, jobject object, jstring address,
                          jstring pin, int nativeData) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     native_data_t *nat = get_native_data(env, object);
     if (nat) {
         DBusMessage *msg = (DBusMessage *)nativeData;
@@ -640,7 +640,7 @@
 static jboolean cancelPairingUserInputNative(JNIEnv *env, jobject object,
                                             jstring address, int nativeData) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     native_data_t *nat = get_native_data(env, object);
     if (nat) {
         DBusMessage *msg = (DBusMessage *)nativeData;
@@ -666,7 +666,7 @@
                                                     jstring path)
 {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     native_data_t *nat = get_native_data(env, object);
     if (nat) {
         DBusMessage *msg, *reply;
@@ -705,7 +705,7 @@
 
 static jobjectArray getAdapterPropertiesNative(JNIEnv *env, jobject object) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     native_data_t *nat = get_native_data(env, object);
     if (nat) {
         DBusMessage *msg, *reply;
@@ -741,7 +741,7 @@
 static jboolean setAdapterPropertyNative(JNIEnv *env, jobject object, jstring key,
                                          void *value, jint type) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     native_data_t *nat = get_native_data(env, object);
     if (nat) {
         DBusMessage *msg;
@@ -808,7 +808,7 @@
 static jboolean setDevicePropertyNative(JNIEnv *env, jobject object, jstring path,
                                                jstring key, void *value, jint type) {
 #ifdef HAVE_BLUETOOTH
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
     native_data_t *nat = get_native_data(env, object);
     if (nat) {
         DBusMessage *reply, *msg;
@@ -863,7 +863,7 @@
 
 static jboolean createDeviceNative(JNIEnv *env, jobject object,
                                                 jstring address) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = get_native_data(env, object);
     jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
@@ -894,7 +894,7 @@
 
 static jboolean discoverServicesNative(JNIEnv *env, jobject object,
                                                jstring path, jstring pattern) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = get_native_data(env, object);
     jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
@@ -955,7 +955,7 @@
 
 static jintArray addReservedServiceRecordsNative(JNIEnv *env, jobject object,
                                                 jintArray uuids) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     DBusMessage *reply = NULL;
 
@@ -979,7 +979,7 @@
 
 static jboolean removeReservedServiceRecordsNative(JNIEnv *env, jobject object,
                                                    jintArray handles) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = get_native_data(env, object);
     jint *values = env->GetIntArrayElements(handles, NULL);
@@ -1002,7 +1002,7 @@
 
 static jint addRfcommServiceRecordNative(JNIEnv *env, jobject object,
         jstring name, jlong uuidMsb, jlong uuidLsb, jshort channel) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = get_native_data(env, object);
     if (nat) {
@@ -1027,7 +1027,7 @@
 }
 
 static jboolean removeServiceRecordNative(JNIEnv *env, jobject object, jint handle) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = get_native_data(env, object);
     if (nat) {
@@ -1045,7 +1045,7 @@
 
 static jboolean setLinkTimeoutNative(JNIEnv *env, jobject object, jstring object_path,
                                      jint num_slots) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = get_native_data(env, object);
     if (nat) {
@@ -1064,7 +1064,7 @@
 }
 
 static jboolean connectInputDeviceNative(JNIEnv *env, jobject object, jstring path) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = get_native_data(env, object);
     jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
@@ -1092,7 +1092,7 @@
 
 static jboolean disconnectInputDeviceNative(JNIEnv *env, jobject object,
                                      jstring path) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = get_native_data(env, object);
     jobject eventLoop = env->GetObjectField(object, field_mEventLoop);
@@ -1120,7 +1120,7 @@
 
 static jboolean setBluetoothTetheringNative(JNIEnv *env, jobject object, jboolean value,
                                             jstring src_role, jstring bridge) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     native_data_t *nat = get_native_data(env, object);
     if (nat) {
@@ -1155,7 +1155,7 @@
 
 static jboolean connectPanDeviceNative(JNIEnv *env, jobject object, jstring path,
                                        jstring dstRole) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     LOGE("connectPanDeviceNative");
     native_data_t *nat = get_native_data(env, object);
@@ -1187,7 +1187,7 @@
 
 static jboolean disconnectPanDeviceNative(JNIEnv *env, jobject object,
                                      jstring path) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     LOGE("disconnectPanDeviceNative");
     native_data_t *nat = get_native_data(env, object);
@@ -1217,7 +1217,7 @@
 static jboolean disconnectPanServerDeviceNative(JNIEnv *env, jobject object,
                                                 jstring path, jstring address,
                                                 jstring iface) {
-    LOGV(__FUNCTION__);
+    LOGV("%s", __FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     LOGE("disconnectPanServerDeviceNative");
     native_data_t *nat = get_native_data(env, object);
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 6f37dc0..d9eccd6 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2256,18 +2256,29 @@
         <attr name="unselectedAlpha" format="float" />
     </declare-styleable>
     <declare-styleable name="GridView">
+        <!-- Defines the default horizontal spacing between columns. -->
         <attr name="horizontalSpacing" format="dimension" />
+        <!-- Defines the default vertical spacing between rows. -->
         <attr name="verticalSpacing" format="dimension" />
+        <!-- Defines how columns should stretch to fill the available empty space, if any. -->
         <attr name="stretchMode">
+            <!-- Stretching is disabled. -->
             <enum name="none" value="0"/>
+            <!-- The spacing between each column is stretched. -->
             <enum name="spacingWidth" value="1" />
+            <!-- Each column is stretched equally. -->
             <enum name="columnWidth" value="2" />
+            <!-- The spacing between each column is uniformly stretched.. -->
             <enum name="spacingWidthUniform" value="3" />
         </attr>
+        <!-- Specifies the fixed width for each column. -->
         <attr name="columnWidth" format="dimension" />
+        <!-- Defines how many columns to show. -->
         <attr name="numColumns" format="integer" min="0">
+            <!-- Display as many columns as possible to fill the available space. -->
             <enum name="auto_fit" value="-1" />
         </attr>
+        <!-- Specifies the gravity within each cell. -->
         <attr name="gravity" />
     </declare-styleable>
     <declare-styleable name="ImageSwitcher">
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java b/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
index 96b028a..672f252 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothStressTest.java
@@ -250,8 +250,8 @@
 
         for (int i = 0; i < iterations; i++) {
             mTestUtils.writeOutput("connectInput iteration " + (i + 1) + " of " + iterations);
-            mTestUtils.connectInput(adapter, device);
-            mTestUtils.disconnectInput(adapter, device);
+            mTestUtils.connectProfile(adapter, device, BluetoothProfile.INPUT_DEVICE);
+            mTestUtils.disconnectProfile(adapter, device, BluetoothProfile.INPUT_DEVICE);
         }
 
         mTestUtils.unpair(adapter, device);
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
index effed76..35210e5 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
@@ -238,6 +238,9 @@
                 case BluetoothProfile.HEADSET:
                     mConnectionAction = BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED;
                     break;
+                case BluetoothProfile.INPUT_DEVICE:
+                    mConnectionAction = BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED;
+                    break;
                 default:
                     mConnectionAction = null;
             }
@@ -270,47 +273,6 @@
         }
     }
 
-    private class ConnectInputReceiver extends FlagReceiver {
-        private static final int STATE_DISCONNECTED_FLAG = 1;
-        private static final int STATE_CONNECTING_FLAG = 1 << 1;
-        private static final int STATE_CONNECTED_FLAG = 1 << 2;
-        private static final int STATE_DISCONNECTING_FLAG = 1 << 3;
-
-        private BluetoothDevice mDevice;
-
-        public ConnectInputReceiver(BluetoothDevice device, int expectedFlags) {
-            super(expectedFlags);
-
-            mDevice = device;
-        }
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (!mDevice.equals(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE))) {
-                return;
-            }
-
-            if (BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED.equals(intent.getAction())) {
-                int state = intent.getIntExtra(BluetoothInputDevice.EXTRA_INPUT_DEVICE_STATE, -1);
-                assertNotSame(-1, state);
-                switch (state) {
-                    case BluetoothInputDevice.STATE_DISCONNECTED:
-                        setFiredFlag(STATE_DISCONNECTED_FLAG);
-                        break;
-                    case BluetoothInputDevice.STATE_CONNECTING:
-                        setFiredFlag(STATE_CONNECTING_FLAG);
-                        break;
-                    case BluetoothInputDevice.STATE_CONNECTED:
-                        setFiredFlag(STATE_CONNECTED_FLAG);
-                        break;
-                    case BluetoothInputDevice.STATE_DISCONNECTING:
-                        setFiredFlag(STATE_DISCONNECTING_FLAG);
-                        break;
-                }
-            }
-        }
-    }
-
     private class ConnectPanReceiver extends FlagReceiver {
         private static final int STATE_DISCONNECTED_FLAG = 1;
         private static final int STATE_CONNECTING_FLAG = 1 << 1;
@@ -366,6 +328,9 @@
                     case BluetoothProfile.HEADSET:
                         mHeadset = (BluetoothHeadset) proxy;
                         break;
+                    case BluetoothProfile.INPUT_DEVICE:
+                        mInput = (BluetoothInputDevice) proxy;
+                        break;
                 }
             }
         }
@@ -379,6 +344,9 @@
                     case BluetoothProfile.HEADSET:
                         mHeadset = null;
                         break;
+                    case BluetoothProfile.INPUT_DEVICE:
+                        mInput = null;
+                        break;
                 }
             }
         }
@@ -393,6 +361,7 @@
     private Context mContext;
     private BluetoothA2dp mA2dp;
     private BluetoothHeadset mHeadset;
+    private BluetoothInputDevice mInput;
 
     /**
      * Creates a utility instance for testing Bluetooth.
@@ -1078,142 +1047,6 @@
     }
 
     /**
-     * Connects the local device with a remote HID device and checks to make sure that the profile
-     * is connected and that the correct actions were broadcast.
-     *
-     * @param adapter The BT adapter.
-     * @param device The remote device.
-     */
-    public void connectInput(BluetoothAdapter adapter, BluetoothDevice device) {
-        int mask = (ConnectInputReceiver.STATE_CONNECTING_FLAG
-                | ConnectInputReceiver.STATE_CONNECTED_FLAG);
-        long start = -1;
-
-        if (!adapter.isEnabled()) {
-            fail(String.format("connectInput() bluetooth not enabled: device=%s", device));
-        }
-
-        if (!adapter.getBondedDevices().contains(device)) {
-            fail(String.format("connectInput() device not paired: device=%s", device));
-        }
-
-        BluetoothInputDevice inputDevice = new BluetoothInputDevice(mContext);
-        assertNotNull(inputDevice);
-        ConnectInputReceiver receiver = getConnectInputReceiver(device, mask);
-
-        int state = inputDevice.getInputDeviceState(device);
-        switch (state) {
-            case BluetoothInputDevice.STATE_CONNECTED:
-                removeReceiver(receiver);
-                return;
-            case BluetoothInputDevice.STATE_CONNECTING:
-                mask = 0; // Don't check for received intents since we might have missed them.
-                break;
-            case BluetoothInputDevice.STATE_DISCONNECTED:
-            case BluetoothInputDevice.STATE_DISCONNECTING:
-                start = System.currentTimeMillis();
-                assertTrue(inputDevice.connectInputDevice(device));
-                break;
-            default:
-                removeReceiver(receiver);
-                fail(String.format("connectInput() invalid state: device=%s, state=%d", device,
-                        state));
-        }
-
-        long s = System.currentTimeMillis();
-        while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
-            state = inputDevice.getInputDeviceState(device);
-            if (state == BluetoothInputDevice.STATE_CONNECTED
-                    && (receiver.getFiredFlags() & mask) == mask) {
-                long finish = receiver.getCompletedTime();
-                if (start != -1 && finish != -1) {
-                    writeOutput(String.format("connectInput() completed in %d ms: device=%s",
-                            (finish - start), device));
-                } else {
-                    writeOutput(String.format("connectInput() completed: device=%s", device));
-                }
-                removeReceiver(receiver);
-                return;
-            }
-            sleep(POLL_TIME);
-        }
-
-        int firedFlags = receiver.getFiredFlags();
-        removeReceiver(receiver);
-        fail(String.format("connectInput() timeout: device=%s, state=%d (expected %d), "
-                + "flags=0x%x (expected 0x%s)", device, state, BluetoothInputDevice.STATE_CONNECTED,
-                firedFlags, mask));
-    }
-
-    /**
-     * Disconnects the local device with a remote HID device and checks to make sure that the
-     * profile is connected and that the correct actions were broadcast.
-     *
-     * @param adapter The BT adapter.
-     * @param device The remote device.
-     */
-    public void disconnectInput(BluetoothAdapter adapter, BluetoothDevice device) {
-        int mask = (ConnectInputReceiver.STATE_DISCONNECTING_FLAG
-                | ConnectInputReceiver.STATE_DISCONNECTED_FLAG);
-        long start = -1;
-
-        if (!adapter.isEnabled()) {
-            fail(String.format("disconnectInput() bluetooth not enabled: device=%s", device));
-        }
-
-        if (!adapter.getBondedDevices().contains(device)) {
-            fail(String.format("disconnectInput() device not paired: device=%s", device));
-        }
-
-        BluetoothInputDevice inputDevice = new BluetoothInputDevice(mContext);
-        assertNotNull(inputDevice);
-        ConnectInputReceiver receiver = getConnectInputReceiver(device, mask);
-
-        int state = inputDevice.getInputDeviceState(device);
-        switch (state) {
-            case BluetoothInputDevice.STATE_CONNECTED:
-            case BluetoothInputDevice.STATE_CONNECTING:
-                start = System.currentTimeMillis();
-                assertTrue(inputDevice.disconnectInputDevice(device));
-                break;
-            case BluetoothInputDevice.STATE_DISCONNECTED:
-                removeReceiver(receiver);
-                return;
-            case BluetoothInputDevice.STATE_DISCONNECTING:
-                mask = 0; // Don't check for received intents since we might have missed them.
-                break;
-            default:
-                removeReceiver(receiver);
-                fail(String.format("disconnectInput() invalid state: device=%s, state=%d", device,
-                        state));
-        }
-
-        long s = System.currentTimeMillis();
-        while (System.currentTimeMillis() - s < CONNECT_DISCONNECT_PROFILE_TIMEOUT) {
-            state = inputDevice.getInputDeviceState(device);
-            if (state == BluetoothInputDevice.STATE_DISCONNECTED
-                    && (receiver.getFiredFlags() & mask) == mask) {
-                long finish = receiver.getCompletedTime();
-                if (start != -1 && finish != -1) {
-                    writeOutput(String.format("disconnectInput() completed in %d ms: device=%s",
-                            (finish - start), device));
-                } else {
-                    writeOutput(String.format("disconnectInput() completed: device=%s", device));
-                }
-                removeReceiver(receiver);
-                return;
-            }
-            sleep(POLL_TIME);
-        }
-
-        int firedFlags = receiver.getFiredFlags();
-        removeReceiver(receiver);
-        fail(String.format("disconnectInput() timeout: device=%s, state=%d (expected %d), "
-                + "flags=0x%x (expected 0x%s)", device, state,
-                BluetoothInputDevice.STATE_DISCONNECTED, firedFlags, mask));
-    }
-
-    /**
      * Connects the PANU to a remote NAP and checks to make sure that the PANU is connected and that
      * the correct actions were broadcast.
      *
@@ -1478,21 +1311,14 @@
             int expectedFlags) {
         String[] actions = {
                 BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED,
-                BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED};
+                BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED,
+                BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED};
         ConnectProfileReceiver receiver = new ConnectProfileReceiver(device, profile,
                 expectedFlags);
         addReceiver(receiver, actions);
         return receiver;
     }
 
-    private ConnectInputReceiver getConnectInputReceiver(BluetoothDevice device,
-            int expectedFlags) {
-        String[] actions = {BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED};
-        ConnectInputReceiver receiver = new ConnectInputReceiver(device, expectedFlags);
-        addReceiver(receiver, actions);
-        return receiver;
-    }
-
     private ConnectPanReceiver getConnectPanReceiver(BluetoothDevice device, int role,
             int expectedFlags) {
         String[] actions = {BluetoothPan.ACTION_PAN_STATE_CHANGED};
@@ -1511,15 +1337,20 @@
         long s = System.currentTimeMillis();
         switch (profile) {
             case BluetoothProfile.A2DP:
-                while (mA2dp != null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
+                while (mA2dp == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
                     sleep(POLL_TIME);
                 }
                 return mA2dp;
             case BluetoothProfile.HEADSET:
-                while (mHeadset != null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
+                while (mHeadset == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
                     sleep(POLL_TIME);
                 }
                 return mHeadset;
+            case BluetoothProfile.INPUT_DEVICE:
+                while (mInput == null && System.currentTimeMillis() - s < CONNECT_PROXY_TIMEOUT) {
+                    sleep(POLL_TIME);
+                }
+                return mInput;
             default:
                 return null;
         }
diff --git a/media/java/android/media/videoeditor/Transition.java b/media/java/android/media/videoeditor/Transition.java
index 95f002c..3e8fe94 100755
--- a/media/java/android/media/videoeditor/Transition.java
+++ b/media/java/android/media/videoeditor/Transition.java
@@ -173,6 +173,7 @@
 
         mDurationMs = durationMs;
         invalidate();
+        mNativeHelper.setGeneratePreview(true);
     }
 
     /**
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index fd575fe..0100a17 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -298,6 +298,17 @@
         return INVALID_OPERATION;
     }
 
+    // It appears that if an invalid file descriptor is passed through
+    // binder calls, the server-side of the inter-process function call
+    // is skipped. As a result, the check at the server-side to catch
+    // the invalid file descritpor never gets invoked. This is to workaround
+    // this issue by checking the file descriptor first before passing
+    // it through binder call.
+    if (fd < 0) {
+        LOGE("Invalid file descriptor: %d", fd);
+        return BAD_VALUE;
+    }
+
     status_t ret = mMediaRecorder->setOutputFile(fd, offset, length);
     if (OK != ret) {
         LOGV("setOutputFile failed: %d", ret);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java
index eaaa798..988b229 100755
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java
@@ -17,7 +17,8 @@
 package com.android.mediaframeworktest;
 
 import com.android.mediaframeworktest.performance.MediaPlayerPerformance;
-
+/*Video Editor performance Test cases*/
+import com.android.mediaframeworktest.performance.VideoEditorPerformance;
 import junit.framework.TestSuite;
 
 import android.test.InstrumentationTestRunner;
@@ -26,7 +27,7 @@
 
 /**
  * Instrumentation Test Runner for all MediaPlayer tests.
- * 
+ *
  * Running all tests:
  *
  * adb shell am instrument \
@@ -40,6 +41,8 @@
   public TestSuite getAllTests() {
       TestSuite suite = new InstrumentationTestSuite(this);
       suite.addTestSuite(MediaPlayerPerformance.class);
+      /*Video Editor performance Test cases*/
+      suite.addTestSuite(VideoEditorPerformance.class);
       return suite;
   }
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaPlayerStressTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaPlayerStressTestRunner.java
index 5438061..0cd784c 100755
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaPlayerStressTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaPlayerStressTestRunner.java
@@ -19,6 +19,8 @@
 import android.test.InstrumentationTestRunner;
 import android.test.InstrumentationTestSuite;
 import com.android.mediaframeworktest.stress.MediaPlayerStressTest;
+/** Import for Video Editor Stress Test cases*/
+import com.android.mediaframeworktest.stress.VideoEditorStressTest;
 
 import junit.framework.TestSuite;
 
@@ -28,6 +30,8 @@
     public TestSuite getAllTests() {
         TestSuite suite = new InstrumentationTestSuite(this);
         suite.addTestSuite(MediaPlayerStressTest.class);
+        /** Video Editor Stress Test cases*/
+        suite.addTestSuite(VideoEditorStressTest.class);
         return suite;
     }
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorPreviewTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorPreviewTest.java
index bd0a838..9a7f4f2 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorPreviewTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorPreviewTest.java
@@ -95,7 +95,7 @@
     private boolean previewStop;
 
     /* Minimum waiting time for Semaphore to wait for release */
-    private final long minWaitingTime = 1000;
+    private final long minWaitingTime = 3000;
 
     // Declares the annotation for Preview Test Cases
     public @interface Preview {
@@ -473,8 +473,8 @@
         mVideoEditorHelper.checkProgressCBValues(progressValues);
         final SurfaceHolder surfaceHolder =
             MediaFrameworkTest.mSurfaceView.getHolder();
-
-        long waitingTime = minWaitingTime + 10000;
+        /* As transition takes more time buffer of 10 sec is added */
+        long waitingTime = minWaitingTime + 10000 + 10000;
 
         blockTillPreviewCompletes.acquire();
         try {
@@ -691,31 +691,34 @@
 
         long waitingTime = minWaitingTime + mVideoEditor.getDuration();
 
+
         blockTillPreviewCompletes.acquire();
+                    final String fileName = mVideoEditor.getPath() + "\test.3gp";
+                    final int height = MediaProperties.HEIGHT_480;
+                    final int bitrate = MediaProperties.BITRATE_512K;
+
+            try {
+                mVideoEditor.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);
+            }
 
         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();
@@ -725,10 +728,10 @@
                     blockTillPreviewCompletes.release();
                 }
             });
+
         } catch (Exception e) {
             blockTillPreviewCompletes.release();
         }
-
         blockTillPreviewCompletes.tryAcquire(waitingTime, TimeUnit.MILLISECONDS);
         mVideoEditor.stopPreview();
         assertTrue("Preview Failed to start", previewStart);
@@ -837,31 +840,7 @@
             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();
+        validatePreviewProgress(5000, -1, false, mVideoEditor.getDuration());
     }
 
     /**
@@ -1142,20 +1121,19 @@
         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 (" Render Preview Frame without generate", flagForException);
+        duration = mVideoEditor.getDuration() + 1000;
+        try {
+            mVideoEditor.renderPreviewFrame(surfaceHolder, duration,
+            overlayData1);
+        } catch ( IllegalArgumentException e) {
+            flagForException = true;
+        }
         assertTrue (" Preview time greater than duration", flagForException);
     }
-
 }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/VideoEditorPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/VideoEditorPerformance.java
new file mode 100644
index 0000000..4481d00
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/VideoEditorPerformance.java
@@ -0,0 +1,1086 @@
+/*
+ * 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.performance;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.Writer;
+
+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.TransitionCrossfade;
+import android.media.videoeditor.TransitionAlpha;
+import android.media.videoeditor.TransitionFadeBlack;
+import android.media.videoeditor.TransitionSliding;
+import android.media.videoeditor.VideoEditor;
+import android.os.Environment;
+import android.test.ActivityInstrumentationTestCase;
+import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener;
+import android.os.Environment;
+import android.os.SystemClock;
+import android.test.ActivityInstrumentationTestCase;
+import android.media.videoeditor.VideoEditor.ExportProgressListener;
+
+import android.util.Log;
+
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import android.test.suitebuilder.annotation.LargeTest;
+import com.android.mediaframeworktest.VideoEditorHelper;
+
+/**
+ * Junit / Instrumentation - performance measurement for media player and
+ * recorder
+ */
+public class VideoEditorPerformance extends
+    ActivityInstrumentationTestCase<MediaFrameworkTest> {
+
+    private final String TAG = "VideoEditorPerformance";
+
+    private final String PROJECT_LOCATION = VideoEditorHelper.PROJECT_LOCATION_COMMON;
+
+    private final String INPUT_FILE_PATH = VideoEditorHelper.INPUT_FILE_PATH_COMMON;
+
+    private final String VIDEOEDITOR_OUTPUT = PROJECT_LOCATION +
+        "VideoEditorPerformance.txt";
+
+    public VideoEditorPerformance() {
+        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+    }
+
+    private final String PROJECT_CLASS_NAME =
+        "android.media.videoeditor.VideoEditorImpl";
+    private VideoEditor mVideoEditor;
+    private VideoEditorHelper mVideoEditorHelper;
+
+    @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();
+    }
+
+    private void writeTimingInfo(String testCaseName, String[] information)
+        throws Exception {
+        File outFile = new File(VIDEOEDITOR_OUTPUT);
+        Writer output = new BufferedWriter(new FileWriter(outFile, true));
+        output.write(testCaseName + "\n\t");
+        for (int i = 0; i < information.length; i++) {
+            output.write(information[i]);
+        }
+        output.write("\n\n");
+        output.close();
+    }
+
+    private final int NUM_OF_ITERATIONS=20;
+
+    private float calculateTimeTaken(long beginTime, int numIterations)
+        throws Exception {
+        final long duration2 = SystemClock.uptimeMillis();
+        final long durationToCreateMediaItem = (duration2 - beginTime);
+        final float timeTaken1 = (float)durationToCreateMediaItem *
+            1.0f/(float)numIterations;
+        return (timeTaken1);
+    }
+
+    private void createVideoItems(MediaVideoItem[] mediaVideoItem,
+        String videoItemFileName, int renderingMode, int startTime, int endTime) throws Exception {
+        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
+            try {
+                mediaVideoItem[i] = new MediaVideoItem(mVideoEditor, "m" + i,
+                    videoItemFileName, renderingMode);
+                mediaVideoItem[i].setExtractBoundaries(startTime, endTime);
+            } catch (Exception e1) {
+                assertTrue(
+                    "Can not create an object of Video Item with file name = "
+                    + videoItemFileName + "------ID:m" + i + "       Issue = "
+                    + e1.toString(), false);
+            }
+        }
+    }
+
+    private void addVideoItems(MediaVideoItem[] mediaVideoItem) throws Exception {
+        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
+            try {
+                mVideoEditor.addMediaItem(mediaVideoItem[i]);
+            } catch (Exception e1) {
+                assertTrue(
+                    "Can not add an object of Video Item with ID:m" + i +
+                    "    Issue = " + e1.toString(), false);
+            }
+        }
+    }
+
+    private void removeVideoItems(MediaVideoItem[] mediaVideoItem) throws Exception {
+            for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
+            try {
+            mVideoEditor.removeMediaItem(mediaVideoItem[i].getId());
+            } catch (Exception e1) {
+                assertTrue(
+                    "Can not Remove an object of Video Item with ID:m" + i +
+                    "    Issue = " + e1.toString(), false);
+            }
+        }
+    }
+
+    private void createImageItems(MediaImageItem[] mIi,
+        String imageItemFileName, int renderingMode, int duration) throws Exception {
+        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
+            try {
+                mIi[i] = new MediaImageItem(mVideoEditor, "m" + i,
+                    imageItemFileName, duration, renderingMode);
+            } catch (Exception e1) {
+                assertTrue( " Cannot create Image Item", false);
+            }
+        }
+    }
+
+    private void addImageItems(MediaImageItem[] mIi) throws Exception {
+        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
+            try {
+                mVideoEditor.addMediaItem(mIi[i]);
+            } catch (Exception e1) {
+                assertTrue("Cannot add Image item", false);
+            }
+        }
+    }
+
+    private void removeImageItems(MediaImageItem[] mIi) throws Exception {
+            for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
+            try {
+            mVideoEditor.removeMediaItem(mIi[i].getId());
+            } catch (Exception e1) {
+                assertTrue("Cannot remove image item", false);
+            }
+        }
+    }
+    /**
+     * To test the performance of adding and removing the video media item
+     *
+     * @throws Exception
+     */
+    // TODO : remove PRF_001
+    @LargeTest
+    public void testPerformanceAddRemoveVideoItem() throws Exception {
+        final String videoItemFileName = INPUT_FILE_PATH +
+            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
+        final int videoItemStartTime = 0;
+        final int videoItemEndTime = 5000;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final String[] loggingInfo = new String[3];
+        final MediaVideoItem[] mediaVideoItem =
+            new MediaVideoItem[NUM_OF_ITERATIONS];
+        float timeTaken = 0.0f;
+        long startTime = 0;
+
+        /** Time Take for creation of Media Video Item */
+        startTime = SystemClock.uptimeMillis();
+        createVideoItems(mediaVideoItem, videoItemFileName, renderingMode,
+            videoItemStartTime, videoItemEndTime);
+
+        timeTaken = calculateTimeTaken (startTime, NUM_OF_ITERATIONS);
+        loggingInfo[0] = "Time taken to Create Media Video Item\t" +
+            timeTaken;
+
+        /** Time Take for Addition of Media Video Item */
+        startTime = SystemClock.uptimeMillis();
+        addVideoItems(mediaVideoItem);
+        timeTaken = calculateTimeTaken (startTime, NUM_OF_ITERATIONS);
+        loggingInfo[1] = "\n\tTime taken to Add  Media Video Item\t"
+            + timeTaken;
+
+        /** Time Take for Removal of Media Video Item */
+        startTime = SystemClock.uptimeMillis();
+        removeVideoItems(mediaVideoItem);
+        timeTaken = calculateTimeTaken (startTime, NUM_OF_ITERATIONS);
+        loggingInfo[2] = "\n\tTime taken to remove  Media Video Item\t"
+            + timeTaken;
+
+        writeTimingInfo("testPerformanceAddRemoveVideoItem (in mSec)", loggingInfo);
+    }
+
+    /**
+     * To test the performance of adding and removing the image media item
+     *
+     * @throws Exception
+     */
+    // TODO : remove PRF_002
+    @LargeTest
+    public void testPerformanceAddRemoveImageItem() throws Exception {
+        final String imageItemFileName = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
+        final int imageItemDuration = 0;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final String[] loggingInfo = new String[3];
+        final MediaImageItem[] mediaImageItem =
+            new MediaImageItem[NUM_OF_ITERATIONS];
+        float timeTaken = 0.0f;
+
+        long beginTime = SystemClock.uptimeMillis();
+        createImageItems(mediaImageItem, imageItemFileName, renderingMode,
+            imageItemDuration);
+        timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
+        loggingInfo[0] = "Time taken to Create  Media Image Item\t" +
+            timeTaken;
+
+        beginTime = SystemClock.uptimeMillis();
+        addImageItems(mediaImageItem);
+        timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
+        loggingInfo[1] = "\n\tTime taken to add  Media Image Item\t" +
+            timeTaken;
+
+        beginTime = SystemClock.uptimeMillis();
+        removeImageItems(mediaImageItem);
+        timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
+        loggingInfo[2] = "\n\tTime taken to remove  Media Image Item\t"
+            + timeTaken;
+
+        writeTimingInfo("testPerformanceAddRemoveImageItem (in mSec)",
+            loggingInfo);
+    }
+
+    /**
+     * To test the performance of adding and removing the transition
+     *
+     * @throws Exception
+     */
+    // TODO : remove PRF_003
+    @LargeTest
+    public void testPerformanceAddRemoveTransition() throws Exception {
+        final String videoItemFileName1 = INPUT_FILE_PATH +
+        "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
+        final int videoItemStartTime1 = 0;
+        final int videoItemEndTime1 = 20000;
+        final String videoItemFileName2 = INPUT_FILE_PATH
+            + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
+        final int videoItemStartTime2 = 0;
+        final int videoItemEndTime2 = 20000;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final int transitionDuration = 5000;
+        final int transitionBehavior = Transition.BEHAVIOR_MIDDLE_FAST;
+        final String[] loggingInfo = new String[3];
+        float timeTaken = 0.0f;
+
+        final MediaVideoItem[] mediaVideoItem =
+            new MediaVideoItem[(NUM_OF_ITERATIONS *10) + 1];
+
+        for (int i = 0; i < (NUM_OF_ITERATIONS *10); i+=2) {
+            try {
+                mediaVideoItem[i] = new MediaVideoItem(mVideoEditor, "m" + i,
+                    videoItemFileName1, renderingMode);
+                mediaVideoItem[i+1] = new MediaVideoItem(mVideoEditor,
+                    "m" + (i+1), videoItemFileName2, renderingMode);
+                mediaVideoItem[i].setExtractBoundaries(videoItemStartTime1,
+                    videoItemEndTime1);
+                mediaVideoItem[i+1].setExtractBoundaries(videoItemStartTime2,
+                    videoItemEndTime2);
+            } catch (Exception e1) {
+                assertTrue("Can not create Video Object Item with file name = "
+                    + e1.toString(), false);
+            }
+            mVideoEditor.addMediaItem(mediaVideoItem[i]);
+            mVideoEditor.addMediaItem(mediaVideoItem[i+1]);
+        }
+        mediaVideoItem[(NUM_OF_ITERATIONS *10)] = new MediaVideoItem(mVideoEditor,
+            "m" + (NUM_OF_ITERATIONS *10), videoItemFileName1, renderingMode);
+        mediaVideoItem[(NUM_OF_ITERATIONS *10)].setExtractBoundaries(
+            videoItemStartTime1, videoItemEndTime1);
+        mVideoEditor.addMediaItem(mediaVideoItem[(NUM_OF_ITERATIONS *10)]);
+        final TransitionCrossfade tranCrossfade[] =
+            new TransitionCrossfade[(NUM_OF_ITERATIONS *10)];
+
+        long beginTime = SystemClock.uptimeMillis();
+        for (int i = 0; i < (NUM_OF_ITERATIONS *10); i++) {
+            tranCrossfade[i] = new TransitionCrossfade("transition" + i,
+                mediaVideoItem[i], mediaVideoItem[i+1], transitionDuration,
+                transitionBehavior);
+        }
+        timeTaken = calculateTimeTaken(beginTime, (NUM_OF_ITERATIONS * 10));
+        loggingInfo[0] = "Time taken to Create CrossFade Transition\t" +
+            timeTaken;
+
+        beginTime = SystemClock.uptimeMillis();
+        for (int i = 0; i < (NUM_OF_ITERATIONS *10); i++) {
+            mVideoEditor.addTransition(tranCrossfade[i]);
+        }
+        timeTaken = calculateTimeTaken(beginTime, (NUM_OF_ITERATIONS * 10));
+        loggingInfo[1] = "\n\tTime taken to add CrossFade Transition\t" +
+            timeTaken;
+
+        beginTime = SystemClock.uptimeMillis();
+        for (int i = 0; i < (NUM_OF_ITERATIONS *10); i++) {
+            assertEquals("Removing Transitions", tranCrossfade[i], mVideoEditor
+                .removeTransition(tranCrossfade[i].getId()));
+        }
+        timeTaken = calculateTimeTaken(beginTime, (NUM_OF_ITERATIONS * 10));
+        loggingInfo[2] = "\n\tTime taken to remove CrossFade Transition\t" +
+            timeTaken;
+
+        writeTimingInfo("testPerformanceAddRemoveTransition (in mSec)", loggingInfo);
+    }
+
+    /**
+     * To test performance of Export
+     *
+     * @throws Exception
+     */
+    // TODO : remove PRF_004
+    @LargeTest
+    public void testPerformanceExport() throws Exception {
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final int outHeight = MediaProperties.HEIGHT_480;
+        final int outBitrate = MediaProperties.BITRATE_256K;
+        final int outVcodec = MediaProperties.VCODEC_H264BP;
+        final String[] loggingInfo = new String[1];
+        final String outFilename = mVideoEditorHelper
+            .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
+        final String videoItemFileName1 = INPUT_FILE_PATH +
+            "H264_BP_1080x720_30fps_12Mbps_AACLC_44.1khz_64kbps_s_1_17.mp4";
+        final String imageItemFileName1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
+        final String videoItemFileName2 = INPUT_FILE_PATH +
+            "H264_BP_640x480_15fps_1200Kbps_AACLC_48KHz_32kbps_m_1_17.3gp";
+        final String imageItemFileName2 = INPUT_FILE_PATH + "IMG_176x144.jpg";
+        final String videoItemFileName3 = INPUT_FILE_PATH +
+            "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_161kbps_s_0_26.mp4";
+        final String overlayFile = INPUT_FILE_PATH + "IMG_640x480_Overlay1.png";
+        final String audioTrackFilename = INPUT_FILE_PATH +
+            "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
+        final String maskFilename = INPUT_FILE_PATH +
+            "TransitionSpiral_QVGA.jpg";
+
+        final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
+            "m1", videoItemFileName1, renderingMode);
+        mediaItem1.setExtractBoundaries(0, 20000);
+        mVideoEditor.addMediaItem(mediaItem1);
+
+        final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
+            "m2", imageItemFileName1, 10000, renderingMode);
+        mVideoEditor.addMediaItem(mediaItem2);
+
+        final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor,
+            "m3", videoItemFileName2, renderingMode);
+        mediaItem3.setExtractBoundaries(0, 20000);
+        mVideoEditor.addMediaItem(mediaItem3);
+
+        final MediaImageItem mediaItem4 = new MediaImageItem(mVideoEditor,
+            "m4", imageItemFileName2, 10000, renderingMode);
+        mVideoEditor.addMediaItem(mediaItem4);
+
+        final MediaVideoItem mediaItem5 = new MediaVideoItem(mVideoEditor,
+            "m5", videoItemFileName3, renderingMode);
+        mediaItem5.setExtractBoundaries(0, 20000);
+        mVideoEditor.addMediaItem(mediaItem5);
+        /**
+         * 7.Add TransitionAlpha, Apply this  Transition as Begin for Media Item 1
+         *  with duration = 2 sec behavior = BEHAVIOR_LINEAR, mask file name =
+         * TransitionSpiral_QVGA.jpg , blending percent = 50%, invert = true;
+         * */
+        final TransitionAlpha transition1 =
+            mVideoEditorHelper.createTAlpha("transition1", null, mediaItem1,
+                2000, Transition.BEHAVIOR_LINEAR, maskFilename, 50, true);
+        mVideoEditor.addTransition(transition1);
+
+        /**
+         * 8.Add Transition Sliding between MediaItem 2 and 3 ,
+         *  Sliding Direction  = DIRECTION_RIGHT_OUT_LEFT_IN,
+         *  behavior  = BEHAVIOR_MIDDLE_FAST and duration = 4sec
+         * */
+        final TransitionSliding transition2And3 =
+            mVideoEditorHelper.createTSliding("transition2", mediaItem2,
+                mediaItem3, 4000, Transition.BEHAVIOR_MIDDLE_FAST,
+                TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN);
+        mVideoEditor.addTransition(transition2And3);
+
+        /**
+         * 9.Add Transition Crossfade between  Media Item 3 and 4,
+         *  behavior = BEHAVIOR_MIDDLE_SLOW, duration = 3.5 sec
+         * */
+        final TransitionCrossfade transition3And4 =
+            mVideoEditorHelper.createTCrossFade("transition3", mediaItem3,
+                mediaItem4, 3500, Transition.BEHAVIOR_MIDDLE_SLOW);
+        mVideoEditor.addTransition(transition3And4);
+
+        /**
+         * 10.Add Transition Fadeblack between  Media Item 4 and 5,
+         *  behavior = BEHAVIOR_SPEED_DOWN, duration = 3.5 sec
+         * */
+        final TransitionFadeBlack transition4And5 =
+            mVideoEditorHelper.createTFadeBlack("transition4", mediaItem4,
+                mediaItem5, 3500, Transition.BEHAVIOR_SPEED_DOWN);
+        mVideoEditor.addTransition(transition4And5);
+
+        /**
+         * 11.Add Effect 1 type="TYPE_SEPIA" to the MediaItem 1,
+         *  start time=1sec and duration =4secs
+         * */
+        final EffectColor effectColor1 = mVideoEditorHelper.createEffectItem(
+            mediaItem1, "effect1", 1000, 4000, EffectColor.TYPE_SEPIA, 0);
+        mediaItem1.addEffect(effectColor1);
+
+        /**
+         * 12.Add Overlay 1  to the MediaItem 3: Frame Overlay with start time = 1 sec
+         * duration = 4 sec with item  = IMG_640x480_Overlay1.png
+         * */
+        final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(overlayFile, 640,
+            480);
+        final OverlayFrame overlayFrame =
+            mVideoEditorHelper.createOverlay(mediaItem3, "overlay",
+                mBitmap, 1000, 4000);
+        mediaItem3.addOverlay(overlayFrame);
+        /**
+         * 13.Add Effect 2 type="TYPE_NEGATIVE" to the MediaItem 2,
+         *  start time=8sec and duration =2secs
+         * */
+        final EffectColor effectColor2 = mVideoEditorHelper.createEffectItem(
+            mediaItem2, "effect2", 8000, 2000, EffectColor.TYPE_NEGATIVE, 0);
+        mediaItem2.addEffect(effectColor2);
+        /**
+         * 14.Add Effect 3 type="TYPE_COLOR" to the MediaItem 3, color param = "PINK",
+         *  start time=5 sec and duration =3secs
+         * */
+        final EffectColor effectColor3 = mVideoEditorHelper.createEffectItem(
+            mediaItem3, "effect3", 5000, 3000, EffectColor.TYPE_COLOR,
+            EffectColor.PINK);
+        mediaItem3.addEffect(effectColor3);
+        /**
+         * 15.Add Effect 4 type="TYPE_FIFTIES" to the MediaItem 4,
+         *  start time=2 sec and duration =1secs
+        * */
+        final EffectColor effectColor4 = mVideoEditorHelper.createEffectItem(
+            mediaItem4, "effect4", 2000, 1000, EffectColor.TYPE_FIFTIES, 0);
+        mediaItem4.addEffect(effectColor4);
+        /**
+         * 16.Add KenBurnsEffect for MediaItem 4 with
+         *  duration = 3 sec and startTime = 4 sec
+         *  StartRect
+         *  left = org_height/3  ;  top = org_width/3
+         *  bottom = org_width/2  ;  right = org_height/2
+         *  EndRect
+         *  left = 0  ;  top = 0
+         *  bottom =  org_height;  right =  org_width
+         * */
+
+        final Rect startRect = new Rect((mediaItem4.getHeight() / 3),
+            (mediaItem4.getWidth() / 3), (mediaItem4.getHeight() / 2),
+            (mediaItem4.getWidth() / 2));
+        final Rect endRect = new Rect(0, 0, mediaItem4.getWidth(),
+            mediaItem4.getHeight());
+        final EffectKenBurns kbEffectOnMediaItem = new EffectKenBurns(
+            mediaItem4, "KBOnM2", startRect, endRect,4000 , 3000);
+        mediaItem4.addEffect(kbEffectOnMediaItem);
+
+        /** 17.Add Audio Track,Set extract boundaries o to 10 sec.
+         * */
+        final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
+            mVideoEditor, "audioTrack", audioTrackFilename);
+        mVideoEditor.addAudioTrack(audioTrack);
+        /** 18.Enable Looping for Audio Track.
+         * */
+        audioTrack.enableLoop();
+        float timeTaken = 0.0f;
+        final long beginTime = SystemClock.uptimeMillis();
+            try {
+                mVideoEditor.export(outFilename, outHeight, outBitrate,
+                    new ExportProgressListener() {
+                        public void onProgress(VideoEditor ve,
+                            String outFileName, int progress) {
+                        }
+                    });
+            } catch (Exception e) {
+                assertTrue("Error in Export" + e.toString(), false);
+            }
+        mVideoEditorHelper.checkDeleteExistingFile(outFilename);
+
+        timeTaken = calculateTimeTaken(beginTime, 1);
+        loggingInfo[0] = "Time taken to do ONE export of storyboard duration\t"
+            + mVideoEditor.getDuration() + "   is   :\t" + timeTaken;
+
+        writeTimingInfo("testPerformanceExport (in mSec)", loggingInfo);
+        mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath()));
+    }
+
+
+    /**
+     * To test the performance of thumbnail extraction
+     *
+     * @throws Exception
+     */
+    // TODO : remove PRF_005
+    @LargeTest
+    public void testPerformanceThumbnailVideoItem() throws Exception {
+        final String videoItemFileName = INPUT_FILE_PATH
+            + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
+        final int videoItemStartTime = 0;
+        final int videoItemEndTime = 20000;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final String[] loggingInfo = new String[1];
+
+        final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
+            "m1", videoItemFileName, renderingMode);
+        mediaVideoItem.setExtractBoundaries(videoItemStartTime,
+            videoItemEndTime);
+
+        float timeTaken = 0.0f;
+        long beginTime = SystemClock.uptimeMillis();
+        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
+            mediaVideoItem.getThumbnail(mediaVideoItem.getWidth() / 2,
+                mediaVideoItem.getHeight() / 2, i);
+        }
+        timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
+        loggingInfo[0] = "Duration taken to get Video Thumbnails\t" +
+            timeTaken;
+
+        writeTimingInfo("testPerformanceThumbnailVideoItem (in mSec)", loggingInfo);
+    }
+
+    /**
+     * To test the performance of adding and removing the overlay to media item
+     *
+     * @throws Exception
+     */
+    // TODO : remove PRF_006
+    @LargeTest
+    public void testPerformanceOverlayVideoItem() throws Exception {
+        final String videoItemFileName1 = INPUT_FILE_PATH +
+            "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
+        final int videoItemStartTime1 = 0;
+        final int videoItemEndTime1 = 10000;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final String overlayFilename = INPUT_FILE_PATH
+            + "IMG_640x480_Overlay1.png";
+        final int overlayStartTime = 1000;
+        final int overlayDuration = 5000;
+
+        final String[] loggingInfo = new String[2];
+        MediaVideoItem mediaVideoItem = null;
+
+        try {
+            mediaVideoItem = new MediaVideoItem(mVideoEditor, "m0",
+                videoItemFileName1, renderingMode);
+            mediaVideoItem.setExtractBoundaries(videoItemStartTime1,
+                videoItemEndTime1);
+        } catch (Exception e1) {
+            assertTrue("Can not create Video Item with file name = "
+                + e1.toString(), false);
+        }
+        final OverlayFrame overlayFrame[] = new OverlayFrame[NUM_OF_ITERATIONS];
+        final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(overlayFilename,
+            640, 480);
+        float timeTaken = 0.0f;
+        long beginTime = SystemClock.uptimeMillis();
+        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
+            overlayFrame[i] = new OverlayFrame(mediaVideoItem, "overlay" + i,
+            mBitmap, overlayStartTime, overlayDuration);
+            mediaVideoItem.addOverlay(overlayFrame[i]);
+        }
+        timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
+        loggingInfo[0] = "Time taken to add & create Overlay\t" + timeTaken;
+
+        beginTime = SystemClock.uptimeMillis();
+        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
+            assertEquals("Removing Overlays", overlayFrame[i],
+                mediaVideoItem.removeOverlay((overlayFrame[i].getId())));
+        }
+        timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
+        loggingInfo[1] = "\n\tTime taken to remove  Overlay\t" +
+            timeTaken;
+
+        writeTimingInfo("testPerformanceOverlayVideoItem (in mSec)", loggingInfo);
+    }
+
+    /**
+     * To test the performance of get properties of a Video media item
+     *
+     * @throws Exception
+     */
+    // TODO : remove PRF_007
+    @LargeTest
+    public void testPerformanceVideoItemProperties() throws Exception {
+        final String videoItemFileName1 = INPUT_FILE_PATH +
+            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
+        final int videoItemStartTime1 = 0;
+        final int videoItemEndTime1 = 10100;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        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 = 3169971;
+        final int fps = 30;
+        final int videoProfile = MediaProperties.H264_PROFILE_0_LEVEL_1_3;
+        final int width = 1080;
+        final int height = MediaProperties.HEIGHT_720;
+        float timeTaken = 0.0f;
+        final String[] loggingInfo = new String[1];
+        final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
+            "m0", videoItemFileName1, renderingMode);
+        mediaVideoItem.setExtractBoundaries(videoItemStartTime1,
+            videoItemEndTime1);
+        long beginTime = SystemClock.uptimeMillis();
+        for (int i = 0; i < (NUM_OF_ITERATIONS*10); i++) {
+            try {
+                assertEquals("Aspect Ratio Mismatch",
+                    aspectRatio, mediaVideoItem.getAspectRatio());
+                assertEquals("File Type Mismatch",
+                    fileType, mediaVideoItem.getFileType());
+                assertEquals("VideoCodec Mismatch",
+                    videoCodecType, mediaVideoItem.getVideoType());
+                assertEquals("duration Mismatch",
+                    duration, mediaVideoItem.getDuration());
+                assertEquals("Video Profile ",
+                    videoProfile, mediaVideoItem.getVideoProfile());
+                assertEquals("Video height ",
+                    height, mediaVideoItem.getHeight());
+                assertEquals("Video width ",
+                    width, mediaVideoItem.getWidth());
+            } catch (Exception e1) {
+                assertTrue("Can not create Video Item with file name = "
+                    + e1.toString(), false);
+            }
+        }
+        timeTaken = calculateTimeTaken(beginTime, (NUM_OF_ITERATIONS*10));
+        loggingInfo[0] = "Time taken to get Media Properties\t"
+            + timeTaken;
+        writeTimingInfo("testPerformanceVideoItemProperties:", loggingInfo);
+    }
+
+    /**
+     * To test the performance of generatePreview : with Transitions
+     *
+     * @throws Exception
+     */
+    // TODO : remove PRF_008
+    @LargeTest
+    public void testPerformanceGeneratePreviewWithTransitions()
+        throws Exception {
+        final String videoItemFileName = INPUT_FILE_PATH +
+            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
+        final String imageItemFileName = INPUT_FILE_PATH +
+            "IMG_1600x1200.jpg";
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final int transitionBehavior = Transition.BEHAVIOR_MIDDLE_FAST;
+        long averageTime = 0;
+        final String[] loggingInfo = new String[1];
+
+        final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
+            "mediaItem1", videoItemFileName, renderingMode);
+        mediaVideoItem.setExtractBoundaries(0, 10000);
+        mVideoEditor.addMediaItem(mediaVideoItem);
+
+        final MediaImageItem mediaImageItem = new MediaImageItem(mVideoEditor,
+            "mediaItem2", imageItemFileName, 10000, renderingMode);
+        mVideoEditor.addMediaItem(mediaImageItem);
+
+        final TransitionCrossfade transitionCrossFade = new TransitionCrossfade(
+            "transitionCrossFade", mediaVideoItem, mediaImageItem,
+            5000, transitionBehavior);
+        mVideoEditor.addTransition(transitionCrossFade);
+
+        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
+            final long duration1 = SystemClock.uptimeMillis();
+            mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
+                public void onProgress(Object item, int action, int progress) {
+                }
+            });
+            final long duration2 = SystemClock.uptimeMillis();
+            mVideoEditor.removeTransition(transitionCrossFade.getId());
+            mVideoEditor.addTransition(transitionCrossFade);
+            averageTime += (duration2 - duration1);
+        }
+        final long durationToAddObjects = averageTime;
+        final float timeTaken = (float)durationToAddObjects *
+            1.0f/(float)NUM_OF_ITERATIONS;
+        loggingInfo[0] = "Time taken to Generate Preview with transition\t"
+            + timeTaken;
+        writeTimingInfo("testPerformanceGeneratePreviewWithTransitions:",
+            loggingInfo);
+    }
+
+    /**
+     * To test the performance of generatePreview : with KenBurn
+     *
+     * @throws Exception
+     */
+    // TODO : remove PRF_009
+    @LargeTest
+    public void testPerformanceWithKenBurn() throws Exception {
+        final String videoItemFileName = INPUT_FILE_PATH +
+            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
+        final String imageItemFileName = INPUT_FILE_PATH +
+            "IMG_1600x1200.jpg";
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        long averageTime = 0;
+        final String[] loggingInfo = new String[1];
+        final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
+            "mediaItem1", videoItemFileName, renderingMode);
+        mediaVideoItem.setExtractBoundaries(0, 10000);
+        mVideoEditor.addMediaItem(mediaVideoItem);
+
+        final MediaImageItem mediaImageItem = new MediaImageItem(mVideoEditor,
+            "mediaItem2", imageItemFileName, 10000, renderingMode);
+        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);
+        mediaImageItem.addEffect(kbEffectOnMediaItem);
+
+        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
+            final long duration1 = SystemClock.uptimeMillis();
+            mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
+                public void onProgress(Object item, int action, int progress) {
+                }
+            });
+            final long duration2 = SystemClock.uptimeMillis();
+            mediaImageItem.removeEffect(kbEffectOnMediaItem.getId());
+            mediaImageItem.addEffect(kbEffectOnMediaItem);
+            averageTime += duration2 - duration1;
+        }
+
+        final long durationToAddObjects = (averageTime);
+        final float timeTaken = (float)durationToAddObjects *
+            1.0f/(float)NUM_OF_ITERATIONS;
+        loggingInfo[0] = "Time taken to Generate KenBurn Effect \t"
+            + timeTaken;
+        writeTimingInfo("testPerformanceWithKenBurn", loggingInfo);
+    }
+
+    /**
+     * To test the performance of generatePreview : with Transitions and
+     * Effect,Overlapping scenario
+     *
+     * @throws Exception
+     */
+    // TODO : remove PRF_010
+    @LargeTest
+    public void testPerformanceEffectOverlappingTransition() throws Exception {
+        final String videoItemFileName1 = INPUT_FILE_PATH +
+            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
+        final String videoItemFileName2 = INPUT_FILE_PATH
+            + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
+        final int videoStartTime1 = 0;
+        final int videoEndTime1 = 10000;
+        final int videoStartTime2 = 0;
+        final int videoEndTime2 = 10000;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final int transitionDuration = 5000;
+        final int transitionBehavior = Transition.BEHAVIOR_MIDDLE_FAST;
+        final int effectItemStartTime = 5000;
+        final int effectItemDurationTime = 5000;
+        final int effectType = EffectColor.TYPE_COLOR;
+        final int effectColorType = EffectColor.GREEN;
+        long averageDuration = 0;
+
+        final String[] loggingInfo = new String[1];
+        final MediaVideoItem mediaVideoItem1 = new MediaVideoItem(mVideoEditor,
+            "mediaItem1", videoItemFileName1, renderingMode);
+        mediaVideoItem1.setExtractBoundaries(videoStartTime1, videoEndTime1);
+        mVideoEditor.addMediaItem(mediaVideoItem1);
+
+        final MediaVideoItem mediaVideoItem2 = new MediaVideoItem(mVideoEditor,
+            "mediaItem2", videoItemFileName2, renderingMode);
+        mediaVideoItem2.setExtractBoundaries(videoStartTime2, videoEndTime2);
+        mVideoEditor.addMediaItem(mediaVideoItem2);
+
+        final TransitionCrossfade transitionCrossFade = new TransitionCrossfade(
+            "transitionCrossFade", mediaVideoItem1, mediaVideoItem2,
+            transitionDuration, transitionBehavior);
+        mVideoEditor.addTransition(transitionCrossFade);
+
+        final EffectColor effectColor = new EffectColor(mediaVideoItem1,
+            "effect", effectItemStartTime, effectItemDurationTime, effectType,
+             effectColorType);
+        mediaVideoItem1.addEffect(effectColor);
+
+        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
+            final long duration1 = SystemClock.uptimeMillis();
+            mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
+                public void onProgress(Object item, int action, int progress) {
+                }
+            });
+            final long duration2 = SystemClock.uptimeMillis();
+            mVideoEditor.removeTransition(transitionCrossFade.getId());
+            mVideoEditor.addTransition(transitionCrossFade);
+            averageDuration += (duration2 - duration1);
+        }
+        SystemClock.uptimeMillis();
+        final long durationToAddObjects = (averageDuration);
+        final float timeTaken = (float)durationToAddObjects *
+            1.0f/(float)NUM_OF_ITERATIONS;
+        loggingInfo[0] =
+            "Time taken to testPerformanceEffectOverlappingTransition\t"
+            + timeTaken;
+        writeTimingInfo("testPerformanceEffectOverlappingTransition:",
+            loggingInfo);
+    }
+
+    /**
+     * To test creation of story board with Transition and Two Effects, Effect
+     * overlapping transitions
+     *
+     * @throws Exception
+     */
+    // TODO : remove PRF_011
+    @LargeTest
+    public void testPerformanceTransitionWithEffectOverlapping() throws Exception {
+        final String videoItemFileName1 = INPUT_FILE_PATH +
+            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
+        final String videoItemFileName2 = INPUT_FILE_PATH
+            + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final int transitionDuration = 5000;
+        final int transitionBehavior = Transition.BEHAVIOR_MIDDLE_FAST;
+        final int effectItemStartTime1 = 5000;
+        final int effectItemDurationTime1 = 5000;
+        final int effectType1 = EffectColor.TYPE_COLOR;
+        final int effectColorType1 = EffectColor.GREEN;
+        final int effectItemStartTime2 = 5000;
+        final int effectItemDurationTime2 = 5000;
+        final int effectType2 = EffectColor.TYPE_COLOR;
+        final int effectColorType2 = EffectColor.GREEN;
+        int averageTime = 0;
+        final String[] loggingInfo = new String[1];
+
+        final MediaVideoItem mediaVideoItem1 = new MediaVideoItem(mVideoEditor,
+            "mediaItem1", videoItemFileName1, renderingMode);
+        mVideoEditor.addMediaItem(mediaVideoItem1);
+
+        final MediaVideoItem mediaVideoItem2 = new MediaVideoItem(mVideoEditor,
+            "mediaItem2", videoItemFileName2, renderingMode);
+        mVideoEditor.addMediaItem(mediaVideoItem2);
+
+        final TransitionCrossfade transitionCrossFade = new TransitionCrossfade(
+            "transitionCrossFade", mediaVideoItem1, mediaVideoItem2,
+            transitionDuration, transitionBehavior);
+        mVideoEditor.addTransition(transitionCrossFade);
+
+        final EffectColor effectColor1 = new EffectColor(mediaVideoItem1,
+            "effect1", effectItemStartTime1, effectItemDurationTime1,
+            effectType1, effectColorType1);
+        mediaVideoItem1.addEffect(effectColor1);
+
+        final EffectColor effectColor2 = new EffectColor(mediaVideoItem2,
+            "effect2", effectItemStartTime2, effectItemDurationTime2,
+            effectType2, effectColorType2);
+        mediaVideoItem2.addEffect(effectColor2);
+
+        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
+            final long duration1 = SystemClock.uptimeMillis();
+            mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
+                public void onProgress(Object item, int action, int progress) {
+                }
+            });
+            final long duration2 = SystemClock.uptimeMillis();
+            mVideoEditor.removeTransition(transitionCrossFade.getId());
+            mVideoEditor.addTransition(transitionCrossFade);
+            averageTime += duration2 - duration1;
+        }
+        final long durationToAddObjects = (averageTime);
+        final float timeTaken = (float)durationToAddObjects *
+            1.0f/(float)NUM_OF_ITERATIONS;
+        loggingInfo[0] = "Time taken to TransitionWithEffectOverlapping\t"
+            + timeTaken;
+        writeTimingInfo("testPerformanceTransitionWithEffectOverlapping",
+            loggingInfo);
+    }
+
+    /**
+     *To test ThumbnailList for H264
+     */
+    // TODO : TC_PRF_12
+    @LargeTest
+    public void testThumbnailH264NonIFrame() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH +
+            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
+        final int outWidth = 1080;
+        final int outHeight = 720;
+        final int atTime = 2400;
+        long durationToAddObjects = 0;
+        int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final String[] loggingInfo = new String[1];
+        final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
+            "m1", videoItemFilename, renderingMode);
+        assertNotNull("MediaVideoItem", mediaVideoItem);
+
+        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
+            final long duration1 = SystemClock.uptimeMillis();
+            mediaVideoItem.getThumbnail(outWidth, outHeight, atTime + i);
+            final long duration2 = SystemClock.uptimeMillis();
+            durationToAddObjects += (duration2 - duration1);
+        }
+        final float timeTaken = (float)durationToAddObjects *
+            1.0f/(float)NUM_OF_ITERATIONS;
+        loggingInfo[0] = "Time taken for Thumbnail generation \t"
+            + timeTaken;
+        writeTimingInfo("testThumbnailH264NonIFrame", loggingInfo);
+    }
+
+    /**
+     *To test ThumbnailList for H264
+     */
+    // TODO : TC_PRF_13
+    @LargeTest
+    public void testThumbnailH264AnIFrame() throws Exception {
+        final String videoItemFilename = INPUT_FILE_PATH +
+            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
+        final int outWidth = 1080;
+        final int outHeight = 720;
+        final int atTime = 3000;
+        int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final String[] loggingInfo = new String[1];
+        long durationToAddObjects = 0;
+
+        final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
+            "m1", videoItemFilename, renderingMode);
+        assertNotNull("MediaVideoItem", mediaVideoItem);
+
+        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
+            final long duration1 = SystemClock.uptimeMillis();
+            mediaVideoItem.getThumbnail(outWidth, outHeight, atTime + i);
+            final long duration2 = SystemClock.uptimeMillis();
+            durationToAddObjects += (duration2 - duration1);
+        }
+        final float timeTaken = (float)durationToAddObjects *
+            1.0f/(float)NUM_OF_ITERATIONS;
+        loggingInfo[0] = "Time taken Thumbnail generation \t"
+            + timeTaken;
+        writeTimingInfo("testThumbnailH264AnIFrame", loggingInfo);
+    }
+
+    /**
+     * To test the performance : With an audio track
+     *
+     * @throws Exception
+     */
+    // TODO : remove PRF_014
+    @LargeTest
+    public void testPerformanceWithAudioTrack() throws Exception {
+        final String videoItemFileName1 = INPUT_FILE_PATH +
+            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
+        final String audioFilename1 = INPUT_FILE_PATH +
+            "AACLC_44.1kHz_256kbps_s_1_17.mp4";
+        final String audioFilename2 = INPUT_FILE_PATH +
+            "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final int audioVolume = 50;
+        final String[] loggingInfo = new String[2];
+        float timeTaken = 0.0f;
+
+        final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
+            "mediaItem1", videoItemFileName1, renderingMode);
+        mVideoEditor.addMediaItem(mediaVideoItem);
+
+        final AudioTrack audioTrack1 = new AudioTrack(mVideoEditor,
+            "Audio Track1", audioFilename1);
+        audioTrack1.disableDucking();
+        audioTrack1.setVolume(audioVolume);
+        mVideoEditor.addAudioTrack(audioTrack1);
+
+        long beginTime = SystemClock.uptimeMillis();
+        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
+            public void onProgress(Object item, int action, int progress) {
+            }
+        });
+        timeTaken = calculateTimeTaken(beginTime, 1);
+        loggingInfo[0] = "Time taken for 1st Audio Track (AACLC)\t"
+            + timeTaken;
+
+        final AudioTrack audioTrack2 = new AudioTrack(mVideoEditor,
+            "Audio Track2", audioFilename2);
+        audioTrack2.enableLoop();
+
+        beginTime = SystemClock.uptimeMillis();
+        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
+            public void onProgress(Object item, int action, int progress) {
+            }
+        });
+        timeTaken = calculateTimeTaken(beginTime, 1);
+        loggingInfo[1] = "\n\tTime taken for 2nd Audio Track(AMRNB)\t"
+            + timeTaken;
+
+        writeTimingInfo("testPerformanceWithAudioTrack", loggingInfo);
+    }
+
+    /**
+     * To test the performance of adding and removing the
+     * image media item with 640 x 480
+     *
+     * @throws Exception
+     */
+    // TODO : remove PRF_015
+    @LargeTest
+    public void testPerformanceAddRemoveImageItem640x480() throws Exception {
+        final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
+        final int imageItemDuration = 0;
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final String[] loggingInfo = new String[3];
+
+        float timeTaken = 0.0f;
+
+        final MediaImageItem[] mediaImageItem =
+            new MediaImageItem[NUM_OF_ITERATIONS];
+        long beginTime = SystemClock.uptimeMillis();
+        createImageItems(mediaImageItem, imageItemFileName, renderingMode,
+            imageItemDuration);
+        timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
+        loggingInfo[0] = "Time taken to Create  Media Image Item (640x480)\t"
+            + timeTaken;
+
+        beginTime = SystemClock.uptimeMillis();
+        addImageItems(mediaImageItem);
+        timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
+        loggingInfo[1] = "\n\tTime taken to add  Media Image Item (640x480)\t"
+            + timeTaken;
+
+        beginTime = SystemClock.uptimeMillis();
+        removeImageItems(mediaImageItem);
+        timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
+        loggingInfo[2] = "\n\tTime taken to remove  Media Image Item (640x480)\t"
+            + timeTaken;
+        writeTimingInfo("testPerformanceAddRemoveImageItem640x480 (in mSec)", loggingInfo);
+    }
+
+
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/VideoEditorStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/VideoEditorStressTest.java
new file mode 100755
index 0000000..0e70dd3
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/VideoEditorStressTest.java
@@ -0,0 +1,1317 @@
+/*
+ * 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.stress;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.Writer;
+import java.util.List;
+
+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.TransitionCrossfade;
+import android.media.videoeditor.TransitionAlpha;
+import android.media.videoeditor.TransitionFadeBlack;
+import android.media.videoeditor.TransitionSliding;
+import android.media.videoeditor.VideoEditor;
+import android.os.Environment;
+import android.test.ActivityInstrumentationTestCase;
+import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener;
+import android.os.Environment;
+import android.os.SystemClock;
+import android.test.ActivityInstrumentationTestCase;
+import android.media.videoeditor.VideoEditor.ExportProgressListener;
+import android.media.videoeditor.VideoEditorFactory;
+import android.media.videoeditor.ExtractAudioWaveformProgressListener;
+
+import android.os.Debug;
+import android.util.Log;
+
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import android.test.suitebuilder.annotation.LargeTest;
+import com.android.mediaframeworktest.VideoEditorHelper;
+
+/**
+ * Junit / Instrumentation - performance measurement for media player and
+ * recorder
+ */
+public class VideoEditorStressTest
+        extends ActivityInstrumentationTestCase<MediaFrameworkTest> {
+
+    private final String TAG = "VideoEditorPerformance";
+
+    private final String PROJECT_LOCATION = VideoEditorHelper.PROJECT_LOCATION_COMMON;
+
+    private final String INPUT_FILE_PATH = VideoEditorHelper.INPUT_FILE_PATH_COMMON;
+
+    private final String VIDEOEDITOR_OUTPUT = PROJECT_LOCATION +
+        "VideoEditorStressMemOutput.txt";
+
+    private long BeginJavaMemory;
+    private long AfterJavaMemory;
+
+    private long BeginNativeMemory;
+    private long AfterNativeMemory;
+
+    public VideoEditorStressTest() {
+        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+        new File(VIDEOEDITOR_OUTPUT).delete();
+    }
+
+    private final String PROJECT_CLASS_NAME =
+        "android.media.videoeditor.VideoEditorImpl";
+    private VideoEditor mVideoEditor;
+    private VideoEditorHelper mVideoEditorHelper;
+
+    @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();
+    }
+
+    private void writeTimingInfo(String[] information)
+        throws Exception {
+        File outFile = new File(VIDEOEDITOR_OUTPUT);
+        Writer output = new BufferedWriter(new FileWriter(outFile, true));
+        for (int i = 0; i < information.length; i++) {
+            output.write(information[i]);
+        }
+        output.close();
+    }
+
+    private void writeTestCaseHeader(String testCaseName)
+        throws Exception {
+        File outFile = new File(VIDEOEDITOR_OUTPUT);
+        Writer output = new BufferedWriter(new FileWriter(outFile, true));
+        output.write("\n\n" + testCaseName + "\n");
+        output.close();
+    }
+
+    private void getBeginMemory() throws Exception {
+        System.gc();
+        Thread.sleep(2500);
+        BeginNativeMemory = Debug.getNativeHeapAllocatedSize();
+    }
+    private void getAfterMemory_updateLog(String[] loggingInfo, boolean when,
+        int iteration)
+        throws Exception {
+        System.gc();
+        Thread.sleep(2500);
+        AfterNativeMemory = Debug.getNativeHeapAllocatedSize();
+        if(when == false){
+            loggingInfo[0] = "\n Before Remove: iteration No.= " + iteration +
+                "\t " + (AfterNativeMemory - BeginNativeMemory);
+        } else {
+            loggingInfo[0] = "\n After Remove: iteration No.= " + iteration +
+                "\t " + (AfterNativeMemory - BeginNativeMemory);
+        }
+        writeTimingInfo(loggingInfo);
+    }
+
+    /**
+     * To stress test MediaItem(Video Item) adding functionality
+     *
+     * @throws Exception
+     */
+    // TODO : remove TC_STR_001
+    @LargeTest
+    public void testStressAddRemoveVideoItem() throws Exception {
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+
+        final String videoItemFileName1 = INPUT_FILE_PATH +
+            "H264_BP_176x144_15fps_144kbps_AMRNB_8kHz_12.2kbps_m_1_17.3gp";
+        final String videoItemFileName2 = INPUT_FILE_PATH +
+            "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
+        final String videoItemFileName3 = INPUT_FILE_PATH +
+            "H263_profile0_176x144_15fps_128kbps_1_35.3gp";
+        final String videoItemFileName4 = INPUT_FILE_PATH +
+            "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp";
+        final String[] loggingInfo = new String[1];
+        writeTestCaseHeader("testStressAddRemoveVideoItem");
+        int i = 0;
+        getBeginMemory();
+
+        for ( i = 0; i < 50; i++) {
+            if (i % 4 == 0) {
+                final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
+                    "m1" + i, videoItemFileName1, renderingMode);
+                mediaItem1.setExtractBoundaries(0, 5000);
+                mVideoEditor.addMediaItem(mediaItem1);
+            }
+            if (i % 4 == 1) {
+                final MediaVideoItem mediaItem2 = new MediaVideoItem(mVideoEditor,
+                    "m2" + i, videoItemFileName2, renderingMode);
+                mediaItem2.setExtractBoundaries(0, 10000);
+                mVideoEditor.addMediaItem(mediaItem2);
+            }
+            if (i % 4 == 2) {
+                final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor,
+                    "m3" + i, videoItemFileName3, renderingMode);
+                mediaItem3.setExtractBoundaries(30000, 45000);
+                mVideoEditor.addMediaItem(mediaItem3);
+            }
+            if (i % 4 == 3) {
+                final MediaVideoItem mediaItem4 = new MediaVideoItem(mVideoEditor,
+                    "m4" + i, videoItemFileName4, renderingMode);
+                mediaItem4.setExtractBoundaries(10000, 30000);
+                mVideoEditor.addMediaItem(mediaItem4);
+            }
+            if (i % 10 == 0) {
+                getAfterMemory_updateLog(loggingInfo, false, i);
+            }
+        }
+        getAfterMemory_updateLog(loggingInfo, false, i);
+
+        /** Remove items and check for memory leak if any */
+        getBeginMemory();
+        for ( i = 0; i < 50; i++) {
+            if (i % 4 == 0) {
+                mVideoEditor.removeMediaItem("m1" + i);
+            }
+            if (i % 4 == 1) {
+                mVideoEditor.removeMediaItem("m2" + i);
+            }
+            if (i % 4 == 2) {
+                mVideoEditor.removeMediaItem("m3" + i);
+            }
+            if (i % 4 == 3) {
+                mVideoEditor.removeMediaItem("m4" + i);
+            }
+            if (i % 10 == 0) {
+                getAfterMemory_updateLog(loggingInfo, true, i);
+            }
+        }
+        getAfterMemory_updateLog(loggingInfo, true, i);
+    }
+
+    /**
+     * To stress test MediaItem(Image Item) adding functionality
+     *
+     * @throws Exception
+     */
+    // TODO : remove TC_STR_002
+    @LargeTest
+    public void testStressAddRemoveImageItem() throws Exception {
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final String ImageItemFileName1 = INPUT_FILE_PATH +
+            "IMG_1600x1200.jpg";
+        final String ImageItemFileName2 = INPUT_FILE_PATH +
+            "IMG_640x480.jpg";
+        final String ImageItemFileName3 = INPUT_FILE_PATH +
+            "IMG_320x240.jpg";
+        final String ImageItemFileName4 = INPUT_FILE_PATH +
+            "IMG_176x144.jpg";
+        final String[] loggingInfo = new String[1];
+        int i = 0;
+        writeTestCaseHeader("testStressAddRemoveImageItem");
+        getBeginMemory();
+        for ( i = 0; i < 50; i++) {
+            if (i % 4 == 0) {
+                final MediaImageItem mediaItem1 = new MediaImageItem(mVideoEditor,
+                    "m1"+ i, ImageItemFileName1, 5000, renderingMode);
+                mVideoEditor.addMediaItem(mediaItem1);
+            }
+            if (i % 4 == 1) {
+                final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
+                    "m2"+ i, ImageItemFileName2, 10000, renderingMode);
+                mVideoEditor.addMediaItem(mediaItem2);
+            }
+            if (i % 4 == 2) {
+                final MediaImageItem mediaItem3 = new MediaImageItem(mVideoEditor,
+                    "m3"+ i, ImageItemFileName3, 15000, renderingMode);
+                mVideoEditor.addMediaItem(mediaItem3);
+            }
+            if (i % 4 == 3) {
+                final MediaImageItem mediaItem4 = new MediaImageItem(mVideoEditor,
+                    "m4"+ i, ImageItemFileName4, 20000, renderingMode);
+                mVideoEditor.addMediaItem(mediaItem4);
+            }
+            if (i % 10 == 0) {
+                getAfterMemory_updateLog(loggingInfo, false, i);
+            }
+        }
+        getAfterMemory_updateLog(loggingInfo, false, i);
+
+        /** Remove items and check for memory leak if any */
+        getBeginMemory();
+        for ( i = 0; i < 50; i++) {
+            if (i % 4 == 0) {
+                mVideoEditor.removeMediaItem("m1"+i);
+            }
+            if (i % 4 == 1) {
+                mVideoEditor.removeMediaItem("m2"+i);
+            }
+            if (i % 4 == 2) {
+                mVideoEditor.removeMediaItem("m3"+i);
+            }
+            if (i % 4 == 3) {
+                mVideoEditor.removeMediaItem("m4"+i);
+            }
+            if (i % 10 == 0) {
+                getAfterMemory_updateLog(loggingInfo, true, i);
+            }
+        }
+        getAfterMemory_updateLog(loggingInfo, true, i);
+    }
+
+    /**
+     * To stress test transition
+     *
+     * @throws Exception
+     */
+    // TODO : remove TC_STR_003
+    @LargeTest
+    public void testStressAddRemoveTransition() throws Exception {
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final String VideoItemFileName1 = INPUT_FILE_PATH +
+            "H264_BP_800x480_15fps_512kbps_1_17.mp4";
+        final String ImageItemFileName2 = INPUT_FILE_PATH +
+            "IMG_1600x1200.jpg";
+        final String VideoItemFileName3 = INPUT_FILE_PATH +
+            "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
+        final String maskFilename = INPUT_FILE_PATH +
+            "TransitionSpiral_QVGA.jpg";
+        final String[] loggingInfo = new String[1];
+        int i = 0;
+        writeTestCaseHeader("testStressAddRemoveTransition");
+        getBeginMemory();
+        for ( i = 0; i < 50; i++) {
+            if (i % 4 == 0) {
+                final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
+                    "m1"+i, VideoItemFileName1, renderingMode);
+                mVideoEditor.addMediaItem(mediaItem1);
+                mediaItem1.setExtractBoundaries(0, 10000);
+                final TransitionCrossfade tranCrossfade =
+                    new TransitionCrossfade("transCF" + i, null,
+                        mediaItem1, 5000, Transition.BEHAVIOR_MIDDLE_FAST);
+                mVideoEditor.addTransition(tranCrossfade);
+            }
+            if (i % 4 == 1) {
+                final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
+                    "m1"+i, VideoItemFileName1, renderingMode);
+                mVideoEditor.addMediaItem(mediaItem1);
+                mediaItem1.setExtractBoundaries(0, 10000);
+
+                final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
+                    "m2" +i, ImageItemFileName2, 10000, renderingMode);
+                mVideoEditor.addMediaItem(mediaItem2);
+
+                final TransitionAlpha transitionAlpha =
+                    mVideoEditorHelper.createTAlpha("transAlpha" + i, mediaItem1,
+                        mediaItem2, 5000, Transition.BEHAVIOR_SPEED_UP,
+                        maskFilename, 10, false);
+                transitionAlpha.setDuration(4000);
+                mVideoEditor.addTransition(transitionAlpha);
+            }
+            if (i % 4 == 2) {
+                final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
+                    "m2" + i, ImageItemFileName2, 10000, renderingMode);
+                mVideoEditor.addMediaItem(mediaItem2);
+
+                final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor,
+                    "m3" + i, VideoItemFileName3, renderingMode);
+                mVideoEditor.addMediaItem(mediaItem3);
+
+                mediaItem3.setExtractBoundaries(0, 10000);
+                final TransitionAlpha transitionAlpha =
+                    mVideoEditorHelper.createTAlpha("transAlpha" + i, mediaItem2,
+                        mediaItem3, 5000, Transition.BEHAVIOR_SPEED_UP,
+                        maskFilename, 10, false);
+                transitionAlpha.setDuration(4000);
+                mVideoEditor.addTransition(transitionAlpha);
+
+                mediaItem3.setExtractBoundaries(0, 6000);
+
+                final TransitionSliding transition2And3 =
+                    mVideoEditorHelper.createTSliding("transSlide" +i, mediaItem2,
+                        mediaItem3, 3000, Transition.BEHAVIOR_MIDDLE_FAST,
+                        TransitionSliding.DIRECTION_LEFT_OUT_RIGHT_IN);
+                mVideoEditor.addTransition(transition2And3);
+            }
+            if (i % 4 == 3) {
+                final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor,
+                    "m3" + i, VideoItemFileName3, renderingMode);
+                mVideoEditor.addMediaItem(mediaItem3);
+                mediaItem3.setExtractBoundaries(0, 5000);
+
+                final TransitionFadeBlack transition3 =
+                    mVideoEditorHelper.createTFadeBlack("transFB" +i, mediaItem3,
+                        null, 2500, Transition.BEHAVIOR_SPEED_UP);
+                transition3.setDuration(500);
+                mVideoEditor.addTransition(transition3);
+            }
+            if (i % 10 == 0) {
+                getAfterMemory_updateLog(loggingInfo, false, i);
+            }
+        }
+        getAfterMemory_updateLog(loggingInfo, false, i);
+
+        /** Remove items and check for memory leak if any */
+        getBeginMemory();
+        for ( i = 0; i < 50; i++) {
+            if (i % 4 == 0) {
+                mVideoEditor.removeTransition("transCF" + i);
+                mVideoEditor.removeMediaItem("m1" + i);
+            }
+            if (i % 4 == 1) {
+                mVideoEditor.removeTransition("transAlpha" + i);
+                mVideoEditor.removeMediaItem("m1" + i);
+                mVideoEditor.removeMediaItem("m2" + i);
+            }
+            if (i % 4 == 2) {
+                mVideoEditor.removeTransition("transSlide" +i);
+                mVideoEditor.removeMediaItem("m2" + i);
+                mVideoEditor.removeMediaItem("m3" + i);
+            }
+            if (i % 4 == 3) {
+                mVideoEditor.removeMediaItem("m3" + i);
+            }
+            if (i % 10 == 0) {
+                getAfterMemory_updateLog(loggingInfo, true, i);
+            }
+        }
+        getAfterMemory_updateLog(loggingInfo, true, i);
+    }
+
+    /**
+     * To stress test overlay
+     *
+     * @throws Exception
+     */
+    // TODO : remove TC_STR_004
+    @LargeTest
+    public void testStressAddRemoveOverlay() throws Exception {
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final String VideoItemFileName1 = INPUT_FILE_PATH +
+            "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
+        final String ImageItemFileName2 = INPUT_FILE_PATH +
+            "IMG_640x480.jpg";
+        final String OverlayFile3 = INPUT_FILE_PATH +
+            "IMG_640x480_Overlay1.png";
+        final String OverlayFile4 = INPUT_FILE_PATH +
+            "IMG_640x480_Overlay2.png";
+        final String[] loggingInfo = new String[1];
+        int i = 0;
+        final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
+            "m1", VideoItemFileName1, renderingMode);
+        mVideoEditor.addMediaItem(mediaItem1);
+
+        final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
+            "m2", ImageItemFileName2, 10000, renderingMode);
+        mVideoEditor.addMediaItem(mediaItem2);
+        writeTestCaseHeader("testStressAddRemoveOverlay");
+        getBeginMemory();
+        for ( i = 0; i < 50; i++) {
+            if (i % 3 == 0) {
+                mediaItem1.setExtractBoundaries(0, 10000);
+                final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(
+                    OverlayFile3, 640, 480);
+                final OverlayFrame overlayFrame =
+                    mVideoEditorHelper.createOverlay(mediaItem1, "overlay" + i,
+                        mBitmap, 1000, 5000);
+                mediaItem1.addOverlay(overlayFrame);
+                mediaItem1.removeOverlay("overlay"+i);
+            }
+            if (i % 3 == 1) {
+                final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(
+                    OverlayFile4, 640, 480);
+                final OverlayFrame overlayFrame =
+                    mVideoEditorHelper.createOverlay(mediaItem2, "overlay" + i,
+                        mBitmap, 1000, 5000);
+                mediaItem2.addOverlay(overlayFrame);
+                mediaItem2.removeOverlay("overlay"+i);
+            }
+            if (i % 3 == 2) {
+                mediaItem1.setExtractBoundaries(0, 10000);
+                final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(
+                    OverlayFile4, 640, 480);
+                final OverlayFrame overlayFrame =
+                    mVideoEditorHelper.createOverlay(mediaItem1, "overlay" + i,
+                        mBitmap, 0, mediaItem1.getDuration());
+                mediaItem1.addOverlay(overlayFrame);
+                mediaItem1.removeOverlay("overlay"+i);
+            }
+            if (i % 10 == 0) {
+                getAfterMemory_updateLog(loggingInfo, false, i);
+            }
+        }
+        getAfterMemory_updateLog(loggingInfo, false, i);
+    }
+
+    /**
+     * To stress test Effects
+     *
+     * @throws Exception
+     */
+    // TODO : remove TC_STR_005
+    @LargeTest
+    public void testStressAddRemoveEffects() throws Exception {
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final String VideoItemFileName1 = INPUT_FILE_PATH +
+            "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp";
+        final String ImageItemFileName2 = INPUT_FILE_PATH +
+            "IMG_1600x1200.jpg";
+        final String[] loggingInfo = new String[1];
+        final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
+            "m1", VideoItemFileName1, renderingMode);
+        mVideoEditor.addMediaItem(mediaItem1);
+        final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
+            "m2", ImageItemFileName2, 10000, renderingMode);
+        int i = 0;
+        mVideoEditor.addMediaItem(mediaItem2);
+        writeTestCaseHeader("testStressAddRemoveEffects");
+        getBeginMemory();
+        for ( i = 0; i < 50; i++) {
+            if (i % 5 == 0) {
+                mediaItem1.setExtractBoundaries(10000, 30000);
+                final EffectColor effectColor1 =
+                    mVideoEditorHelper.createEffectItem(mediaItem1, "effect1"+i,
+                        10000, (mediaItem1.getTimelineDuration()-1000),
+                        EffectColor.TYPE_COLOR, EffectColor.GREEN);
+                mediaItem1.addEffect(effectColor1);
+            }
+            if (i % 5 == 1) {
+                mediaItem2.setDuration(20000);
+                final EffectColor effectColor1 =
+                    mVideoEditorHelper.createEffectItem(mediaItem2, "effect1"+i,
+                        0, 4000, EffectColor.TYPE_GRADIENT, EffectColor.GRAY);
+                mediaItem2.addEffect(effectColor1);
+            }
+            if (i % 5 == 2) {
+                mediaItem1.setExtractBoundaries(10000, 30000);
+                final EffectColor effectColor1 =
+                    mVideoEditorHelper.createEffectItem(mediaItem1, "effect1"+i,
+                        (mediaItem1.getTimelineDuration() - 4000), 4000,
+                        EffectColor.TYPE_SEPIA, 0);
+                mediaItem1.addEffect(effectColor1);
+            }
+            if (i % 5 == 3) {
+                mediaItem2.setDuration(20000);
+                final EffectColor effectColor1 =
+                    mVideoEditorHelper.createEffectItem(mediaItem2, "effect1"+i,
+                        10000, 4000, EffectColor.TYPE_NEGATIVE, 0);
+                mediaItem2.addEffect(effectColor1);
+            }
+            if (i % 5 == 4) {
+                mediaItem2.setDuration(20000);
+                final Rect startRect = new Rect((mediaItem2.getHeight() / 3),
+                    (mediaItem2.getWidth() / 3), (mediaItem2.getHeight() / 2),
+                    (mediaItem2.getWidth() / 2));
+                final Rect endRect = new Rect(0, 0, mediaItem2.getWidth(),
+                    mediaItem2.getHeight());
+                final EffectKenBurns kbEffectOnMediaItem = new EffectKenBurns(
+                    mediaItem2, "KBOnM2" + i, startRect, endRect, 500,
+                    (mediaItem2.getDuration() - 500));
+                mediaItem2.addEffect(kbEffectOnMediaItem);
+            }
+            if (i % 10 == 0) {
+                getAfterMemory_updateLog(loggingInfo, false, i);
+            }
+        }
+        getAfterMemory_updateLog(loggingInfo, false, i);
+
+        /** Remove items and check for memory leak if any */
+        getBeginMemory();
+        for ( i = 0; i < 50; i++) {
+            if (i % 5 == 0) {
+                mediaItem1.removeEffect("effect1"+i);
+            }
+            if (i % 5 == 1) {
+                mediaItem1.removeEffect("effect1"+i);
+            }
+            if (i % 5 == 2) {
+                mediaItem1.removeEffect("effect1"+i);
+            }
+            if (i % 5 == 3) {
+                mediaItem1.removeEffect("effect1"+i);
+            }
+            if (i % 5 == 4) {
+                mediaItem1.removeEffect("KBOnM2"+i);
+            }
+            if (i % 10 == 0) {
+                getAfterMemory_updateLog(loggingInfo, true, i);
+            }
+        }
+        getAfterMemory_updateLog(loggingInfo, true, i);
+    }
+
+    /**
+     * This method will test thumbnail list extraction in a loop = 200 for Video
+     * Item
+     *
+     * @throws Exception
+     */
+    // TODO : remove TC_STR_006
+    @LargeTest
+    public void testStressThumbnailVideoItem() 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 String[] loggingInfo = new String[1];
+        int i = 0;
+        final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
+            "m1", videoItemFileName, renderingMode);
+        writeTestCaseHeader("testStressThumbnailVideoItem");
+        getBeginMemory();
+        for ( i = 0; i < 50; i++) {
+            if (i % 4 == 0) {
+                final Bitmap[] thumbNails =
+                    mediaVideoItem.getThumbnailList(mediaVideoItem.getWidth()*3,
+                        mediaVideoItem.getHeight()*2, i, 5000, 2);
+                // Recycle this Bitmap array
+                for (int i1 = 0; i1 < thumbNails.length; i1++) {
+                    thumbNails[i1].recycle();
+                }
+            }
+            if (i % 4 == 1) {
+                final Bitmap[] thumbNails =
+                    mediaVideoItem.getThumbnailList(mediaVideoItem.getWidth()/2,
+                        mediaVideoItem.getHeight() * 3, i, 5000, 2);
+                // Recycle this Bitmap array
+                for (int i1 = 0; i1 < thumbNails.length; i1++) {
+                    thumbNails[i1].recycle();
+                }
+            }
+            if (i % 4 == 2) {
+                final Bitmap[] thumbNails =
+                    mediaVideoItem.getThumbnailList(mediaVideoItem.getWidth()*2,
+                        mediaVideoItem.getHeight() / 3, i, 5000, 2);
+                // Recycle this Bitmap array
+                for (int i1 = 0; i1 < thumbNails.length; i1++) {
+                    thumbNails[i1].recycle();
+                }
+            }
+            if (i % 4 == 3) {
+                final Bitmap[] thumbNails =
+                    mediaVideoItem.getThumbnailList(mediaVideoItem.getWidth(),
+                        mediaVideoItem.getHeight(), i, 5000, 2);
+                // Recycle this Bitmap array
+                for (int i1 = 0; i1 < thumbNails.length; i1++) {
+                    thumbNails[i1].recycle();
+                }
+            }
+            if (i % 10 == 0) {
+                getAfterMemory_updateLog(loggingInfo, false, i);
+            }
+        }
+        getAfterMemory_updateLog(loggingInfo, false, i);
+    }
+
+    /**
+     * To stress test media properties
+     *
+     * @throws Exception
+     */
+    // TODO : remove TC_STR_007
+    @LargeTest
+    public void testStressMediaProperties() throws Exception {
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final String VideoItemFileName1 = INPUT_FILE_PATH +
+            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
+        final String ImageItemFileName2 = INPUT_FILE_PATH +
+            "IMG_640x480.jpg";
+        final String AudioItemFileName3 = INPUT_FILE_PATH +
+            "AACLC_44.1kHz_256kbps_s_1_17.mp4";
+        final String[] loggingInfo = new String[1];
+        int i = 0;
+        final int videoAspectRatio = MediaProperties.ASPECT_RATIO_3_2;
+        final int videoFileType = MediaProperties.FILE_MP4;
+        final int videoCodecType = MediaProperties.VCODEC_H264BP;
+        final int videoDuration = 77366;
+        final int videoProfile = MediaProperties.H264_PROFILE_0_LEVEL_1_3;
+        final int videoHeight = MediaProperties.HEIGHT_720;
+        final int videoWidth = 1080;
+
+        final int imageAspectRatio = MediaProperties.ASPECT_RATIO_4_3;
+        final int imageFileType = MediaProperties.FILE_JPEG;
+        final int imageWidth = 640;
+        final int imageHeight = MediaProperties.HEIGHT_480;
+
+        final int audioDuration = 77554;
+        final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
+        final int audioSamplingFrequency = 44100;
+        final int audioChannel = 2;
+        writeTestCaseHeader("testStressMediaProperties");
+        getBeginMemory();
+        for ( i = 0; i < 50; i++) {
+            if (i % 3 == 0) {
+                final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
+                    "m1" + i, VideoItemFileName1, renderingMode);
+                mVideoEditor.addMediaItem(mediaItem1);
+                mediaItem1.setExtractBoundaries(0, 20000);
+                assertEquals("Aspect Ratio Mismatch",
+                    videoAspectRatio, mediaItem1.getAspectRatio());
+                assertEquals("File Type Mismatch",
+                    videoFileType, mediaItem1.getFileType());
+                assertEquals("VideoCodec Mismatch",
+                    videoCodecType, mediaItem1.getVideoType());
+                assertEquals("duration Mismatch",
+                    videoDuration, mediaItem1.getDuration());
+                assertEquals("Video Profile ",
+                    videoProfile, mediaItem1.getVideoProfile());
+                assertEquals("Video height ",
+                    videoHeight, mediaItem1.getHeight());
+                assertEquals("Video width ",
+                    videoWidth, mediaItem1.getWidth());
+                mVideoEditor.removeMediaItem("m1" + i);
+            }
+            if (i % 3 == 1) {
+                final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
+                    "m2" + i, ImageItemFileName2, 10000, renderingMode);
+                mVideoEditor.addMediaItem(mediaItem2);
+                assertEquals("Aspect Ratio Mismatch",
+                    imageAspectRatio, mediaItem2.getAspectRatio());
+                assertEquals("File Type Mismatch",
+                    imageFileType, mediaItem2.getFileType());
+                assertEquals("Image height",
+                    imageHeight, mediaItem2.getHeight());
+                assertEquals("Image width",
+                    imageWidth, mediaItem2.getWidth());
+                mVideoEditor.removeMediaItem("m2" + i);
+            }
+            if (i % 3 == 2) {
+                final AudioTrack mediaItem3 = new AudioTrack(mVideoEditor,
+                    "m3" + i, AudioItemFileName3);
+                mVideoEditor.addAudioTrack(mediaItem3);
+                assertEquals("AudioType Mismatch", audioCodecType,
+                    mediaItem3.getAudioType());
+                assertEquals("Audio Sampling", audioSamplingFrequency,
+                    mediaItem3.getAudioSamplingFrequency());
+                assertEquals("Audio Channels",
+                    audioChannel, mediaItem3.getAudioChannels());
+                assertEquals("duration Mismatch", audioDuration,
+                    mediaItem3.getDuration());
+                mVideoEditor.removeAudioTrack("m3" + i);
+            }
+            if (i % 10 == 0) {
+                getAfterMemory_updateLog(loggingInfo, false, i);
+            }
+        }
+        getAfterMemory_updateLog(loggingInfo, false, i);
+    }
+
+    /**
+     * To stress test insert and move of mediaitems
+     *
+     * @throws Exception
+     */
+    // TODO : remove TC_STR_008
+    @LargeTest
+    public void testStressInsertMovieItems() throws Exception {
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final String VideoItemFileName1 = INPUT_FILE_PATH +
+            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
+        final String VideoItemFileName2 = INPUT_FILE_PATH +
+            "H264_BP_800x480_15fps_512kbps_1_17.mp4";
+        final String VideoItemFileName3 = INPUT_FILE_PATH +
+            "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp";
+        final String[] loggingInfo = new String[1];
+        int i = 0;
+        writeTestCaseHeader("testStressInsertMoveItems");
+
+        final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
+            "m1", VideoItemFileName1, renderingMode);
+        mVideoEditor.addMediaItem(mediaItem1);
+        mediaItem1.setExtractBoundaries(0, 10000);
+
+        final MediaVideoItem mediaItem2 = new MediaVideoItem(mVideoEditor,
+            "m2", VideoItemFileName2, renderingMode);
+        mVideoEditor.addMediaItem(mediaItem2);
+        mediaItem2.setExtractBoundaries(0, 15000);
+
+        getBeginMemory();
+        for ( i = 0; i < 50; i++) {
+            final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor,
+                "m3" + i, VideoItemFileName3, renderingMode);
+            mediaItem3.setExtractBoundaries(0, 15000);
+            mVideoEditor.insertMediaItem(mediaItem3, "m1");
+            mVideoEditor.moveMediaItem("m2", "m3" + i);
+            if (i % 10 == 0) {
+                getAfterMemory_updateLog(loggingInfo, false, i);
+            }
+        }
+        getAfterMemory_updateLog(loggingInfo, false, i);
+
+        /** Remove items and check for memory leak if any */
+        getBeginMemory();
+        for ( i = 0; i < 50; i++) {
+            mVideoEditor.removeMediaItem("m3" + i);
+            if (i % 10 == 0) {
+                getAfterMemory_updateLog(loggingInfo, true, i);
+            }
+        }
+            mVideoEditor.removeMediaItem("m2");
+            mVideoEditor.removeMediaItem("m1");
+        getAfterMemory_updateLog(loggingInfo, true, i);
+    }
+
+    /**
+     * To stress test : load and save
+     *
+     * @throws Exception
+     */
+    // TODO : remove TC_STR_009
+    @LargeTest
+    public void testStressLoadAndSave() throws Exception {
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final String VideoItemFileName1 = INPUT_FILE_PATH +
+            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
+        final String VideoItemFileName2 = INPUT_FILE_PATH +
+            "H264_BP_800x480_15fps_512kbps_1_17.mp4";
+        final String VideoItemFileName3 = INPUT_FILE_PATH +
+            "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp";
+        final String ImageItemFileName4 = INPUT_FILE_PATH +
+            "IMG_640x480.jpg";
+        final String ImageItemFileName5 = INPUT_FILE_PATH +
+            "IMG_176x144.jpg";
+        final String OverlayFile6 = INPUT_FILE_PATH +
+            "IMG_640x480_Overlay1.png";
+        final String[] loggingInfo = new String[1];
+        int i = 0;
+        final String[] projectPath = new String[10];
+        writeTestCaseHeader("testStressLoadAndSave");
+        getBeginMemory();
+        for( i=0; i < 10; i++){
+
+            projectPath[i] =
+                mVideoEditorHelper.createRandomFile(PROJECT_LOCATION);
+            final VideoEditor mVideoEditor1 =
+                mVideoEditorHelper.createVideoEditor(projectPath[i]);
+
+            final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor1,
+                "m1", VideoItemFileName1, renderingMode);
+            mVideoEditor1.addMediaItem(mediaItem1);
+            mediaItem1.setExtractBoundaries(0, 10000);
+
+            final MediaVideoItem mediaItem2 = new MediaVideoItem(mVideoEditor1,
+                "m2", VideoItemFileName2, renderingMode);
+            mVideoEditor1.addMediaItem(mediaItem2);
+            mediaItem2.setExtractBoundaries(mediaItem2.getDuration()/4,
+                mediaItem2.getDuration()/2);
+
+            final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor1,
+                "m3", VideoItemFileName3, renderingMode);
+            mVideoEditor1.addMediaItem(mediaItem3);
+            mediaItem3.setExtractBoundaries(mediaItem3.getDuration()/2,
+                mediaItem3.getDuration());
+
+            final MediaImageItem mediaItem4 = new MediaImageItem(mVideoEditor1,
+                "m4", ImageItemFileName4, 5000, renderingMode);
+            mVideoEditor1.addMediaItem(mediaItem4);
+
+            final MediaImageItem mediaItem5 = new MediaImageItem(mVideoEditor1,
+                "m5", ImageItemFileName5, 5000, renderingMode);
+            mVideoEditor1.addMediaItem(mediaItem5);
+
+            final EffectColor effectColor1 =
+                mVideoEditorHelper.createEffectItem(mediaItem3, "effect1",
+                    10000, 2000, EffectColor.TYPE_COLOR, EffectColor.GREEN);
+            mediaItem3.addEffect(effectColor1);
+
+            final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(OverlayFile6,
+                640, 480);
+            final OverlayFrame overlayFrame =
+                mVideoEditorHelper.createOverlay(mediaItem4, "overlay",
+                    mBitmap, 4000, 1000);
+            mediaItem4.addOverlay(overlayFrame);
+
+            final TransitionCrossfade tranCrossfade =
+                new TransitionCrossfade("transCF", mediaItem1,
+                    mediaItem2, 5000, Transition.BEHAVIOR_MIDDLE_FAST);
+            mVideoEditor1.addTransition(tranCrossfade);
+
+            final EffectColor effectColor2 =
+                mVideoEditorHelper.createEffectItem(mediaItem4, "effect2", 0,
+                    mediaItem4.getDuration(), EffectColor.TYPE_COLOR,
+                    EffectColor.PINK);
+            mediaItem4.addEffect(effectColor2);
+
+            mVideoEditor1.generatePreview(new MediaProcessingProgressListener() {
+                public void onProgress(Object item, int action, int progress) {
+                }
+            });
+
+            mVideoEditor1.save();
+            mVideoEditor1.release();
+
+            getAfterMemory_updateLog(loggingInfo, false, i);
+        }
+        getAfterMemory_updateLog(loggingInfo, false, i);
+
+        /** Remove items and check for memory leak if any */
+        getBeginMemory();
+        for( i=0; i<10; i++){
+            final VideoEditor mVideoEditor1b =
+                VideoEditorFactory.load(projectPath[i], true);
+            List<MediaItem> mediaList = mVideoEditor1b.getAllMediaItems();
+            assertEquals("Media Item List Size", 5, mediaList.size());
+
+            mediaList.get(3).removeEffect("effect1");
+            mediaList.get(3).removeEffect("effect2");
+            mediaList.get(2).removeOverlay("overlay");
+            mVideoEditor1b.removeTransition("transCF");
+            mVideoEditor1b.removeMediaItem("m5");
+            mVideoEditor1b.removeMediaItem("m4");
+            mVideoEditor1b.removeMediaItem("m3");
+            mVideoEditor1b.removeMediaItem("m2");
+            mVideoEditor1b.removeMediaItem("m1");
+            mVideoEditor1b.release();
+            getAfterMemory_updateLog(loggingInfo, true, i);
+        }
+        getAfterMemory_updateLog(loggingInfo, true, i);
+    }
+
+    /**
+     * To stress test : Multiple Export
+     *
+     * @throws Exception
+     */
+    // TODO : remove TC_STR_010
+    @LargeTest
+    public void testStressMultipleExport() throws Exception {
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final String VideoItemFileName1 = INPUT_FILE_PATH +
+            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
+        final String VideoItemFileName2 = INPUT_FILE_PATH +
+            "H264_BP_800x480_15fps_512kbps_1_17.mp4";
+        final String[] loggingInfo = new String[1];
+        final String outFilename = mVideoEditorHelper.createRandomFile(
+            mVideoEditor.getPath() + "/") + ".3gp";
+        int i = 0;
+        writeTestCaseHeader("testStressMultipleExport");
+        getBeginMemory();
+        final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
+            "m1", VideoItemFileName1, renderingMode);
+        mVideoEditor.addMediaItem(mediaItem1);
+        mediaItem1.setExtractBoundaries(0, 10000);
+
+        final MediaVideoItem mediaItem2 = new MediaVideoItem(mVideoEditor,
+            "m2", VideoItemFileName2, renderingMode);
+        mVideoEditor.addMediaItem(mediaItem2);
+        mediaItem2.setExtractBoundaries(0, 15000);
+
+        for ( i = 0; i < 50; i++) {
+            if(i%4 ==0){
+                final int aspectRatio = MediaProperties.ASPECT_RATIO_4_3;
+                mVideoEditor.setAspectRatio(aspectRatio);
+                mVideoEditor.export(outFilename, MediaProperties.HEIGHT_480,
+                    MediaProperties.BITRATE_256K,MediaProperties.ACODEC_AAC_LC,
+                        MediaProperties.VCODEC_H263,
+                        new ExportProgressListener() {
+                        public void onProgress(VideoEditor ve, String outFileName,
+                            int progress) {
+                        }
+                    });
+            }
+            if(i%4 ==1){
+                final int aspectRatio = MediaProperties.ASPECT_RATIO_5_3;
+                mVideoEditor.setAspectRatio(aspectRatio);
+                mVideoEditor.export(outFilename, MediaProperties.HEIGHT_144,
+                    MediaProperties.BITRATE_384K,MediaProperties.ACODEC_AAC_LC,
+                        MediaProperties.VCODEC_MPEG4,
+                        new ExportProgressListener() {
+                        public void onProgress(VideoEditor ve, String outFileName,
+                            int progress) {
+                        }
+                    });
+            }
+            if(i%4 ==2){
+                final int aspectRatio = MediaProperties.ASPECT_RATIO_11_9;
+                mVideoEditor.setAspectRatio(aspectRatio);
+                mVideoEditor.export(outFilename, MediaProperties.HEIGHT_144,
+                    MediaProperties.BITRATE_512K,MediaProperties.ACODEC_AAC_LC,
+                        MediaProperties.VCODEC_H264BP,
+                        new ExportProgressListener() {
+                        public void onProgress(VideoEditor ve, String outFileName,
+                            int progress) {
+                        }
+                    });
+            }
+            if(i%4 ==3){
+                final int aspectRatio = MediaProperties.ASPECT_RATIO_3_2;
+                mVideoEditor.setAspectRatio(aspectRatio);
+                mVideoEditor.export(outFilename, MediaProperties.HEIGHT_480,
+                    MediaProperties.BITRATE_800K,MediaProperties.ACODEC_AAC_LC,
+                        MediaProperties.VCODEC_H264BP,
+                        new ExportProgressListener() {
+                        public void onProgress(VideoEditor ve, String outFileName,
+                            int progress) {
+                        }
+                    });
+            }
+            if (i % 10 == 0) {
+                getAfterMemory_updateLog(loggingInfo, false, i);
+            }
+        }
+        getAfterMemory_updateLog(loggingInfo, false, i);
+
+        /** Remove items and check for memory leak if any */
+        getBeginMemory();
+        mVideoEditor.removeMediaItem("m2");
+        mVideoEditor.removeMediaItem("m1");
+
+        getAfterMemory_updateLog(loggingInfo, true, i);
+    }
+
+    /**
+     * To stress test Media Item,Overlays,Transitions and Ken Burn
+     *
+     * @throws Exception
+     */
+    // TODO : remove TC_STR_011
+    @LargeTest
+    public void testStressOverlayTransKenBurn() throws Exception {
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final String VideoItemFileName1 = INPUT_FILE_PATH +
+            "H264_BP_640x480_30fps_256kbps_1_17.mp4";
+        final String ImageItemFileName2 = INPUT_FILE_PATH +
+            "IMG_640x480.jpg";
+        final String OverlayFile3 = INPUT_FILE_PATH +
+            "IMG_640x480_Overlay1.png";
+        final String audioFilename4 = INPUT_FILE_PATH +
+            "AACLC_44.1kHz_256kbps_s_1_17.mp4";
+        int i = 0;
+        final String[] loggingInfo = new String[1];
+        writeTestCaseHeader("testStressOverlayTransKenBurn");
+        getBeginMemory();
+        for ( i = 0; i < 10; i++) {
+            final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
+                "m1" + i, VideoItemFileName1, renderingMode);
+            mVideoEditor.addMediaItem(mediaItem1);
+            mediaItem1.setExtractBoundaries(0, 10000);
+
+            final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
+                "m2" + i, ImageItemFileName2, 10000, renderingMode);
+            mVideoEditor.addMediaItem(mediaItem2);
+
+            final EffectColor effectColor1 =
+                mVideoEditorHelper.createEffectItem(mediaItem1, "effect1"+i,
+                    (mediaItem1.getDuration() - 4000), 4000,
+                    EffectColor.TYPE_SEPIA, 0);
+            mediaItem1.addEffect(effectColor1);
+
+            final TransitionCrossfade tranCrossfade =
+                new TransitionCrossfade("transCF" + i, mediaItem1,
+                    mediaItem2, 4000, Transition.BEHAVIOR_MIDDLE_FAST);
+            mVideoEditor.addTransition(tranCrossfade);
+
+            final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(OverlayFile3,
+                640, 480);
+            final OverlayFrame overlayFrame =
+                mVideoEditorHelper.createOverlay(mediaItem1, "overlay" + i,
+                    mBitmap, 1000, 5000);
+            mediaItem1.addOverlay(overlayFrame);
+
+            final Rect startRect = new Rect((mediaItem2.getHeight() / 3),
+                (mediaItem2.getWidth() / 3), (mediaItem2.getHeight() / 2),
+                (mediaItem2.getWidth() / 2));
+            final Rect endRect = new Rect(0, 0, mediaItem2.getWidth(),
+                mediaItem2.getHeight());
+
+            final EffectKenBurns kbEffectOnMediaItem = new EffectKenBurns(
+                mediaItem2, "KBOnM2" + i, startRect, endRect, 500,
+                (mediaItem2.getDuration()-500));
+            mediaItem2.addEffect(kbEffectOnMediaItem);
+
+            if(i == 5) {
+                final AudioTrack audioTrack1 = new AudioTrack(mVideoEditor,
+                    "Audio Track1", audioFilename4);
+                mVideoEditor.addAudioTrack(audioTrack1);
+            }
+            getAfterMemory_updateLog(loggingInfo, false, i);
+        }
+        getAfterMemory_updateLog(loggingInfo, false, i);
+
+        /** Remove items and check for memory leak if any */
+        getBeginMemory();
+        for ( i = 0; i < 10; i++) {
+            MediaImageItem m2 = (MediaImageItem)mVideoEditor.getMediaItem("m2"+i);
+            MediaVideoItem m1 = (MediaVideoItem)mVideoEditor.getMediaItem("m1"+i);
+            m2.removeEffect("KBOnM2" + i);
+            m1.removeOverlay("overlay" + i);
+            mVideoEditor.removeTransition("transCF" + i);
+            m1.removeEffect("effect1" + i);
+            mVideoEditor.removeMediaItem("m2" + i);
+            mVideoEditor.removeMediaItem("m1" + i);
+            if(i == 5) {
+                mVideoEditor.removeAudioTrack("Audio Track1");
+            }
+            getAfterMemory_updateLog(loggingInfo, true, i);
+        }
+        getAfterMemory_updateLog(loggingInfo, true, i);
+    }
+
+    /**
+     * To test the performance : With an audio track with Video
+     *
+     * @throws Exception
+     */
+    // TODO : remove TC_STR_012
+    @LargeTest
+    public void testStressAudioTrackVideo() throws Exception {
+        final String videoItemFileName1 = INPUT_FILE_PATH +
+            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
+        final String audioFilename1 = INPUT_FILE_PATH +
+            "AACLC_44.1kHz_256kbps_s_1_17.mp4";
+        final String audioFilename2 = INPUT_FILE_PATH +
+            "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final int audioVolume = 50;
+        final String[] loggingInfo = new String[1];
+        int i = 1;
+        writeTestCaseHeader("testStressAudioTrackVideo");
+        getBeginMemory();
+        final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
+            "mediaItem1", videoItemFileName1, renderingMode);
+        mVideoEditor.addMediaItem(mediaVideoItem);
+
+        final AudioTrack audioTrack1 = new AudioTrack(mVideoEditor,
+            "Audio Track1", audioFilename1);
+        audioTrack1.disableDucking();
+        audioTrack1.setVolume(audioVolume);
+        mVideoEditor.addAudioTrack(audioTrack1);
+
+        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
+            public void onProgress(Object item, int action, int progress) {
+            }
+        });
+
+        mVideoEditor.removeAudioTrack("Audio Track1");
+
+        final AudioTrack audioTrack2 = new AudioTrack(mVideoEditor,
+            "Audio Track2", audioFilename2);
+        audioTrack2.enableLoop();
+
+        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
+            public void onProgress(Object item, int action, int progress) {
+            }
+        });
+        getAfterMemory_updateLog(loggingInfo, false, i);
+
+        /** Remove items and check for memory leak if any */
+        getBeginMemory();
+        mVideoEditor.removeMediaItem("mediaItem1");
+
+        getAfterMemory_updateLog(loggingInfo, true, i);
+    }
+
+    /**
+     * To Test Stress : Story Board creation with out preview or export
+     *
+     * @throws Exception
+     */
+    // TODO : remove TC_STR_013
+    @LargeTest
+    public void testStressStoryBoard() throws Exception {
+        final String videoItemFileName1 = INPUT_FILE_PATH +
+            "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_161kbps_s_0_26.mp4";
+        final String videoItemFileName2 = INPUT_FILE_PATH +
+            "MPEG4_SP_854x480_15fps_256kbps_AACLC_16khz_48kbps_s_0_26.mp4";
+        final String videoItemFileName3= INPUT_FILE_PATH +
+            "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
+        final String imageItemFileName4 = INPUT_FILE_PATH +
+            "IMG_1600x1200.jpg";
+        final String imageItemFileName5 = INPUT_FILE_PATH +
+            "IMG_176x144.jpg";
+        final String audioFilename6 = INPUT_FILE_PATH +
+            "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
+        final String audioFilename7 = INPUT_FILE_PATH +
+            "AACLC_44.1kHz_256kbps_s_1_17.mp4";
+
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final int audioVolume = 50;
+        final String[] loggingInfo = new String[1];
+        int i = 1;
+
+        writeTestCaseHeader("testStressStoryBoard");
+        getBeginMemory();
+        final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
+            "m1", videoItemFileName1, renderingMode);
+        mediaItem1.setExtractBoundaries(0, 10000);
+        mVideoEditor.addMediaItem(mediaItem1);
+
+        final MediaVideoItem mediaItem2 = new MediaVideoItem(mVideoEditor,
+            "m2", videoItemFileName2, renderingMode);
+        mediaItem2.setExtractBoundaries(mediaItem2.getDuration()/4,
+            mediaItem2.getDuration()/2);
+        mVideoEditor.addMediaItem(mediaItem2);
+
+        final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor,
+            "m3", videoItemFileName3, renderingMode);
+        mediaItem3.setExtractBoundaries(mediaItem3.getDuration()/2,
+            mediaItem3.getDuration());
+        mVideoEditor.addMediaItem(mediaItem3);
+
+        final MediaImageItem mediaItem4 = new MediaImageItem(mVideoEditor,
+            "m4", imageItemFileName4, 5000, renderingMode);
+        mVideoEditor.addMediaItem(mediaItem4);
+
+        final MediaImageItem mediaItem5 = new MediaImageItem(mVideoEditor,
+            "m5", imageItemFileName5, 5000, renderingMode);
+        mVideoEditor.addMediaItem(mediaItem5);
+
+        final TransitionCrossfade tranCrossfade =
+            new TransitionCrossfade("transCF", mediaItem2, mediaItem3, 2500,
+                Transition.BEHAVIOR_MIDDLE_FAST);
+        mVideoEditor.addTransition(tranCrossfade);
+
+        final TransitionCrossfade tranCrossfade1 =
+            new TransitionCrossfade("transCF1", mediaItem3, mediaItem4, 2500,
+                Transition.BEHAVIOR_MIDDLE_FAST);
+        mVideoEditor.addTransition(tranCrossfade1);
+
+        final AudioTrack audioTrack1 = new AudioTrack(mVideoEditor,
+            "Audio Track1", audioFilename6);
+        mVideoEditor.addAudioTrack(audioTrack1);
+
+        mVideoEditor.removeAudioTrack("Audio Track1");
+        final AudioTrack audioTrack2 = new AudioTrack(mVideoEditor,
+            "Audio Track2", audioFilename7);
+        mVideoEditor.addAudioTrack(audioTrack2);
+        audioTrack2.enableLoop();
+        getAfterMemory_updateLog(loggingInfo, false, i);
+
+        /** Remove items and check for memory leak if any */
+        getBeginMemory();
+        mVideoEditor.removeAudioTrack("Audio Track2");
+        mVideoEditor.removeTransition("transCF");
+        mVideoEditor.removeTransition("transCF1");
+        mVideoEditor.removeMediaItem("m5");
+        mVideoEditor.removeMediaItem("m4");
+        mVideoEditor.removeMediaItem("m3");
+        mVideoEditor.removeMediaItem("m2");
+        mVideoEditor.removeMediaItem("m1");
+
+        getAfterMemory_updateLog(loggingInfo, true, i);
+    }
+
+     /**
+     * To test the performance : With an audio track Only
+     *
+     * @throws Exception
+     */
+    // TODO : remove TC_STR_014
+    @LargeTest
+    public void testStressAudioTrackOnly() throws Exception {
+
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final String AudioItemFileName1 = INPUT_FILE_PATH +
+            "AACLC_44.1kHz_256kbps_s_1_17.mp4";
+        final String[] loggingInfo = new String[1];
+        int i = 0;
+        writeTestCaseHeader("testStressAudioTrackOnly");
+        getBeginMemory();
+        for ( i = 0; i < 50; i++) {
+            final AudioTrack mediaItem1 = new AudioTrack(mVideoEditor,
+                "m1" + i, AudioItemFileName1);
+            mVideoEditor.addAudioTrack(mediaItem1);
+            mediaItem1.enableLoop();
+            mVideoEditor.removeAudioTrack("m1" + i);
+            if (i % 10 == 0) {
+                getAfterMemory_updateLog(loggingInfo, false, i);
+            }
+        }
+        getAfterMemory_updateLog(loggingInfo, false, i);
+    }
+
+    /**
+     * This method will test thumbnail list extraction in a loop = 200 for Image
+     * Item
+     *
+     * @throws Exception
+     */
+    // TODO : remove TC_STR_016  -- New Test Case
+    @LargeTest
+    public void testStressThumbnailImageItem() throws Exception {
+        final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
+        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
+        final String[] loggingInfo = new String[1];
+        int i = 0;
+        final MediaImageItem mediaImageItem = new MediaImageItem(mVideoEditor,
+            "m1", imageItemFileName, 5000, renderingMode);
+        writeTestCaseHeader("testStressThumbnailImageItem");
+        getBeginMemory();
+        for ( i = 0; i < 50; i++) {
+            if (i % 4 == 0) {
+                final Bitmap[] thumbNails = mediaImageItem.getThumbnailList(
+                    mediaImageItem.getWidth() / 2 ,
+                    mediaImageItem.getHeight() / 2, i, 5000, 2);
+                // Recycle this Bitmap array
+                for (int i1 = 0; i1 < thumbNails.length; i1++) {
+                    thumbNails[i1].recycle();
+                }
+            }
+            if (i % 4 == 1) {
+                final Bitmap[] thumbNails = mediaImageItem.getThumbnailList(
+                    mediaImageItem.getWidth() / 2,
+                    mediaImageItem.getHeight() * 3, i, 5000, 2);
+                // Recycle this Bitmap array
+                for (int i1 = 0; i1 < thumbNails.length; i1++) {
+                    thumbNails[i1].recycle();
+                }
+            }
+            if (i % 4 == 2) {
+                final Bitmap[] thumbNails = mediaImageItem.getThumbnailList(
+                    mediaImageItem.getWidth() * 2,
+                    mediaImageItem.getHeight() / 3, i, 5000, 2);
+                // Recycle this Bitmap array
+                for (int i1 = 0; i1 < thumbNails.length; i1++) {
+                    thumbNails[i1].recycle();
+                }
+            }
+            if (i % 4 == 3) {
+                final Bitmap[] thumbNails = mediaImageItem.getThumbnailList(
+                    mediaImageItem.getWidth(),
+                    mediaImageItem.getHeight(), i, 5000, 2);
+                // Recycle this Bitmap array
+                for (int i1 = 0; i1 < thumbNails.length; i1++) {
+                    thumbNails[i1].recycle();
+                }
+            }
+            if (i % 10 == 0) {
+                getAfterMemory_updateLog(loggingInfo, false, i);
+            }
+        }
+        getAfterMemory_updateLog(loggingInfo, false, i);
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 156391e..84588b7 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2438,6 +2438,17 @@
         return mKeyguardMediator.isShowingAndNotHidden();
     }
 
+
+    /** {@inheritDoc} */
+    public boolean isKeyguardLocked() {
+        return keyguardOn();
+    }
+
+    /** {@inheritDoc} */
+    public boolean isKeyguardSecure() {
+        return mKeyguardMediator.isSecure();
+    }
+
     /** {@inheritDoc} */
     public boolean inKeyguardRestrictedKeyInputMode() {
         return mKeyguardMediator.isInputRestricted();
@@ -2463,6 +2474,15 @@
     public int rotationForOrientationLw(int orientation, int lastRotation,
             boolean displayEnabled) {
 
+        if (false) {
+            Slog.v(TAG, "rotationForOrientationLw(orient="
+                        + orientation + ", last=" + lastRotation
+                        + "); user=" + mUserRotation + " "
+                        + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
+                            ? "USER_ROTATION_LOCKED" : "")
+                        );
+        }
+
         if (mPortraitRotation < 0) {
             // Initialize the rotation angles for each orientation once.
             Display d = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
@@ -2581,15 +2601,15 @@
     // User rotation: to be used when all else fails in assigning an orientation to the device
     public void setUserRotationMode(int mode, int rot) {
         ContentResolver res = mContext.getContentResolver();
-        mUserRotationMode = mode;
+
+        // mUserRotationMode and mUserRotation will be assigned by the content observer
         if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
-            mUserRotation = rot;
-            Settings.System.putInt(res,
-                    Settings.System.ACCELEROMETER_ROTATION,
-                    0);
             Settings.System.putInt(res,
                     Settings.System.USER_ROTATION,
                     rot);
+            Settings.System.putInt(res,
+                    Settings.System.ACCELEROMETER_ROTATION,
+                    0);
         } else {
             Settings.System.putInt(res,
                     Settings.System.ACCELEROMETER_ROTATION,
@@ -2907,7 +2927,7 @@
                 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
         pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
                 pw.print(" mUserRotation="); pw.print(mUserRotation);
-                pw.print("mAllowAllRotations="); pw.println(mAllowAllRotations);
+                pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
         pw.print(prefix); pw.print("mAccelerometerDefault="); pw.print(mAccelerometerDefault);
                 pw.print(" mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
         pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
diff --git a/services/java/com/android/server/UsbService.java b/services/java/com/android/server/UsbService.java
index af4c425..1bc203e 100644
--- a/services/java/com/android/server/UsbService.java
+++ b/services/java/com/android/server/UsbService.java
@@ -44,7 +44,11 @@
 import java.util.HashMap;
 
 /**
- * <p>UsbService monitors for changes to USB state.
+ * UsbService monitors for changes to USB state.
+ * This includes code for both USB host support (where the android device is the host)
+ * as well as USB device support (android device is connected to a USB host).
+ * Accessory mode is a special case of USB device mode, where the android device is
+ * connected to a USB host that supports the android accessory protocol.
  */
 class UsbService extends IUsbManager.Stub {
     private static final String TAG = UsbService.class.getSimpleName();
@@ -63,7 +67,9 @@
     private static final String USB_COMPOSITE_CLASS_PATH =
             "/sys/class/usb_composite";
 
-    private static final int MSG_UPDATE = 0;
+    private static final int MSG_UPDATE_STATE = 0;
+    private static final int MSG_FUNCTION_ENABLED = 1;
+    private static final int MSG_FUNCTION_DISABLED = 2;
 
     // Delay for debouncing USB disconnects.
     // We often get rapid connect/disconnect events when enabling USB functions,
@@ -79,7 +85,6 @@
     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>();
 
@@ -90,26 +95,48 @@
     private final String[] mHostBlacklist;
 
     private boolean mSystemReady;
+
     private UsbAccessory mCurrentAccessory;
+    // functions to restore after exiting accessory mode
+    private final ArrayList<String> mAccessoryRestoreFunctions = new ArrayList<String>();
 
     private final Context mContext;
+    private final Object mLock = new Object();
 
-    private final void functionEnabled(String function, boolean enabled) {
-        synchronized (mEnabledFunctions) {
-            if (enabled) {
-                if (!mEnabledFunctions.contains(function)) {
-                    mEnabledFunctions.add(function);
+    /*
+     * Handles USB function enable/disable events (device mode)
+     */
+    private final void functionEnabledLocked(String function, boolean enabled) {
+        boolean enteringAccessoryMode =
+            (enabled && UsbManager.USB_FUNCTION_ACCESSORY.equals(function));
+
+        if (enteringAccessoryMode) {
+            // keep a list of functions to reenable after exiting accessory mode
+            mAccessoryRestoreFunctions.clear();
+            int count = mEnabledFunctions.size();
+            for (int i = 0; i < count; i++) {
+                String f = mEnabledFunctions.get(i);
+                // RNDIS should not be restored and adb is handled automatically
+                if (!UsbManager.USB_FUNCTION_RNDIS.equals(f) &&
+                    !UsbManager.USB_FUNCTION_ADB.equals(f) &&
+                    !UsbManager.USB_FUNCTION_ACCESSORY.equals(f)) {
+                    mAccessoryRestoreFunctions.add(f);
                 }
-                mDisabledFunctions.remove(function);
-            } else {
-                if (!mDisabledFunctions.contains(function)) {
-                    mDisabledFunctions.add(function);
-                }
-                mEnabledFunctions.remove(function);
             }
         }
+        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)) {
+        if (enteringAccessoryMode) {
             String[] strings = nativeGetAccessoryStrings();
             if (strings != null) {
                 Log.d(TAG, "entering USB accessory mode");
@@ -136,6 +163,9 @@
         }
     }
 
+    /*
+     * Listens for uevent messages from the kernel to monitor the USB state (device mode)
+     */
     private final UEventObserver mUEventObserver = new UEventObserver() {
         @Override
         public void onUEvent(UEventObserver.UEvent event) {
@@ -143,7 +173,7 @@
                 Slog.v(TAG, "USB UEVENT: " + event.toString());
             }
 
-            synchronized (this) {
+            synchronized (mLock) {
                 String name = event.get("SWITCH_NAME");
                 String state = event.get("SWITCH_STATE");
                 if (name != null && state != null) {
@@ -172,8 +202,11 @@
                     if (function != null && enabledStr != null) {
                         // 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);
-                        functionEnabled(function, enabled);
+                        int what = ("1".equals(enabledStr) ?
+                                MSG_FUNCTION_ENABLED : MSG_FUNCTION_DISABLED);
+                        Message msg = Message.obtain(mHandler, what);
+                        msg.obj = function;
+                        mHandler.sendMessage(msg);
                     }
                 }
             }
@@ -197,6 +230,7 @@
     private final void init() {
         char[] buffer = new char[1024];
 
+        // Read initial USB state (device mode)
         mConfiguration = -1;
         try {
             FileReader file = new FileReader(USB_CONNECTED_PATH);
@@ -217,21 +251,20 @@
         if (mConfiguration < 0)
             return;
 
+        // Read initial list of enabled and disabled functions (device mode)
         try {
-            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);
-                    }
+            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) {
@@ -251,6 +284,7 @@
         return false;
     }
 
+    /* returns true if the USB device should not be accessible by applications (host mode) */
     private boolean isBlackListed(int clazz, int subClass, int protocol) {
         // blacklist hubs
         if (clazz == UsbConstants.USB_CLASS_HUB) return true;
@@ -264,7 +298,7 @@
         return false;
     }
 
-    // called from JNI in monitorUsbHostBus()
+    /* Called from JNI in monitorUsbHostBus() to report new USB devices (host mode) */
     private void usbDeviceAdded(String deviceName, int vendorID, int productID,
             int deviceClass, int deviceSubclass, int deviceProtocol,
             /* array of quintuples containing id, class, subclass, protocol
@@ -279,7 +313,7 @@
             return;
         }
 
-        synchronized (mDevices) {
+        synchronized (mLock) {
             if (mDevices.get(deviceName) != null) {
                 Log.w(TAG, "device already on mDevices list: " + deviceName);
                 return;
@@ -338,9 +372,9 @@
         }
     }
 
-    // called from JNI in monitorUsbHostBus()
+    /* Called from JNI in monitorUsbHostBus to report USB device removal (host mode) */
     private void usbDeviceRemoved(String deviceName) {
-        synchronized (mDevices) {
+        synchronized (mLock) {
             UsbDevice device = mDevices.remove(deviceName);
             if (device != null) {
                 Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_DETACHED);
@@ -363,7 +397,7 @@
     }
 
     void systemReady() {
-        synchronized (this) {
+        synchronized (mLock) {
             if (mContext.getResources().getBoolean(
                     com.android.internal.R.bool.config_hasUsbHostSupport)) {
                 // start monitoring for connected USB devices
@@ -375,21 +409,27 @@
         }
     }
 
+    /*
+     * Sends a message to update the USB connected and configured state (device mode).
+     * If delayed is true, then we add a small delay in sending the message to debounce
+     * the USB connection when enabling USB tethering.
+     */
     private final void update(boolean delayed) {
-        mHandler.removeMessages(MSG_UPDATE);
-        mHandler.sendEmptyMessageDelayed(MSG_UPDATE, delayed ? UPDATE_DELAY : 0);
+        mHandler.removeMessages(MSG_UPDATE_STATE);
+        mHandler.sendEmptyMessageDelayed(MSG_UPDATE_STATE, delayed ? UPDATE_DELAY : 0);
     }
 
-    /* Returns a list of all currently attached USB devices */
+    /* Returns a list of all currently attached USB devices (host mdoe) */
     public void getDeviceList(Bundle devices) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_USB, null);
-        synchronized (mDevices) {
+        synchronized (mLock) {
             for (String name : mDevices.keySet()) {
                 devices.putParcelable(name, mDevices.get(name));
             }
         }
     }
 
+    /* Opens the specified USB device (host mode) */
     public ParcelFileDescriptor openDevice(String deviceName) {
         if (isBlackListed(deviceName)) {
             throw new SecurityException("USB device is on a restricted bus");
@@ -403,34 +443,37 @@
         return nativeOpenDevice(deviceName);
     }
 
+    /* returns the currently attached USB accessory (device mode) */
     public UsbAccessory getCurrentAccessory() {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_USB, null);
         return mCurrentAccessory;
     }
 
+    /* opens the currently attached USB accessory (device mode) */
     public ParcelFileDescriptor openAccessory() {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_USB, null);
         return nativeOpenAccessory();
     }
 
+    /*
+     * This handler is for deferred handling of events related to device mode and accessories.
+     */
     private final Handler mHandler = new Handler() {
-        private void addEnabledFunctions(Intent intent) {
-            synchronized (mEnabledFunctions) {
+        private void addEnabledFunctionsLocked(Intent intent) {
             // 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);
             }
         }
 
         @Override
         public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_UPDATE:
-                    synchronized (this) {
+            synchronized (mLock) {
+                switch (msg.what) {
+                    case MSG_UPDATE_STATE:
                         if (mConnected != mLastConnected || mConfiguration != mLastConfiguration) {
                             if (mConnected == 0 && mCurrentAccessory != null) {
                                 // turn off accessory mode when we are disconnected
@@ -438,6 +481,14 @@
                                         UsbManager.USB_FUNCTION_ACCESSORY, false)) {
                                     Log.d(TAG, "exited USB accessory mode");
 
+                                    // restore previously enabled functions
+                                    for (String function : mAccessoryRestoreFunctions) {
+                                        if (UsbManager.setFunctionEnabled(function, true)) {
+                                            Log.e(TAG, "could not reenable function " + function);
+                                        }
+                                    }
+                                    mAccessoryRestoreFunctions.clear();
+
                                     Intent intent = new Intent(
                                             UsbManager.ACTION_USB_ACCESSORY_DETACHED);
                                     intent.putExtra(UsbManager.EXTRA_ACCESSORY, mCurrentAccessory);
@@ -468,17 +519,23 @@
                             intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
                             intent.putExtra(UsbManager.USB_CONNECTED, mConnected != 0);
                             intent.putExtra(UsbManager.USB_CONFIGURATION, mConfiguration);
-                            addEnabledFunctions(intent);
+                            addEnabledFunctionsLocked(intent);
                             mContext.sendStickyBroadcast(intent);
                         }
-                    }
-                    break;
+                        break;
+                    case MSG_FUNCTION_ENABLED:
+                    case MSG_FUNCTION_DISABLED:
+                        functionEnabledLocked((String)msg.obj, msg.what == MSG_FUNCTION_ENABLED);
+                        break;
+                }
             }
         }
     };
 
+    // host support
     private native void monitorUsbHostBus();
     private native ParcelFileDescriptor nativeOpenDevice(String deviceName);
+    // accessory support
     private native String[] nativeGetAccessoryStrings();
     private native ParcelFileDescriptor nativeOpenAccessory();
 }
diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java
index 34f3618..b1833c4 100644
--- a/services/java/com/android/server/wm/InputMonitor.java
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -1,6 +1,19 @@
-/**
- * 
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
+
 package com.android.server.wm;
 
 import android.graphics.Rect;
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index a598ce9..b7cc324 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -4410,6 +4410,14 @@
         return mPolicy.inKeyguardRestrictedKeyInputMode();
     }
 
+    public boolean isKeyguardLocked() {
+        return mPolicy.isKeyguardLocked();
+    }
+
+    public boolean isKeyguardSecure() {
+        return mPolicy.isKeyguardSecure();
+    }
+
     public void closeSystemDialogs(String reason) {
         synchronized(mWindowMap) {
             for (int i=mWindows.size()-1; i>=0; i--) {
@@ -4822,21 +4830,25 @@
 
     public void freezeRotation() {
         if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
-                "setRotation()")) {
+                "freezeRotation()")) {
             throw new SecurityException("Requires SET_ORIENTATION permission");
         }
 
+        if (DEBUG_ORIENTATION) Slog.v(TAG, "freezeRotation: mRotation=" + mRotation);
+
         mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED, mRotation);
         setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false, 0);
     }
 
     public void thawRotation() {
         if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
-                "setRotation()")) {
+                "thawRotation()")) {
             throw new SecurityException("Requires SET_ORIENTATION permission");
         }
 
-        mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 0);
+        if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation);
+
+        mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 777); // rot not used
         setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false, 0);
     }