Merge "Fix problems with early ending of Sequencer"
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 1242bcf..458274f 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -349,6 +349,7 @@
     public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
         synchronized (mConstructorArgs) {
             final AttributeSet attrs = Xml.asAttributeSet(parser);
+            Context lastContext = (Context)mConstructorArgs[0];
             mConstructorArgs[0] = mContext;
             View result = root;
 
@@ -433,12 +434,12 @@
                         + ": " + e.getMessage());
                 ex.initCause(e);
                 throw ex;
+            } finally {
+                // Don't retain static reference on context.
+                mConstructorArgs[0] = lastContext;
+                mConstructorArgs[1] = null;
             }
 
-            // Told retain static reference on context.
-            mConstructorArgs[0] = null;
-            mConstructorArgs[1] = null;
-
             return result;
         }
     }
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index e36d9fe..a15b84e 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -1569,9 +1569,9 @@
                 // The idea here is to avoid having two or more samples with the
                 // same timestamp in the output file.
                 if (mTimeScale >= 1000000LL) {
-                    timestampUs += 1;
+                    timestampUs = lastTimestampUs + 1;
                 } else {
-                    timestampUs += (1000000LL + (mTimeScale >> 1)) / mTimeScale;
+                    timestampUs = lastTimestampUs + (1000000LL + (mTimeScale >> 1)) / mTimeScale;
                 }
 #endif
             }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
index c7f461e..46135ff 100755
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
@@ -27,7 +27,9 @@
 import com.android.mediaframeworktest.functional.MediaAudioManagerTest;
 import com.android.mediaframeworktest.functional.MediaAudioEffectTest;
 import com.android.mediaframeworktest.functional.MediaBassBoostTest;
+import com.android.mediaframeworktest.functional.MediaEnvReverbTest;
 import com.android.mediaframeworktest.functional.MediaEqualizerTest;
+import com.android.mediaframeworktest.functional.MediaPresetReverbTest;
 import com.android.mediaframeworktest.functional.MediaVirtualizerTest;
 import com.android.mediaframeworktest.functional.MediaVisualizerTest;
 import junit.framework.TestSuite;
@@ -62,7 +64,9 @@
         suite.addTestSuite(MediaAudioManagerTest.class);
         suite.addTestSuite(MediaAudioEffectTest.class);
         suite.addTestSuite(MediaBassBoostTest.class);
+        suite.addTestSuite(MediaEnvReverbTest.class);
         suite.addTestSuite(MediaEqualizerTest.class);
+        suite.addTestSuite(MediaPresetReverbTest.class);
         suite.addTestSuite(MediaVirtualizerTest.class);
         suite.addTestSuite(MediaVisualizerTest.class);
         return suite;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/EnergyProbe.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/EnergyProbe.java
new file mode 100644
index 0000000..d339e06
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/EnergyProbe.java
@@ -0,0 +1,106 @@
+/*
+ * 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.mediaframeworktest.functional;
+
+import android.media.Visualizer;
+import android.util.Log;
+
+/**
+ * The EnergyProbe class provides audio signal energy measurements based on the FFT returned
+ * by the Visualizer class. The measure is qualitative and not quantitative in that the returned
+ * value has no unit and is just proportional to the amount of energy present around the
+ * specified frequency.
+ */
+
+public class EnergyProbe {
+    private String TAG = "EnergyProbe";
+
+    private static int CAPTURE_SIZE = 1024;
+    private static int MEASURE_COUNT = 5;
+    private static int AVERAGE_COUNT = 3;
+
+    private Visualizer mVisualizer = null;
+    private int mMaxFrequency = 0;
+    private int mCapturePeriodMs;
+    private byte[] mFft = new byte[CAPTURE_SIZE];
+
+    public EnergyProbe(int session) {
+        try {
+            mVisualizer = new Visualizer(session);
+            if (mVisualizer != null) {
+                mVisualizer.setCaptureSize(CAPTURE_SIZE);
+                mMaxFrequency = mVisualizer.getSamplingRate() / 2000;
+                mCapturePeriodMs = 1000000 / mVisualizer.getMaxCaptureRate();
+            }
+        } catch (UnsupportedOperationException e) {
+            Log.e(TAG, "Error creating visualizer");
+        } catch (IllegalStateException e) {
+            Log.e(TAG, "Error configuring visualizer");
+        }
+    }
+
+    public int capture(int freq) throws InterruptedException {
+        int energy = 0;
+        int count = 0;
+
+        if (freq > mMaxFrequency) {
+            return 0;
+        }
+
+        if (mVisualizer != null) {
+            try {
+                mVisualizer.setEnabled(true);
+                for (int i = 0; i < MEASURE_COUNT; i++) {
+                    if (mVisualizer.getFft(mFft) == Visualizer.SUCCESS) {
+                        if (freq == mMaxFrequency) {
+                            energy += (int)mFft[0] * (int)mFft[0];
+                        } else {
+                            int bin = 2 * (freq * CAPTURE_SIZE / mMaxFrequency / 2);
+                            if (bin < 2) bin = 2;
+                            int tmp = 0;
+                            int j;
+                            for (j = 0;
+                                 (j < AVERAGE_COUNT) && ((bin + 2 * j) < CAPTURE_SIZE);
+                                 j++) {
+                                tmp += (int)mFft[bin + 2 * j] * (int)mFft[bin + 2 * j] +
+                                       (int)mFft[bin + 2 * j + 1] * (int)mFft[bin + 2 * j + 1];
+                            }
+                            // j is always != 0
+                            energy += tmp/j;
+                        }
+                        count++;
+                    }
+                    Thread.sleep(mCapturePeriodMs);
+                }
+                mVisualizer.setEnabled(false);
+            } catch (IllegalStateException e) {
+                Log.e(TAG, "Error capturing audio");
+            }
+        }
+        if (count == 0) {
+            return 0;
+        }
+        return energy/count;
+    }
+
+    public void release() {
+        if (mVisualizer != null) {
+            mVisualizer.release();
+            mVisualizer = null;
+        }
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaBassBoostTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaBassBoostTest.java
index 8a68c5e..aca729e 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaBassBoostTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaBassBoostTest.java
@@ -43,7 +43,7 @@
  */
 public class MediaBassBoostTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
     private String TAG = "MediaBassBoostTest";
-    private final static int MIN_ENERGY_RATIO_2 = 4;
+    private final static int MIN_ENERGY_RATIO_2 = 3;
     private final static short TEST_STRENGTH = 500;
 
     private BassBoost mBassBoost = null;
@@ -259,52 +259,6 @@
     // private methods
     //----------------------------------
 
-    private class EnergyProbe {
-        Visualizer mVisualizer = null;
-        private byte[] mFft = new byte[1024];
-
-        public EnergyProbe(int session) {
-            mVisualizer = new Visualizer(session);
-            mVisualizer.setCaptureSize(1024);
-        }
-
-        public int capture(int freq) throws InterruptedException {
-            int energy = 0;
-            int count = 0;
-            if (mVisualizer != null) {
-                mVisualizer.setEnabled(true);
-                for (int i = 0; i < 10; i++) {
-                    if (mVisualizer.getFft(mFft) == Visualizer.SUCCESS) {
-                        // TODO: check speex FFT as it seems to return only the number of points
-                        // correspondong to valid part of the spectrum (< Fs).
-                        // e.g., if the number of points is 1024, it covers the frequency range
-                        // 0 to 22050 instead of 0 to 44100 as expected from an FFT.
-                        int bin = freq / (22050 / 1024);
-                        int tmp = 0;
-                        for (int j = bin-2; j < bin+3; j++) {
-                            tmp += (int)mFft[j] * (int)mFft[j];
-                        }
-                        energy += tmp/5;
-                        count++;
-                    }
-                    Thread.sleep(50);
-                }
-                mVisualizer.setEnabled(false);
-            }
-            if (count == 0) {
-                return 0;
-            }
-            return energy/count;
-        }
-
-        public void release() {
-            if (mVisualizer != null) {
-                mVisualizer.release();
-                mVisualizer = null;
-            }
-        }
-    }
-
     private void getBassBoost(int session) {
          if (mBassBoost == null || session != mSession) {
              if (session != mSession && mBassBoost != null) {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java
new file mode 100644
index 0000000..db0db70
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEnvReverbTest.java
@@ -0,0 +1,508 @@
+/*
+ * 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.mediaframeworktest.functional;
+
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import com.android.mediaframeworktest.MediaNames;
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.media.AudioEffect;
+import android.media.AudioManager;
+import android.media.EnvironmentalReverb;
+import android.media.Visualizer;
+import android.media.MediaPlayer;
+
+import android.os.Looper;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+
+import java.nio.ByteOrder;
+import java.nio.ByteBuffer;
+import java.util.UUID;
+
+/**
+ * Junit / Instrumentation test case for the media AudioTrack api
+
+ */
+public class MediaEnvReverbTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
+    private String TAG = "MediaEnvReverbTest";
+    // allow +/- 100 millibel difference between set and get gains
+    private final static int MILLIBEL_TOLERANCE = 100;
+    // allow +/- 5% tolerance between set and get delays
+    private final static float DELAY_TOLERANCE = 1.05f;
+    // allow +/- 5% tolerance between set and get ratios
+    private final static float RATIO_TOLERANCE = 1.05f;
+
+    private EnvironmentalReverb mReverb = null;
+    private int mSession = -1;
+
+    public MediaEnvReverbTest() {
+        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+      super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        releaseReverb();
+    }
+
+    private static void assumeTrue(String message, boolean cond) {
+        assertTrue("(assume)"+message, cond);
+    }
+
+    private void log(String testName, String message) {
+        Log.v(TAG, "["+testName+"] "+message);
+    }
+
+    private void loge(String testName, String message) {
+        Log.e(TAG, "["+testName+"] "+message);
+    }
+
+    //-----------------------------------------------------------------
+    // ENVIRONMENTAL REVEB TESTS:
+    //----------------------------------
+
+
+    //-----------------------------------------------------------------
+    // 0 - constructor
+    //----------------------------------
+
+    //Test case 0.0: test constructor and release
+    @LargeTest
+    public void test0_0ConstructorAndRelease() throws Exception {
+        boolean result = false;
+        String msg = "test1_0ConstructorAndRelease()";
+        EnvironmentalReverb reverb = null;
+         try {
+            reverb = new EnvironmentalReverb(0, 0);
+            assertNotNull(msg + ": could not create EnvironmentalReverb", reverb);
+            try {
+                assertTrue(msg +": invalid effect ID", (reverb.getId() != 0));
+            } catch (IllegalStateException e) {
+                msg = msg.concat(": EnvironmentalReverb not initialized");
+            }
+            result = true;
+        } catch (IllegalArgumentException e) {
+            msg = msg.concat(": EnvironmentalReverb not found");
+        } catch (UnsupportedOperationException e) {
+            msg = msg.concat(": Effect library not loaded");
+        } finally {
+            if (reverb != null) {
+                reverb.release();
+            }
+        }
+        assertTrue(msg, result);
+    }
+
+    //-----------------------------------------------------------------
+    // 1 - get/set parameters
+    //----------------------------------
+
+    //Test case 1.0: test room level and room HF level
+    @LargeTest
+    public void test1_0Room() throws Exception {
+        boolean result = false;
+        String msg = "test1_0Room()";
+        getReverb(0);
+        try {
+            mReverb.setRoomLevel((short)0);
+            short level = mReverb.getRoomLevel();
+            assertTrue(msg +": got incorrect room level",
+                    (level > (0 - MILLIBEL_TOLERANCE)) &&
+                    (level < (0 + MILLIBEL_TOLERANCE)));
+
+            mReverb.setRoomHFLevel((short)-6);
+            level = mReverb.getRoomHFLevel();
+            assertTrue(msg +": got incorrect room HF level",
+                    (level > (-6 - MILLIBEL_TOLERANCE)) &&
+                    (level < (-6 + MILLIBEL_TOLERANCE)));
+
+            result = true;
+        } catch (IllegalArgumentException e) {
+            msg = msg.concat(": Bad parameter value");
+            loge(msg, "Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            msg = msg.concat(": get parameter() rejected");
+            loge(msg, "get parameter() rejected");
+        } catch (IllegalStateException e) {
+            msg = msg.concat("get parameter() called in wrong state");
+            loge(msg, "get parameter() called in wrong state");
+        } finally {
+            releaseReverb();
+        }
+        assertTrue(msg, result);
+    }
+
+    //Test case 1.1: test decay time and ratio
+    @LargeTest
+    public void test1_1Decay() throws Exception {
+        boolean result = false;
+        String msg = "test1_1Decay()";
+        getReverb(0);
+        try {
+            mReverb.setDecayTime(500);
+            int time = mReverb.getDecayTime();
+            assertTrue(msg +": got incorrect decay time",
+                    ((float)time > (float)(500 / DELAY_TOLERANCE)) &&
+                    ((float)time < (float)(500 * DELAY_TOLERANCE)));
+
+            mReverb.setDecayHFRatio((short)1000);
+            short ratio = mReverb.getDecayHFRatio();
+            assertTrue(msg +": got incorrect decay HF ratio",
+                    ((float)ratio > (float)(1000 / RATIO_TOLERANCE)) &&
+                    ((float)ratio < (float)(1000 * RATIO_TOLERANCE)));
+
+            result = true;
+        } catch (IllegalArgumentException e) {
+            msg = msg.concat(": Bad parameter value");
+            loge(msg, "Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            msg = msg.concat(": get parameter() rejected");
+            loge(msg, "get parameter() rejected");
+        } catch (IllegalStateException e) {
+            msg = msg.concat("get parameter() called in wrong state");
+            loge(msg, "get parameter() called in wrong state");
+        } finally {
+            releaseReverb();
+        }
+        assertTrue(msg, result);
+    }
+
+    //Test case 1.2: test reflections
+    @LargeTest
+    public void test1_2Reflections() throws Exception {
+        // TODO: uncomment when early reflections are implemented
+//        boolean result = false;
+//        String msg = "test1_2Reflections()";
+//        getReverb(0);
+//        try {
+//            mReverb.setReflectionsLevel((short)0);
+//            short level = mReverb.getReflectionsLevel();
+//            assertTrue(msg +": got incorrect reflections level",
+//                    (level > (0 - MILLIBEL_TOLERANCE)) &&
+//                    (level < (0 + MILLIBEL_TOLERANCE)));
+//
+//            mReverb.setReflectionsDelay(30);
+//            int delay = mReverb.getReflectionsDelay();
+//            assertTrue(msg +": got incorrect reflections delay",
+//                    ((float)delay > (float)(30 / DELAY_TOLERANCE)) &&
+//                    ((float)delay < (float)(30 * DELAY_TOLERANCE)));
+//
+//            result = true;
+//        } catch (IllegalArgumentException e) {
+//            msg = msg.concat(": Bad parameter value");
+//            loge(msg, "Bad parameter value");
+//        } catch (UnsupportedOperationException e) {
+//            msg = msg.concat(": get parameter() rejected");
+//            loge(msg, "get parameter() rejected");
+//        } catch (IllegalStateException e) {
+//            msg = msg.concat("get parameter() called in wrong state");
+//            loge(msg, "get parameter() called in wrong state");
+//        } finally {
+//            releaseReverb();
+//        }
+//        assertTrue(msg, result);
+    }
+
+    //Test case 1.3: test reverb
+    @LargeTest
+    public void test1_3Reverb() throws Exception {
+        boolean result = false;
+        String msg = "test1_3Reverb()";
+        getReverb(0);
+        try {
+            mReverb.setReverbLevel((short)0);
+            short level = mReverb.getReverbLevel();
+            assertTrue(msg +": got incorrect reverb level",
+                    (level > (0 - MILLIBEL_TOLERANCE)) &&
+                    (level < (0 + MILLIBEL_TOLERANCE)));
+
+            // TODO: change delay when early reflections are implemented
+            mReverb.setReverbDelay(0);
+            int delay = mReverb.getReverbDelay();
+            assertTrue(msg +": got incorrect reverb delay", delay < 5);
+
+            result = true;
+        } catch (IllegalArgumentException e) {
+            msg = msg.concat(": Bad parameter value");
+            loge(msg, "Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            msg = msg.concat(": get parameter() rejected");
+            loge(msg, "get parameter() rejected");
+        } catch (IllegalStateException e) {
+            msg = msg.concat("get parameter() called in wrong state");
+            loge(msg, "get parameter() called in wrong state");
+        } finally {
+            releaseReverb();
+        }
+        assertTrue(msg, result);
+    }
+
+    //Test case 1.4: test diffusion and density
+    @LargeTest
+    public void test1_4DiffusionAndDensity() throws Exception {
+        boolean result = false;
+        String msg = "test1_4DiffusionAndDensity()";
+        getReverb(0);
+        try {
+            mReverb.setDiffusion((short)500);
+            short diffusion = mReverb.getDiffusion();
+            assertTrue(msg +": got incorrect diffusion",
+                    ((float)diffusion > (float)(500 / RATIO_TOLERANCE)) &&
+                    ((float)diffusion < (float)(500 * RATIO_TOLERANCE)));
+
+            mReverb.setDensity((short)500);
+            short density = mReverb.getDensity();
+            assertTrue(msg +": got incorrect density",
+                    ((float)density > (float)(500 / RATIO_TOLERANCE)) &&
+                    ((float)density < (float)(500 * RATIO_TOLERANCE)));
+
+            result = true;
+        } catch (IllegalArgumentException e) {
+            msg = msg.concat(": Bad parameter value");
+            loge(msg, "Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            msg = msg.concat(": get parameter() rejected");
+            loge(msg, "get parameter() rejected");
+        } catch (IllegalStateException e) {
+            msg = msg.concat("get parameter() called in wrong state");
+            loge(msg, "get parameter() called in wrong state");
+        } finally {
+            releaseReverb();
+        }
+        assertTrue(msg, result);
+    }
+
+    //Test case 1.5: test properties
+    @LargeTest
+    public void test1_5Properties() throws Exception {
+        boolean result = false;
+        String msg = "test1_5Properties()";
+        getReverb(0);
+        try {
+            EnvironmentalReverb.Settings settings = mReverb.getProperties();
+            short newRoomLevel = 0;
+            if (settings.roomLevel == 0) {
+                newRoomLevel = -1000;
+            }
+            String str = settings.toString();
+            settings = new EnvironmentalReverb.Settings(str);
+            settings.roomLevel = newRoomLevel;
+            mReverb.setProperties(settings);
+            settings = mReverb.getProperties();
+            assertTrue(msg +": setProperties failed",
+                    (settings.roomLevel > (newRoomLevel - MILLIBEL_TOLERANCE)) &&
+                    (settings.roomLevel < (newRoomLevel + MILLIBEL_TOLERANCE)));
+            result = true;
+        } catch (IllegalArgumentException e) {
+            msg = msg.concat(": Bad parameter value");
+            loge(msg, "Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            msg = msg.concat(": get parameter() rejected");
+            loge(msg, "get parameter() rejected");
+        } catch (IllegalStateException e) {
+            msg = msg.concat("get parameter() called in wrong state");
+            loge(msg, "get parameter() called in wrong state");
+        } finally {
+            releaseReverb();
+        }
+        assertTrue(msg, result);
+    }
+
+    //-----------------------------------------------------------------
+    // 2 - Effect action
+    //----------------------------------
+
+    //Test case 2.0: test actual auxiliary reverb influence on sound
+    @LargeTest
+    public void test2_0AuxiliarySoundModification() throws Exception {
+        boolean result = false;
+        String msg = "test2_0AuxiliarySoundModification()";
+        EnergyProbe probe = null;
+        AudioEffect vc = null;
+        MediaPlayer mp = null;
+        AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
+        int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+        am.setStreamVolume(AudioManager.STREAM_MUSIC,
+                           am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
+                           0);
+        getReverb(0);
+        try {
+            probe = new EnergyProbe(0);
+            // creating a volume controller on output mix ensures that ro.audio.silent mutes
+            // audio after the effects and not before
+            vc = new AudioEffect(
+                    AudioEffect.EFFECT_TYPE_NULL,
+                    UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"),
+                      0,
+                      0);
+            vc.setEnabled(true);
+
+            mp = new MediaPlayer();
+            mp.setDataSource(MediaNames.SINE_200_1000);
+            mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
+            mp.attachAuxEffect(mReverb.getId());
+            mp.setAuxEffectSendLevel(1.0f);
+            mReverb.setRoomLevel((short)0);
+            mReverb.setReverbLevel((short)0);
+            mReverb.setDecayTime(2000);
+            mReverb.setEnabled(true);
+            mp.prepare();
+            mp.start();
+            Thread.sleep(1000);
+            mp.stop();
+            Thread.sleep(300);
+            // measure energy around 1kHz after media player was stopped for 300 ms
+            int energy1000 = probe.capture(1000);
+            assertTrue(msg + ": reverb has no effect", energy1000 > 0);
+            result = true;
+        } catch (IllegalArgumentException e) {
+            msg = msg.concat(": Bad parameter value");
+            loge(msg, "Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            msg = msg.concat(": get parameter() rejected");
+            loge(msg, "get parameter() rejected");
+        } catch (IllegalStateException e) {
+            msg = msg.concat("get parameter() called in wrong state");
+            loge(msg, "get parameter() called in wrong state");
+        } catch (InterruptedException e) {
+            loge(msg, "sleep() interrupted");
+        }
+        finally {
+            releaseReverb();
+            if (mp != null) {
+                mp.release();
+            }
+            if (vc != null) {
+                vc.release();
+            }
+            if (probe != null) {
+                probe.release();
+            }
+            am.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);
+        }
+        assertTrue(msg, result);
+    }
+
+    //Test case 2.1: test actual insert reverb influence on sound
+    @LargeTest
+    public void test2_1InsertSoundModification() throws Exception {
+        boolean result = false;
+        String msg = "test2_1InsertSoundModification()";
+        EnergyProbe probe = null;
+        AudioEffect vc = null;
+        MediaPlayer mp = null;
+        AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
+        int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+        am.setStreamVolume(AudioManager.STREAM_MUSIC,
+                           am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
+                           0);
+        try {
+            probe = new EnergyProbe(0);
+            // creating a volume controller on output mix ensures that ro.audio.silent mutes
+            // audio after the effects and not before
+            vc = new AudioEffect(
+                    AudioEffect.EFFECT_TYPE_NULL,
+                    UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"),
+                      0,
+                      0);
+            vc.setEnabled(true);
+
+            mp = new MediaPlayer();
+            mp.setDataSource(MediaNames.SINE_200_1000);
+            mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
+            getReverb(mp.getAudioSessionId());
+            mReverb.setRoomLevel((short)0);
+            mReverb.setReverbLevel((short)0);
+            mReverb.setDecayTime(2000);
+            mReverb.setEnabled(true);
+            mp.prepare();
+            mp.start();
+            Thread.sleep(1000);
+            mp.stop();
+            Thread.sleep(300);
+            // measure energy around 1kHz after media player was stopped for 300 ms
+            int energy1000 = probe.capture(1000);
+            assertTrue(msg + ": reverb has no effect", energy1000 > 0);
+            result = true;
+        } catch (IllegalArgumentException e) {
+            msg = msg.concat(": Bad parameter value");
+            loge(msg, "Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            msg = msg.concat(": get parameter() rejected");
+            loge(msg, "get parameter() rejected");
+        } catch (IllegalStateException e) {
+            msg = msg.concat("get parameter() called in wrong state");
+            loge(msg, "get parameter() called in wrong state");
+        } catch (InterruptedException e) {
+            loge(msg, "sleep() interrupted");
+        }
+        finally {
+            releaseReverb();
+            if (mp != null) {
+                mp.release();
+            }
+            if (vc != null) {
+                vc.release();
+            }
+            if (probe != null) {
+                probe.release();
+            }
+            am.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);
+        }
+        assertTrue(msg, result);
+    }
+
+    //-----------------------------------------------------------------
+    // private methods
+    //----------------------------------
+
+    private void getReverb(int session) {
+         if (mReverb == null || session != mSession) {
+             if (session != mSession && mReverb != null) {
+                 mReverb.release();
+                 mReverb = null;
+             }
+             try {
+                mReverb = new EnvironmentalReverb(0, session);
+                mSession = session;
+            } catch (IllegalArgumentException e) {
+                Log.e(TAG, "getReverb() EnvironmentalReverb not found exception: "+e);
+            } catch (UnsupportedOperationException e) {
+                Log.e(TAG, "getReverb() Effect library not loaded exception: "+e);
+            }
+         }
+         assertNotNull("could not create mReverb", mReverb);
+    }
+
+    private void releaseReverb() {
+        if (mReverb != null) {
+            mReverb.release();
+            mReverb = null;
+        }
+   }
+
+}
+
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEqualizerTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEqualizerTest.java
index e46887b..7b3945d 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEqualizerTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaEqualizerTest.java
@@ -322,52 +322,6 @@
     // private methods
     //----------------------------------
 
-    private class EnergyProbe {
-        Visualizer mVisualizer = null;
-        private byte[] mFft = new byte[1024];
-
-        public EnergyProbe(int session) {
-            mVisualizer = new Visualizer(session);
-            mVisualizer.setCaptureSize(1024);
-        }
-
-        public int capture(int freq) throws InterruptedException {
-            int energy = 0;
-            int count = 0;
-            if (mVisualizer != null) {
-                mVisualizer.setEnabled(true);
-                for (int i = 0; i < 10; i++) {
-                    if (mVisualizer.getFft(mFft) == Visualizer.SUCCESS) {
-                        // TODO: check speex FFT as it seems to return only the number of points
-                        // correspondong to valid part of the spectrum (< Fs).
-                        // e.g., if the number of points is 1024, it covers the frequency range
-                        // 0 to 22050 instead of 0 to 44100 as expected from an FFT.
-                        int bin = freq / (22050 / 1024);
-                        int tmp = 0;
-                        for (int j = bin-2; j < bin+3; j++) {
-                            tmp += (int)mFft[j] * (int)mFft[j];
-                        }
-                        energy += tmp/5;
-                        count++;
-                    }
-                    Thread.sleep(50);
-                }
-                mVisualizer.setEnabled(false);
-            }
-            if (count == 0) {
-                return 0;
-            }
-            return energy/count;
-        }
-
-        public void release() {
-            if (mVisualizer != null) {
-                mVisualizer.release();
-                mVisualizer = null;
-            }
-        }
-    }
-
     private void getEqualizer(int session) {
          if (mEqualizer == null || session != mSession) {
              if (session != mSession && mEqualizer != null) {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java
new file mode 100644
index 0000000..c14319a
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPresetReverbTest.java
@@ -0,0 +1,349 @@
+/*
+ * 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.mediaframeworktest.functional;
+
+import com.android.mediaframeworktest.MediaFrameworkTest;
+import com.android.mediaframeworktest.MediaNames;
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.media.AudioEffect;
+import android.media.AudioManager;
+import android.media.PresetReverb;
+import android.media.Visualizer;
+import android.media.MediaPlayer;
+
+import android.os.Looper;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+
+import java.nio.ByteOrder;
+import java.nio.ByteBuffer;
+import java.util.UUID;
+
+/**
+ * Junit / Instrumentation test case for the media AudioTrack api
+
+ */
+public class MediaPresetReverbTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
+    private String TAG = "MediaPresetReverbTest";
+
+    private PresetReverb mReverb = null;
+    private int mSession = -1;
+
+    public MediaPresetReverbTest() {
+        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+      super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        releaseReverb();
+    }
+
+    private static void assumeTrue(String message, boolean cond) {
+        assertTrue("(assume)"+message, cond);
+    }
+
+    private void log(String testName, String message) {
+        Log.v(TAG, "["+testName+"] "+message);
+    }
+
+    private void loge(String testName, String message) {
+        Log.e(TAG, "["+testName+"] "+message);
+    }
+
+    //-----------------------------------------------------------------
+    // PRESET REVEB TESTS:
+    //----------------------------------
+
+
+    //-----------------------------------------------------------------
+    // 0 - constructor
+    //----------------------------------
+
+    //Test case 0.0: test constructor and release
+    @LargeTest
+    public void test0_0ConstructorAndRelease() throws Exception {
+        boolean result = false;
+        String msg = "test1_0ConstructorAndRelease()";
+        PresetReverb reverb = null;
+         try {
+            reverb = new PresetReverb(0, 0);
+            assertNotNull(msg + ": could not create PresetReverb", reverb);
+            try {
+                assertTrue(msg +": invalid effect ID", (reverb.getId() != 0));
+            } catch (IllegalStateException e) {
+                msg = msg.concat(": PresetReverb not initialized");
+            }
+            result = true;
+        } catch (IllegalArgumentException e) {
+            msg = msg.concat(": PresetReverb not found");
+        } catch (UnsupportedOperationException e) {
+            msg = msg.concat(": Effect library not loaded");
+        } finally {
+            if (reverb != null) {
+                reverb.release();
+            }
+        }
+        assertTrue(msg, result);
+    }
+
+    //-----------------------------------------------------------------
+    // 1 - get/set parameters
+    //----------------------------------
+
+    //Test case 1.0: test preset
+    @LargeTest
+    public void test1_0Preset() throws Exception {
+        boolean result = false;
+        String msg = "test1_0Preset()";
+        getReverb(0);
+        try {
+            mReverb.setPreset((short)PresetReverb.PRESET_LARGEROOM);
+            short preset = mReverb.getPreset();
+            assertEquals(msg +": got incorrect preset",
+                         (short)PresetReverb.PRESET_LARGEROOM,
+                         preset);
+            result = true;
+        } catch (IllegalArgumentException e) {
+            msg = msg.concat(": Bad parameter value");
+            loge(msg, "Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            msg = msg.concat(": get parameter() rejected");
+            loge(msg, "get parameter() rejected");
+        } catch (IllegalStateException e) {
+            msg = msg.concat("get parameter() called in wrong state");
+            loge(msg, "get parameter() called in wrong state");
+        } finally {
+            releaseReverb();
+        }
+        assertTrue(msg, result);
+    }
+
+    //Test case 1.1: test properties
+    @LargeTest
+    public void test1_1Properties() throws Exception {
+        boolean result = false;
+        String msg = "test1_1Properties()";
+        getReverb(0);
+        try {
+            PresetReverb.Settings settings = mReverb.getProperties();
+            short newPreset = (short)PresetReverb.PRESET_LARGEROOM;
+            if (settings.preset == (short)PresetReverb.PRESET_LARGEROOM) {
+                newPreset = (short)PresetReverb.PRESET_SMALLROOM;
+            }
+            String str = settings.toString();
+            settings = new PresetReverb.Settings(str);
+            settings.preset = newPreset;
+            mReverb.setProperties(settings);
+            settings = mReverb.getProperties();
+            assertEquals(msg +": setProperties failed", newPreset, settings.preset);
+            result = true;
+        } catch (IllegalArgumentException e) {
+            msg = msg.concat(": Bad parameter value");
+            loge(msg, "Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            msg = msg.concat(": get parameter() rejected");
+            loge(msg, "get parameter() rejected");
+        } catch (IllegalStateException e) {
+            msg = msg.concat("get parameter() called in wrong state");
+            loge(msg, "get parameter() called in wrong state");
+        } finally {
+            releaseReverb();
+        }
+        assertTrue(msg, result);
+    }
+
+    //-----------------------------------------------------------------
+    // 2 - Effect action
+    //----------------------------------
+
+    //Test case 2.0: test actual auxiliary reverb influence on sound
+    @LargeTest
+    public void test2_0AuxiliarySoundModification() throws Exception {
+        boolean result = false;
+        String msg = "test2_0AuxiliarySoundModification()";
+        EnergyProbe probe = null;
+        AudioEffect vc = null;
+        MediaPlayer mp = null;
+        AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
+        int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+        am.setStreamVolume(AudioManager.STREAM_MUSIC,
+                           am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
+                           0);
+        getReverb(0);
+        try {
+            probe = new EnergyProbe(0);
+            // creating a volume controller on output mix ensures that ro.audio.silent mutes
+            // audio after the effects and not before
+            vc = new AudioEffect(
+                    AudioEffect.EFFECT_TYPE_NULL,
+                    UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"),
+                      0,
+                      0);
+            vc.setEnabled(true);
+
+            mp = new MediaPlayer();
+            mp.setDataSource(MediaNames.SINE_200_1000);
+            mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
+            mp.attachAuxEffect(mReverb.getId());
+            mp.setAuxEffectSendLevel(1.0f);
+            mReverb.setPreset((short)PresetReverb.PRESET_PLATE);
+            mReverb.setEnabled(true);
+            mp.prepare();
+            mp.start();
+            Thread.sleep(1000);
+            mp.stop();
+            Thread.sleep(200);
+            // measure energy around 1kHz after media player was stopped for 200 ms
+            int energy1000 = probe.capture(1000);
+            assertTrue(msg + ": reverb has no effect", energy1000 > 0);
+            result = true;
+        } catch (IllegalArgumentException e) {
+            msg = msg.concat(": Bad parameter value");
+            loge(msg, "Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            msg = msg.concat(": get parameter() rejected");
+            loge(msg, "get parameter() rejected");
+        } catch (IllegalStateException e) {
+            msg = msg.concat("get parameter() called in wrong state");
+            loge(msg, "get parameter() called in wrong state");
+        } catch (InterruptedException e) {
+            loge(msg, "sleep() interrupted");
+        }
+        finally {
+            releaseReverb();
+            if (mp != null) {
+                mp.release();
+            }
+            if (vc != null) {
+                vc.release();
+            }
+            if (probe != null) {
+                probe.release();
+            }
+            am.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);
+        }
+        assertTrue(msg, result);
+    }
+
+    //Test case 2.1: test actual insert reverb influence on sound
+    @LargeTest
+    public void test2_1InsertSoundModification() throws Exception {
+        boolean result = false;
+        String msg = "test2_1InsertSoundModification()";
+        EnergyProbe probe = null;
+        AudioEffect vc = null;
+        MediaPlayer mp = null;
+        AudioManager am = (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
+        int volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+        am.setStreamVolume(AudioManager.STREAM_MUSIC,
+                           am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),
+                           0);
+        try {
+            probe = new EnergyProbe(0);
+            // creating a volume controller on output mix ensures that ro.audio.silent mutes
+            // audio after the effects and not before
+            vc = new AudioEffect(
+                    AudioEffect.EFFECT_TYPE_NULL,
+                    UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"),
+                      0,
+                      0);
+            vc.setEnabled(true);
+
+            mp = new MediaPlayer();
+            mp.setDataSource(MediaNames.SINE_200_1000);
+            mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
+            getReverb(mp.getAudioSessionId());
+            mReverb.setPreset((short)PresetReverb.PRESET_PLATE);
+            mReverb.setEnabled(true);
+            mp.prepare();
+            mp.start();
+            Thread.sleep(1000);
+            mp.stop();
+            Thread.sleep(200);
+            // measure energy around 1kHz after media player was stopped for 200 ms
+            int energy1000 = probe.capture(1000);
+            assertTrue(msg + ": reverb has no effect", energy1000 > 0);
+            result = true;
+        } catch (IllegalArgumentException e) {
+            msg = msg.concat(": Bad parameter value");
+            loge(msg, "Bad parameter value");
+        } catch (UnsupportedOperationException e) {
+            msg = msg.concat(": get parameter() rejected");
+            loge(msg, "get parameter() rejected");
+        } catch (IllegalStateException e) {
+            msg = msg.concat("get parameter() called in wrong state");
+            loge(msg, "get parameter() called in wrong state");
+        } catch (InterruptedException e) {
+            loge(msg, "sleep() interrupted");
+        }
+        finally {
+            releaseReverb();
+            if (mp != null) {
+                mp.release();
+            }
+            if (vc != null) {
+                vc.release();
+            }
+            if (probe != null) {
+                probe.release();
+            }
+            am.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);
+        }
+        assertTrue(msg, result);
+    }
+
+    //-----------------------------------------------------------------
+    // private methods
+    //----------------------------------
+
+    private void getReverb(int session) {
+         if (mReverb == null || session != mSession) {
+             if (session != mSession && mReverb != null) {
+                 mReverb.release();
+                 mReverb = null;
+             }
+             try {
+                mReverb = new PresetReverb(0, session);
+                mSession = session;
+            } catch (IllegalArgumentException e) {
+                Log.e(TAG, "getReverb() PresetReverb not found exception: "+e);
+            } catch (UnsupportedOperationException e) {
+                Log.e(TAG, "getReverb() Effect library not loaded exception: "+e);
+            }
+         }
+         assertNotNull("could not create mReverb", mReverb);
+    }
+
+    private void releaseReverb() {
+        if (mReverb != null) {
+            mReverb.release();
+            mReverb = null;
+        }
+   }
+
+}
+
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVirtualizerTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVirtualizerTest.java
index 6b8ae44..517d575 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVirtualizerTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaVirtualizerTest.java
@@ -43,7 +43,7 @@
  */
 public class MediaVirtualizerTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
     private String TAG = "MediaVirtualizerTest";
-    private final static int MIN_ENERGY_RATIO_2 = 4;
+    private final static int MIN_ENERGY_RATIO_2 = 3;
     private final static short TEST_STRENGTH = 500;
 
     private Virtualizer mVirtualizer = null;
@@ -224,7 +224,7 @@
             int energy200 = probe.capture(200);
             int energy1000 = probe.capture(1000);
             // verify that the energy ration between low and high frequencies is at least
-            // four times higher with virtualizer on.
+            // MIN_ENERGY_RATIO_2 times higher with virtualizer on.
             // NOTE: this is what is observed with current virtualizer implementation and the test
             // audio file but is not the primary effect of the virtualizer. A better way would
             // be to have a stereo PCM capture and check that a strongly paned input is centered
@@ -264,52 +264,6 @@
     // private methods
     //----------------------------------
 
-    private class EnergyProbe {
-        Visualizer mVisualizer = null;
-        private byte[] mFft = new byte[1024];
-
-        public EnergyProbe(int session) {
-            mVisualizer = new Visualizer(session);
-            mVisualizer.setCaptureSize(1024);
-        }
-
-        public int capture(int freq) throws InterruptedException {
-            int energy = 0;
-            int count = 0;
-            if (mVisualizer != null) {
-                mVisualizer.setEnabled(true);
-                for (int i = 0; i < 10; i++) {
-                    if (mVisualizer.getFft(mFft) == Visualizer.SUCCESS) {
-                        // TODO: check speex FFT as it seems to return only the number of points
-                        // correspondong to valid part of the spectrum (< Fs).
-                        // e.g., if the number of points is 1024, it covers the frequency range
-                        // 0 to 22050 instead of 0 to 44100 as expected from an FFT.
-                        int bin = freq / (22050 / 1024);
-                        int tmp = 0;
-                        for (int j = bin-2; j < bin+3; j++) {
-                            tmp += (int)mFft[j] * (int)mFft[j];
-                        }
-                        energy += tmp/5;
-                        count++;
-                    }
-                    Thread.sleep(50);
-                }
-                mVisualizer.setEnabled(false);
-            }
-            if (count == 0) {
-                return 0;
-            }
-            return energy/count;
-        }
-
-        public void release() {
-            if (mVisualizer != null) {
-                mVisualizer.release();
-                mVisualizer = null;
-            }
-        }
-    }
-
     private void getVirtualizer(int session) {
          if (mVirtualizer == null || session != mSession) {
              if (session != mSession && mVirtualizer != null) {
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index b39556a..8d77f76 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -224,6 +224,7 @@
             mCM.unregisterForNVReady(this); //EVENT_NV_READY
             mSST.unregisterForNetworkAttach(this); //EVENT_REGISTERED_TO_NETWORK
             mCM.unSetOnSuppServiceNotification(this);
+            removeCallbacks(mExitEcmRunnable);
 
             mPendingMmis.clear();
 
@@ -256,6 +257,7 @@
             this.mSST = null;
             this.mEriManager = null;
             this.mCcatService = null;
+            this.mExitEcmRunnable = null;
     }
 
     protected void finalize() {
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/WebViewEventSender.java b/tests/DumpRenderTree/src/com/android/dumprendertree/WebViewEventSender.java
index 0c2347d..716086b 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/WebViewEventSender.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/WebViewEventSender.java
@@ -16,14 +16,12 @@
 
 package com.android.dumprendertree;
 
-import android.os.Handler;
 import android.os.SystemClock;
 import android.util.*;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.webkit.WebView;
 
-import java.lang.InterruptedException;
 import java.util.Arrays;
 import java.util.Vector;
 
@@ -33,7 +31,7 @@
 	
     WebViewEventSender(WebView webView) {
         mWebView = webView;
-        mTouchPoints = new Vector();
+        mTouchPoints = new Vector<TouchPoint>();
     }
 	
 	public void resetMouse() {
@@ -82,47 +80,23 @@
 		mouseUp();
 	}
 
-	public void mouseDown() {
-          /*  KeyEvent event = new KeyEvent(
-                KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
-            mWebView.onKeyDown(event.getKeyCode(), event); */
-	}
+    public void mouseDown() {
+        long ts = SystemClock.uptimeMillis();
+        MotionEvent event = MotionEvent.obtain(ts, ts, MotionEvent.ACTION_DOWN, mouseX, mouseY, 0);
+        mWebView.onTouchEvent(event);
+    }
 
-	public void mouseMoveTo(int X, int Y) {
-		if (X > mouseX) {
-                    KeyEvent event = new KeyEvent(
-                        KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT);
-                    mWebView.onKeyDown(event.getKeyCode(), event);
-                    mWebView.onKeyUp(event.getKeyCode(), event);
-		} else if ( X < mouseX ) {
-                    KeyEvent event = new KeyEvent(
-                        KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT);
-                    mWebView.onKeyDown(event.getKeyCode(), event);
-                    mWebView.onKeyUp(event.getKeyCode(), event);
-		}
-		if (Y > mouseY) {
-                    KeyEvent event = new KeyEvent(
-                        KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN);
-                    mWebView.onKeyDown(event.getKeyCode(), event);
-                    mWebView.onKeyUp(event.getKeyCode(), event);
-		} else if (Y < mouseY ) {
-                    KeyEvent event = new KeyEvent(
-                        KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP);
-                    mWebView.onKeyDown(event.getKeyCode(), event);
-                    mWebView.onKeyUp(event.getKeyCode(), event);
-		}
-		mouseX= X;
-		mouseY= Y;
-	
-	}
+    public void mouseMoveTo(int X, int Y) {
+        mouseX= X;
+        mouseY= Y;
+    }
 
-	public void mouseUp() {
-        /*    KeyEvent event = new KeyEvent(
-                KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER);
-            mWebView.onKeyDown(event.getKeyCode(), event);*/
+     public void mouseUp() {
+        long ts = SystemClock.uptimeMillis();
+        MotionEvent event = MotionEvent.obtain(ts, ts, MotionEvent.ACTION_UP, mouseX, mouseY, 0);
+        mWebView.onTouchEvent(event);
+    }
 
-	}
-	
 	// Assumes lowercase chars, case needs to be
 	// handled by calling function.
 	static int keyMapper(char c) {
@@ -365,7 +339,7 @@
             mX = x;
             mY = y;
         }
-    };
+    }
 
     private Vector<TouchPoint> mTouchPoints;
     private int mTouchMetaState;