More threading issues fixed in audio effect tests

Fixed synchonizaion issues in Equalizer, BassBoost, Virtualizer,
Reverb and Visualizer listener tests.

Change-Id: I58a3c5d2ef6679eb3912e06495140d60edbdbfc6
diff --git a/tests/tests/media/src/android/media/cts/BassBoostTest.java b/tests/tests/media/src/android/media/cts/BassBoostTest.java
index e68bcde..9dcb4e9 100644
--- a/tests/tests/media/src/android/media/cts/BassBoostTest.java
+++ b/tests/tests/media/src/android/media/cts/BassBoostTest.java
@@ -30,6 +30,7 @@
     private final static short TEST_STRENGTH = 500;
     private final static short TEST_STRENGTH2 = 1000;
     private final static float STRENGTH_TOLERANCE = 1.1f;  // 10%
+    private final static int MAX_LOOPER_WAIT_COUNT = 10;
 
     private BassBoost mBassBoost = null;
     private BassBoost mBassBoost2 = null;
@@ -40,6 +41,7 @@
     private boolean mInitialized = false;
     private Looper mLooper = null;
     private final Object mLock = new Object();
+    private ListenerThread mEffectListenerLooper = null;
 
     //-----------------------------------------------------------------
     // BASS BOOST TESTS:
@@ -194,81 +196,69 @@
 
     //Test case 3.0: test control status listener
     public void test3_0ControlStatusListener() throws Exception {
-        mHasControl = true;
-        createListenerLooper(true, false, false);
         synchronized(mLock) {
-            try {
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Looper creation: wait was interrupted.");
+            mHasControl = true;
+            mInitialized = false;
+            createListenerLooper(true, false, false);
+            waitForLooperInitialization_l();
+
+            getBassBoost(0);
+            int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+            while (mHasControl && (looperWaitCount-- > 0)) {
+                try {
+                    mLock.wait();
+                } catch(Exception e) {
+                }
             }
-        }
-        assertTrue(mInitialized);
-        synchronized(mLock) {
-            try {
-                getBassBoost(0);
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Create second effect: wait was interrupted.");
-            } finally {
-                releaseBassBoost();
-                terminateListenerLooper();
-            }
+            terminateListenerLooper();
+            releaseBassBoost();
         }
         assertFalse("effect control not lost by effect1", mHasControl);
     }
 
     //Test case 3.1: test enable status listener
     public void test3_1EnableStatusListener() throws Exception {
-        createListenerLooper(false, true, false);
         synchronized(mLock) {
-            try {
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Looper creation: wait was interrupted.");
+            mInitialized = false;
+            createListenerLooper(false, true, false);
+            waitForLooperInitialization_l();
+
+            mBassBoost2.setEnabled(true);
+            mIsEnabled = true;
+            getBassBoost(0);
+            mBassBoost.setEnabled(false);
+            int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+            while (mIsEnabled && (looperWaitCount-- > 0)) {
+                try {
+                    mLock.wait();
+                } catch(Exception e) {
+                }
             }
-        }
-        assertTrue(mInitialized);
-        mBassBoost2.setEnabled(true);
-        mIsEnabled = true;
-        getBassBoost(0);
-        synchronized(mLock) {
-            try {
-                mBassBoost.setEnabled(false);
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Create second effect: wait was interrupted.");
-            } finally {
-                releaseBassBoost();
-                terminateListenerLooper();
-            }
+            terminateListenerLooper();
+            releaseBassBoost();
         }
         assertFalse("enable status not updated", mIsEnabled);
     }
 
     //Test case 3.2: test parameter changed listener
     public void test3_2ParameterChangedListener() throws Exception {
-        createListenerLooper(false, false, true);
         synchronized(mLock) {
-            try {
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Looper creation: wait was interrupted.");
+            mInitialized = false;
+            createListenerLooper(false, false, true);
+            waitForLooperInitialization_l();
+
+            getBassBoost(0);
+            mChangedParameter = -1;
+            mBassBoost.setStrength(TEST_STRENGTH);
+            int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+            while ((mChangedParameter == -1) && (looperWaitCount-- > 0)) {
+                try {
+                    mLock.wait();
+                } catch(Exception e) {
+                }
             }
-        }
-        assertTrue(mInitialized);
-        getBassBoost(0);
-        synchronized(mLock) {
-            try {
-                mChangedParameter = -1;
-                mBassBoost.setStrength(TEST_STRENGTH);
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Create second effect: wait was interrupted.");
-            } finally {
-                releaseBassBoost();
-                terminateListenerLooper();
-            }
+            terminateListenerLooper();
+            releaseBassBoost();
         }
         assertEquals("parameter change not received",
                 BassBoost.PARAM_STRENGTH, mChangedParameter);
@@ -303,6 +293,17 @@
         }
     }
 
+    private void waitForLooperInitialization_l() {
+        int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+        while (!mInitialized && (looperWaitCount-- > 0)) {
+            try {
+                mLock.wait();
+            } catch(Exception e) {
+            }
+        }
+        assertTrue(mInitialized);
+    }
+
     // Initializes the bassboot listener looper
     class ListenerThread extends Thread {
         boolean mControl;
@@ -315,11 +316,19 @@
             mEnable = enable;
             mParameter = parameter;
         }
+
+        public void cleanUp() {
+            if (mBassBoost2 != null) {
+                mBassBoost2.setControlStatusListener(null);
+                mBassBoost2.setEnableStatusListener(null);
+                mBassBoost2.setParameterListener(
+                        (BassBoost.OnParameterChangeListener)null);
+            }
+        }
     }
 
     private void createListenerLooper(boolean control, boolean enable, boolean parameter) {
-        mInitialized = false;
-        new ListenerThread(control, enable, parameter) {
+        mEffectListenerLooper = new ListenerThread(control, enable, parameter) {
             @Override
             public void run() {
                 // Set up a looper
@@ -332,67 +341,77 @@
                 mBassBoost2 = new BassBoost(0, 0);
                 assertNotNull("could not create bassboot2", mBassBoost2);
 
-                if (mControl) {
-                    mBassBoost2.setControlStatusListener(
-                            new AudioEffect.OnControlStatusChangeListener() {
-                        public void onControlStatusChange(
-                                AudioEffect effect, boolean controlGranted) {
-                            synchronized(mLock) {
-                                if (effect == mBassBoost2) {
-                                    mHasControl = controlGranted;
-                                    mLock.notify();
-                                }
-                            }
-                        }
-                    });
-                }
-                if (mEnable) {
-                    mBassBoost2.setEnableStatusListener(
-                            new AudioEffect.OnEnableStatusChangeListener() {
-                        public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
-                            synchronized(mLock) {
-                                if (effect == mBassBoost2) {
-                                    mIsEnabled = enabled;
-                                    mLock.notify();
-                                }
-                            }
-                        }
-                    });
-                }
-                if (mParameter) {
-                    mBassBoost2.setParameterListener(new BassBoost.OnParameterChangeListener() {
-                        public void onParameterChange(BassBoost effect, int status,
-                                int param, short value)
-                        {
-                            synchronized(mLock) {
-                                if (effect == mBassBoost2) {
-                                    mChangedParameter = param;
-                                    mLock.notify();
-                                }
-                            }
-                        }
-                    });
-                }
-
                 synchronized(mLock) {
+                    if (mControl) {
+                        mBassBoost2.setControlStatusListener(
+                                new AudioEffect.OnControlStatusChangeListener() {
+                            public void onControlStatusChange(
+                                    AudioEffect effect, boolean controlGranted) {
+                                synchronized(mLock) {
+                                    if (effect == mBassBoost2) {
+                                        mHasControl = controlGranted;
+                                        mLock.notify();
+                                    }
+                                }
+                            }
+                        });
+                    }
+                    if (mEnable) {
+                        mBassBoost2.setEnableStatusListener(
+                                new AudioEffect.OnEnableStatusChangeListener() {
+                            public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
+                                synchronized(mLock) {
+                                    if (effect == mBassBoost2) {
+                                        mIsEnabled = enabled;
+                                        mLock.notify();
+                                    }
+                                }
+                            }
+                        });
+                    }
+                    if (mParameter) {
+                        mBassBoost2.setParameterListener(new BassBoost.OnParameterChangeListener() {
+                            public void onParameterChange(BassBoost effect, int status,
+                                    int param, short value)
+                            {
+                                synchronized(mLock) {
+                                    if (effect == mBassBoost2) {
+                                        mChangedParameter = param;
+                                        mLock.notify();
+                                    }
+                                }
+                            }
+                        });
+                    }
+
                     mInitialized = true;
                     mLock.notify();
                 }
                 Looper.loop();  // Blocks forever until Looper.quit() is called.
             }
-        }.start();
+        };
+        mEffectListenerLooper.start();
     }
 
     // Terminates the listener looper thread.
     private void terminateListenerLooper() {
+        if (mEffectListenerLooper != null) {
+            mEffectListenerLooper.cleanUp();
+            if (mLooper != null) {
+                mLooper.quit();
+                mLooper = null;
+            }
+            try {
+                mEffectListenerLooper.join();
+            } catch(InterruptedException e) {
+            }
+            mEffectListenerLooper = null;
+        }
+
         if (mBassBoost2 != null) {
             mBassBoost2.release();
             mBassBoost2 = null;
         }
-        if (mLooper != null) {
-            mLooper.quit();
-            mLooper = null;
-        }
     }
 
 }
\ No newline at end of file
diff --git a/tests/tests/media/src/android/media/cts/EnvReverbTest.java b/tests/tests/media/src/android/media/cts/EnvReverbTest.java
index ad77b31..edfef96 100644
--- a/tests/tests/media/src/android/media/cts/EnvReverbTest.java
+++ b/tests/tests/media/src/android/media/cts/EnvReverbTest.java
@@ -30,6 +30,7 @@
     private final static int MILLIBEL_TOLERANCE = 100;            // +/-1dB
     private final static float DELAY_TOLERANCE = 1.05f;           // 5%
     private final static float RATIO_TOLERANCE = 1.05f;           // 5%
+    private final static int MAX_LOOPER_WAIT_COUNT = 10;
 
     private EnvironmentalReverb mReverb = null;
     private EnvironmentalReverb mReverb2 = null;
@@ -40,7 +41,7 @@
     private boolean mInitialized = false;
     private Looper mLooper = null;
     private final Object mLock = new Object();
-
+    private ListenerThread mEffectListenerLooper = null;
 
     //-----------------------------------------------------------------
     // ENVIRONMENTAL REVERB TESTS:
@@ -305,81 +306,70 @@
 
     //Test case 3.0: test control status listener
     public void test3_0ControlStatusListener() throws Exception {
-        mHasControl = true;
-        createListenerLooper(true, false, false);
         synchronized(mLock) {
-            try {
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Looper creation: wait was interrupted.");
+            mHasControl = true;
+            mInitialized = false;
+            createListenerLooper(true, false, false);
+            waitForLooperInitialization_l();
+
+            getReverb(0);
+            int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+            while (mHasControl && (looperWaitCount-- > 0)) {
+                try {
+                    mLock.wait();
+                } catch(Exception e) {
+                }
             }
-        }
-        assertTrue(mInitialized);
-        synchronized(mLock) {
-            try {
-                getReverb(0);
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Create second effect: wait was interrupted.");
-            } finally {
-                releaseReverb();
-                terminateListenerLooper();
-            }
+            terminateListenerLooper();
+            releaseReverb();
         }
         assertFalse("effect control not lost by effect1", mHasControl);
     }
 
     //Test case 3.1: test enable status listener
     public void test3_1EnableStatusListener() throws Exception {
-        createListenerLooper(false, true, false);
-        synchronized(mLock) {
-            try {
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Looper creation: wait was interrupted.");
+         synchronized(mLock) {
+            mInitialized = false;
+            createListenerLooper(false, true, false);
+            waitForLooperInitialization_l();
+
+            mReverb2.setEnabled(true);
+            mIsEnabled = true;
+            getReverb(0);
+            mReverb.setEnabled(false);
+            int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+            while (mIsEnabled && (looperWaitCount-- > 0)) {
+                try {
+                    mLock.wait();
+                } catch(Exception e) {
+                }
             }
-        }
-        assertTrue(mInitialized);
-        mReverb2.setEnabled(true);
-        mIsEnabled = true;
-        getReverb(0);
-        synchronized(mLock) {
-            try {
-                mReverb.setEnabled(false);
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Create second effect: wait was interrupted.");
-            } finally {
-                releaseReverb();
-                terminateListenerLooper();
-            }
+            terminateListenerLooper();
+            releaseReverb();
         }
         assertFalse("enable status not updated", mIsEnabled);
     }
 
     //Test case 3.2: test parameter changed listener
     public void test3_2ParameterChangedListener() throws Exception {
-        createListenerLooper(false, false, true);
         synchronized(mLock) {
-            try {
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Looper creation: wait was interrupted.");
+            mInitialized = false;
+            createListenerLooper(false, false, true);
+            waitForLooperInitialization_l();
+
+            getReverb(0);
+            mChangedParameter = -1;
+            mReverb.setRoomLevel((short)0);
+
+            int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+            while ((mChangedParameter == -1) && (looperWaitCount-- > 0)) {
+                try {
+                    mLock.wait();
+                } catch(Exception e) {
+                }
             }
-        }
-        assertTrue(mInitialized);
-        getReverb(0);
-        synchronized(mLock) {
-            try {
-                mChangedParameter = -1;
-                mReverb.setRoomLevel((short)0);
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Create second effect: wait was interrupted.");
-            } finally {
-                releaseReverb();
-                terminateListenerLooper();
-            }
+            terminateListenerLooper();
+            releaseReverb();
         }
         assertEquals("parameter change not received",
                 EnvironmentalReverb.PARAM_ROOM_LEVEL, mChangedParameter);
@@ -414,6 +404,17 @@
         }
     }
 
+    private void waitForLooperInitialization_l() {
+        int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+        while (!mInitialized && (looperWaitCount-- > 0)) {
+            try {
+                mLock.wait();
+            } catch(Exception e) {
+            }
+        }
+        assertTrue(mInitialized);
+    }
+
     // Initializes the reverb listener looper
     class ListenerThread extends Thread {
         boolean mControl;
@@ -426,11 +427,19 @@
             mEnable = enable;
             mParameter = parameter;
         }
+
+        public void cleanUp() {
+            if (mReverb2 != null) {
+                mReverb2.setControlStatusListener(null);
+                mReverb2.setEnableStatusListener(null);
+                mReverb2.setParameterListener(
+                            (EnvironmentalReverb.OnParameterChangeListener)null);
+            }
+        }
     }
 
     private void createListenerLooper(boolean control, boolean enable, boolean parameter) {
-        mInitialized = false;
-        new ListenerThread(control, enable, parameter) {
+        mEffectListenerLooper = new ListenerThread(control, enable, parameter) {
             @Override
             public void run() {
                 // Set up a looper
@@ -443,67 +452,76 @@
                 mReverb2 = new EnvironmentalReverb(0, 0);
                 assertNotNull("could not create reverb2", mReverb2);
 
-                if (mControl) {
-                    mReverb2.setControlStatusListener(
-                            new AudioEffect.OnControlStatusChangeListener() {
-                        public void onControlStatusChange(
-                                AudioEffect effect, boolean controlGranted) {
-                            synchronized(mLock) {
-                                if (effect == mReverb2) {
-                                    mHasControl = controlGranted;
-                                    mLock.notify();
-                                }
-                            }
-                        }
-                    });
-                }
-                if (mEnable) {
-                    mReverb2.setEnableStatusListener(
-                            new AudioEffect.OnEnableStatusChangeListener() {
-                        public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
-                            synchronized(mLock) {
-                                if (effect == mReverb2) {
-                                    mIsEnabled = enabled;
-                                    mLock.notify();
-                                }
-                            }
-                        }
-                    });
-                }
-                if (mParameter) {
-                    mReverb2.setParameterListener(new EnvironmentalReverb.OnParameterChangeListener() {
-                        public void onParameterChange(EnvironmentalReverb effect,
-                                int status, int param, int value)
-                        {
-                            synchronized(mLock) {
-                                if (effect == mReverb2) {
-                                    mChangedParameter = param;
-                                    mLock.notify();
-                                }
-                            }
-                        }
-                    });
-                }
-
                 synchronized(mLock) {
+                    if (mControl) {
+                        mReverb2.setControlStatusListener(
+                                new AudioEffect.OnControlStatusChangeListener() {
+                            public void onControlStatusChange(
+                                    AudioEffect effect, boolean controlGranted) {
+                                synchronized(mLock) {
+                                    if (effect == mReverb2) {
+                                        mHasControl = controlGranted;
+                                        mLock.notify();
+                                    }
+                                }
+                            }
+                        });
+                    }
+                    if (mEnable) {
+                        mReverb2.setEnableStatusListener(
+                                new AudioEffect.OnEnableStatusChangeListener() {
+                            public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
+                                synchronized(mLock) {
+                                    if (effect == mReverb2) {
+                                        mIsEnabled = enabled;
+                                        mLock.notify();
+                                    }
+                                }
+                            }
+                        });
+                    }
+                    if (mParameter) {
+                        mReverb2.setParameterListener(new EnvironmentalReverb.OnParameterChangeListener() {
+                            public void onParameterChange(EnvironmentalReverb effect,
+                                    int status, int param, int value)
+                            {
+                                synchronized(mLock) {
+                                    if (effect == mReverb2) {
+                                        mChangedParameter = param;
+                                        mLock.notify();
+                                    }
+                                }
+                            }
+                        });
+                    }
+
                     mInitialized = true;
                     mLock.notify();
                 }
                 Looper.loop();  // Blocks forever until Looper.quit() is called.
             }
-        }.start();
+        };
+        mEffectListenerLooper.start();
     }
 
     // Terminates the listener looper thread.
     private void terminateListenerLooper() {
+        if (mEffectListenerLooper != null) {
+            mEffectListenerLooper.cleanUp();
+            if (mLooper != null) {
+                mLooper.quit();
+                mLooper = null;
+            }
+            try {
+                mEffectListenerLooper.join();
+            } catch(InterruptedException e) {
+            }
+            mEffectListenerLooper = null;
+        }
         if (mReverb2 != null) {
             mReverb2.release();
             mReverb2 = null;
         }
-        if (mLooper != null) {
-            mLooper.quit();
-            mLooper = null;
-        }
     }
 
 }
\ No newline at end of file
diff --git a/tests/tests/media/src/android/media/cts/EqualizerTest.java b/tests/tests/media/src/android/media/cts/EqualizerTest.java
index 7b3f2ad..3bc0d8e 100644
--- a/tests/tests/media/src/android/media/cts/EqualizerTest.java
+++ b/tests/tests/media/src/android/media/cts/EqualizerTest.java
@@ -33,6 +33,7 @@
     private final static int TEST_FREQUENCY_MILLIHERTZ = 1000000; // 1kHz
     private final static int MIN_NUMBER_OF_PRESETS = 0;
     private final static float TOLERANCE = 100;                   // +/-1dB
+    private final static int MAX_LOOPER_WAIT_COUNT = 10;
 
     private Equalizer mEqualizer = null;
     private Equalizer mEqualizer2 = null;
@@ -43,7 +44,7 @@
     private boolean mInitialized = false;
     private Looper mLooper = null;
     private final Object mLock = new Object();
-
+    private ListenerThread mEffectListenerLooper = null;
 
     //-----------------------------------------------------------------
     // EQUALIZER TESTS:
@@ -244,81 +245,70 @@
 
     //Test case 3.0: test control status listener
     public void test3_0ControlStatusListener() throws Exception {
-        mHasControl = true;
-        createListenerLooper(true, false, false);
         synchronized(mLock) {
-            try {
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Looper creation: wait was interrupted.");
+            mHasControl = true;
+            mInitialized = false;
+            createListenerLooper(true, false, false);
+            waitForLooperInitialization_l();
+
+            getEqualizer(0);
+            int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+            while (mHasControl && (looperWaitCount-- > 0)) {
+                try {
+                    mLock.wait();
+                } catch(Exception e) {
+                }
             }
-        }
-        assertTrue(mInitialized);
-        synchronized(mLock) {
-            try {
-                getEqualizer(0);
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Create second effect: wait was interrupted.");
-            } finally {
-                releaseEqualizer();
-                terminateListenerLooper();
-            }
+            terminateListenerLooper();
+            releaseEqualizer();
         }
         assertFalse("effect control not lost by effect1", mHasControl);
     }
 
     //Test case 3.1: test enable status listener
     public void test3_1EnableStatusListener() throws Exception {
-        createListenerLooper(false, true, false);
         synchronized(mLock) {
-            try {
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Looper creation: wait was interrupted.");
+            mInitialized = false;
+            createListenerLooper(false, true, false);
+            waitForLooperInitialization_l();
+
+            mEqualizer2.setEnabled(true);
+            mIsEnabled = true;
+            getEqualizer(0);
+            mEqualizer.setEnabled(false);
+            int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+            while (mIsEnabled && (looperWaitCount-- > 0)) {
+                try {
+                    mLock.wait();
+                } catch(Exception e) {
+                }
             }
-        }
-        assertTrue(mInitialized);
-        mEqualizer2.setEnabled(true);
-        mIsEnabled = true;
-        getEqualizer(0);
-        synchronized(mLock) {
-            try {
-                mEqualizer.setEnabled(false);
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Create second effect: wait was interrupted.");
-            } finally {
-                releaseEqualizer();
-                terminateListenerLooper();
-            }
+            terminateListenerLooper();
+            releaseEqualizer();
         }
         assertFalse("enable status not updated", mIsEnabled);
     }
 
     //Test case 3.2: test parameter changed listener
     public void test3_2ParameterChangedListener() throws Exception {
-        createListenerLooper(false, false, true);
         synchronized(mLock) {
-            try {
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Looper creation: wait was interrupted.");
+            mInitialized = false;
+            createListenerLooper(false, false, true);
+            waitForLooperInitialization_l();
+
+            getEqualizer(0);
+            mChangedParameter = -1;
+            mEqualizer.setBandLevel((short)0, (short)0);
+
+            int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+            while ((mChangedParameter == -1) && (looperWaitCount-- > 0)) {
+                try {
+                    mLock.wait();
+                } catch(Exception e) {
+                }
             }
-        }
-        assertTrue(mInitialized);
-        getEqualizer(0);
-        synchronized(mLock) {
-            try {
-                mChangedParameter = -1;
-                mEqualizer.setBandLevel((short)0, (short)0);
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Create second effect: wait was interrupted.");
-            } finally {
-                releaseEqualizer();
-                terminateListenerLooper();
-            }
+            terminateListenerLooper();
+            releaseEqualizer();
         }
         assertEquals("parameter change not received",
                 Equalizer.PARAM_BAND_LEVEL, mChangedParameter);
@@ -353,6 +343,17 @@
         }
     }
 
+    private void waitForLooperInitialization_l() {
+        int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+        while (!mInitialized && (looperWaitCount-- > 0)) {
+            try {
+                mLock.wait();
+            } catch(Exception e) {
+            }
+        }
+        assertTrue(mInitialized);
+    }
+
     // Initializes the equalizer listener looper
     class ListenerThread extends Thread {
         boolean mControl;
@@ -365,11 +366,18 @@
             mEnable = enable;
             mParameter = parameter;
         }
+
+        public void cleanUp() {
+            if (mEqualizer2 != null) {
+                mEqualizer2.setControlStatusListener(null);
+                mEqualizer2.setEnableStatusListener(null);
+                mEqualizer2.setParameterListener((Equalizer.OnParameterChangeListener)null);
+            }
+        }
     }
 
     private void createListenerLooper(boolean control, boolean enable, boolean parameter) {
-        mInitialized = false;
-        new ListenerThread(control, enable, parameter) {
+        mEffectListenerLooper = new ListenerThread(control, enable, parameter) {
             @Override
             public void run() {
                 // Set up a looper
@@ -382,67 +390,75 @@
                 mEqualizer2 = new Equalizer(0, 0);
                 assertNotNull("could not create Equalizer2", mEqualizer2);
 
-                if (mControl) {
-                    mEqualizer2.setControlStatusListener(
-                            new AudioEffect.OnControlStatusChangeListener() {
-                        public void onControlStatusChange(
-                                AudioEffect effect, boolean controlGranted) {
-                            synchronized(mLock) {
-                                if (effect == mEqualizer2) {
-                                    mHasControl = controlGranted;
-                                    mLock.notify();
-                                }
-                            }
-                        }
-                    });
-                }
-                if (mEnable) {
-                    mEqualizer2.setEnableStatusListener(
-                            new AudioEffect.OnEnableStatusChangeListener() {
-                        public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
-                            synchronized(mLock) {
-                                if (effect == mEqualizer2) {
-                                    mIsEnabled = enabled;
-                                    mLock.notify();
-                                }
-                            }
-                        }
-                    });
-                }
-                if (mParameter) {
-                    mEqualizer2.setParameterListener(new Equalizer.OnParameterChangeListener() {
-                        public void onParameterChange(Equalizer effect,
-                                int status, int param1, int param2, int value)
-                        {
-                            synchronized(mLock) {
-                                if (effect == mEqualizer2) {
-                                    mChangedParameter = param1;
-                                    mLock.notify();
-                                }
-                            }
-                        }
-                    });
-                }
-
                 synchronized(mLock) {
+                    if (mControl) {
+                        mEqualizer2.setControlStatusListener(
+                                new AudioEffect.OnControlStatusChangeListener() {
+                            public void onControlStatusChange(
+                                    AudioEffect effect, boolean controlGranted) {
+                                synchronized(mLock) {
+                                    if (effect == mEqualizer2) {
+                                        mHasControl = controlGranted;
+                                        mLock.notify();
+                                    }
+                                }
+                            }
+                        });
+                    }
+                    if (mEnable) {
+                        mEqualizer2.setEnableStatusListener(
+                                new AudioEffect.OnEnableStatusChangeListener() {
+                            public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
+                                synchronized(mLock) {
+                                    if (effect == mEqualizer2) {
+                                        mIsEnabled = enabled;
+                                        mLock.notify();
+                                    }
+                                }
+                            }
+                        });
+                    }
+                    if (mParameter) {
+                        mEqualizer2.setParameterListener(new Equalizer.OnParameterChangeListener() {
+                            public void onParameterChange(Equalizer effect,
+                                    int status, int param1, int param2, int value)
+                            {
+                                synchronized(mLock) {
+                                    if (effect == mEqualizer2) {
+                                        mChangedParameter = param1;
+                                        mLock.notify();
+                                    }
+                                }
+                            }
+                        });
+                    }
                     mInitialized = true;
                     mLock.notify();
                 }
                 Looper.loop();  // Blocks forever until Looper.quit() is called.
             }
-        }.start();
+        };
+        mEffectListenerLooper.start();
     }
 
     // Terminates the listener looper thread.
     private void terminateListenerLooper() {
+        if (mEffectListenerLooper != null) {
+            mEffectListenerLooper.cleanUp();
+            if (mLooper != null) {
+                mLooper.quit();
+                mLooper = null;
+            }
+            try {
+                mEffectListenerLooper.join();
+            } catch(InterruptedException e) {
+            }
+            mEffectListenerLooper = null;
+        }
         if (mEqualizer2 != null) {
             mEqualizer2.release();
             mEqualizer2 = null;
         }
-        if (mLooper != null) {
-            mLooper.quit();
-            mLooper = null;
-        }
     }
 
 }
diff --git a/tests/tests/media/src/android/media/cts/PresetReverbTest.java b/tests/tests/media/src/android/media/cts/PresetReverbTest.java
index b384bd7..d69256c 100644
--- a/tests/tests/media/src/android/media/cts/PresetReverbTest.java
+++ b/tests/tests/media/src/android/media/cts/PresetReverbTest.java
@@ -29,6 +29,8 @@
     private String TAG = "PresetReverbTest";
     private final static short FIRST_PRESET = PresetReverb.PRESET_NONE;
     private final static short LAST_PRESET = PresetReverb.PRESET_PLATE;
+    private final static int MAX_LOOPER_WAIT_COUNT = 10;
+
     private PresetReverb mReverb = null;
     private PresetReverb mReverb2 = null;
     private int mSession = -1;
@@ -38,7 +40,7 @@
     private boolean mInitialized = false;
     private Looper mLooper = null;
     private final Object mLock = new Object();
-
+    private ListenerThread mEffectListenerLooper = null;
 
     //-----------------------------------------------------------------
     // PRESET REVERB TESTS:
@@ -157,81 +159,70 @@
 
     //Test case 3.0: test control status listener
     public void test3_0ControlStatusListener() throws Exception {
-        mHasControl = true;
-        createListenerLooper(true, false, false);
-        synchronized(mLock) {
-            try {
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Looper creation: wait was interrupted.");
+         synchronized(mLock) {
+            mHasControl = true;
+            mInitialized = false;
+            createListenerLooper(true, false, false);
+            waitForLooperInitialization_l();
+
+            getReverb(0);
+            int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+            while (mHasControl && (looperWaitCount-- > 0)) {
+                try {
+                    mLock.wait();
+                } catch(Exception e) {
+                }
             }
-        }
-        assertTrue(mInitialized);
-        synchronized(mLock) {
-            try {
-                getReverb(0);
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Create second effect: wait was interrupted.");
-            } finally {
-                releaseReverb();
-                terminateListenerLooper();
-            }
+            terminateListenerLooper();
+            releaseReverb();
         }
         assertFalse("effect control not lost by effect1", mHasControl);
     }
 
     //Test case 3.1: test enable status listener
     public void test3_1EnableStatusListener() throws Exception {
-        createListenerLooper(false, true, false);
-        synchronized(mLock) {
-            try {
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Looper creation: wait was interrupted.");
+         synchronized(mLock) {
+            mInitialized = false;
+            createListenerLooper(false, true, false);
+            waitForLooperInitialization_l();
+
+            mReverb2.setEnabled(true);
+            mIsEnabled = true;
+            getReverb(0);
+            mReverb.setEnabled(false);
+            int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+            while (mIsEnabled && (looperWaitCount-- > 0)) {
+                try {
+                    mLock.wait();
+                } catch(Exception e) {
+                }
             }
-        }
-        assertTrue(mInitialized);
-        mReverb2.setEnabled(true);
-        mIsEnabled = true;
-        getReverb(0);
-        synchronized(mLock) {
-            try {
-                mReverb.setEnabled(false);
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Create second effect: wait was interrupted.");
-            } finally {
-                releaseReverb();
-                terminateListenerLooper();
-            }
+            terminateListenerLooper();
+            releaseReverb();
         }
         assertFalse("enable status not updated", mIsEnabled);
     }
 
     //Test case 3.2: test parameter changed listener
     public void test3_2ParameterChangedListener() throws Exception {
-        createListenerLooper(false, false, true);
         synchronized(mLock) {
-            try {
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Looper creation: wait was interrupted.");
+            mInitialized = false;
+            createListenerLooper(false, false, true);
+            waitForLooperInitialization_l();
+
+            getReverb(0);
+            mChangedParameter = -1;
+            mReverb.setPreset(PresetReverb.PRESET_SMALLROOM);
+
+            int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+            while ((mChangedParameter == -1) && (looperWaitCount-- > 0)) {
+                try {
+                    mLock.wait();
+                } catch(Exception e) {
+                }
             }
-        }
-        assertTrue(mInitialized);
-        getReverb(0);
-        synchronized(mLock) {
-            try {
-                mChangedParameter = -1;
-                mReverb.setPreset(PresetReverb.PRESET_SMALLROOM);
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Create second effect: wait was interrupted.");
-            } finally {
-                releaseReverb();
-                terminateListenerLooper();
-            }
+            terminateListenerLooper();
+            releaseReverb();
         }
         assertEquals("parameter change not received",
                 PresetReverb.PARAM_PRESET, mChangedParameter);
@@ -266,6 +257,17 @@
         }
     }
 
+    private void waitForLooperInitialization_l() {
+        int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+        while (!mInitialized && (looperWaitCount-- > 0)) {
+            try {
+                mLock.wait();
+            } catch(Exception e) {
+            }
+        }
+        assertTrue(mInitialized);
+    }
+
     // Initializes the reverb listener looper
     class ListenerThread extends Thread {
         boolean mControl;
@@ -278,11 +280,19 @@
             mEnable = enable;
             mParameter = parameter;
         }
+
+        public void cleanUp() {
+            if (mReverb2 != null) {
+                mReverb2.setControlStatusListener(null);
+                mReverb2.setEnableStatusListener(null);
+                mReverb2.setParameterListener(
+                            (PresetReverb.OnParameterChangeListener)null);
+            }
+        }
     }
 
     private void createListenerLooper(boolean control, boolean enable, boolean parameter) {
-        mInitialized = false;
-        new ListenerThread(control, enable, parameter) {
+        mEffectListenerLooper = new ListenerThread(control, enable, parameter) {
             @Override
             public void run() {
                 // Set up a looper
@@ -295,67 +305,77 @@
                 mReverb2 = new PresetReverb(0, 0);
                 assertNotNull("could not create Reverb2", mReverb2);
 
-                if (mControl) {
-                    mReverb2.setControlStatusListener(
-                            new AudioEffect.OnControlStatusChangeListener() {
-                        public void onControlStatusChange(
-                                AudioEffect effect, boolean controlGranted) {
-                            synchronized(mLock) {
-                                if (effect == mReverb2) {
-                                    mHasControl = controlGranted;
-                                    mLock.notify();
-                                }
-                            }
-                        }
-                    });
-                }
-                if (mEnable) {
-                    mReverb2.setEnableStatusListener(
-                            new AudioEffect.OnEnableStatusChangeListener() {
-                        public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
-                            synchronized(mLock) {
-                                if (effect == mReverb2) {
-                                    mIsEnabled = enabled;
-                                    mLock.notify();
-                                }
-                            }
-                        }
-                    });
-                }
-                if (mParameter) {
-                    mReverb2.setParameterListener(new PresetReverb.OnParameterChangeListener() {
-                        public void onParameterChange(PresetReverb effect,
-                                int status, int param, short value)
-                        {
-                            synchronized(mLock) {
-                                if (effect == mReverb2) {
-                                    mChangedParameter = param;
-                                    mLock.notify();
-                                }
-                            }
-                        }
-                    });
-                }
-
                 synchronized(mLock) {
+                    if (mControl) {
+                        mReverb2.setControlStatusListener(
+                                new AudioEffect.OnControlStatusChangeListener() {
+                            public void onControlStatusChange(
+                                    AudioEffect effect, boolean controlGranted) {
+                                synchronized(mLock) {
+                                    if (effect == mReverb2) {
+                                        mHasControl = controlGranted;
+                                        mLock.notify();
+                                    }
+                                }
+                            }
+                        });
+                    }
+                    if (mEnable) {
+                        mReverb2.setEnableStatusListener(
+                                new AudioEffect.OnEnableStatusChangeListener() {
+                            public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
+                                synchronized(mLock) {
+                                    if (effect == mReverb2) {
+                                        mIsEnabled = enabled;
+                                        mLock.notify();
+                                    }
+                                }
+                            }
+                        });
+                    }
+                    if (mParameter) {
+                        mReverb2.setParameterListener(new PresetReverb.OnParameterChangeListener() {
+                            public void onParameterChange(PresetReverb effect,
+                                    int status, int param, short value)
+                            {
+                                synchronized(mLock) {
+                                    if (effect == mReverb2) {
+                                        mChangedParameter = param;
+                                        mLock.notify();
+                                    }
+                                }
+                            }
+                        });
+                    }
+
                     mInitialized = true;
                     mLock.notify();
                 }
                 Looper.loop();  // Blocks forever until Looper.quit() is called.
             }
-        }.start();
+        };
+        mEffectListenerLooper.start();
     }
 
     // Terminates the listener looper thread.
     private void terminateListenerLooper() {
+        if (mEffectListenerLooper != null) {
+            mEffectListenerLooper.cleanUp();
+            if (mLooper != null) {
+                mLooper.quit();
+                mLooper = null;
+            }
+            try {
+                mEffectListenerLooper.join();
+            } catch(InterruptedException e) {
+            }
+            mEffectListenerLooper = null;
+        }
+
         if (mReverb2 != null) {
             mReverb2.release();
             mReverb2 = null;
         }
-        if (mLooper != null) {
-            mLooper.quit();
-            mLooper = null;
-        }
     }
 
 }
\ No newline at end of file
diff --git a/tests/tests/media/src/android/media/cts/VirtualizerTest.java b/tests/tests/media/src/android/media/cts/VirtualizerTest.java
index 53320b8..3d18c47 100644
--- a/tests/tests/media/src/android/media/cts/VirtualizerTest.java
+++ b/tests/tests/media/src/android/media/cts/VirtualizerTest.java
@@ -30,6 +30,7 @@
     private final static short TEST_STRENGTH = 500;
     private final static short TEST_STRENGTH2 = 1000;
     private final static float STRENGTH_TOLERANCE = 1.1f;  // 10%
+    private final static int MAX_LOOPER_WAIT_COUNT = 10;
 
     private Virtualizer mVirtualizer = null;
     private Virtualizer mVirtualizer2 = null;
@@ -40,6 +41,7 @@
     private boolean mInitialized = false;
     private Looper mLooper = null;
     private final Object mLock = new Object();
+    private ListenerThread mEffectListenerLooper = null;
 
     //-----------------------------------------------------------------
     // VIRTUALIZER TESTS:
@@ -188,81 +190,70 @@
 
     //Test case 3.0: test control status listener
     public void test3_0ControlStatusListener() throws Exception {
-        mHasControl = true;
-        createListenerLooper(true, false, false);
         synchronized(mLock) {
-            try {
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Looper creation: wait was interrupted.");
+            mHasControl = true;
+            mInitialized = false;
+            createListenerLooper(true, false, false);
+            waitForLooperInitialization_l();
+
+            getVirtualizer(0);
+            int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+            while (mHasControl && (looperWaitCount-- > 0)) {
+                try {
+                    mLock.wait();
+                } catch(Exception e) {
+                }
             }
-        }
-        assertTrue(mInitialized);
-        synchronized(mLock) {
-            try {
-                getVirtualizer(0);
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Create second effect: wait was interrupted.");
-            } finally {
-                releaseVirtualizer();
-                terminateListenerLooper();
-            }
+            terminateListenerLooper();
+            releaseVirtualizer();
         }
         assertFalse("effect control not lost by effect1", mHasControl);
     }
 
     //Test case 3.1: test enable status listener
     public void test3_1EnableStatusListener() throws Exception {
-        createListenerLooper(false, true, false);
         synchronized(mLock) {
-            try {
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Looper creation: wait was interrupted.");
+            mInitialized = false;
+            createListenerLooper(false, true, false);
+            waitForLooperInitialization_l();
+
+            mVirtualizer2.setEnabled(true);
+            mIsEnabled = true;
+            getVirtualizer(0);
+            mVirtualizer.setEnabled(false);
+            int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+            while (mIsEnabled && (looperWaitCount-- > 0)) {
+                try {
+                    mLock.wait();
+                } catch(Exception e) {
+                }
             }
-        }
-        assertTrue(mInitialized);
-        mVirtualizer2.setEnabled(true);
-        mIsEnabled = true;
-        getVirtualizer(0);
-        synchronized(mLock) {
-            try {
-                mVirtualizer.setEnabled(false);
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Create second effect: wait was interrupted.");
-            } finally {
-                releaseVirtualizer();
-                terminateListenerLooper();
-            }
+            terminateListenerLooper();
+            releaseVirtualizer();
         }
         assertFalse("enable status not updated", mIsEnabled);
     }
 
     //Test case 3.2: test parameter changed listener
     public void test3_2ParameterChangedListener() throws Exception {
-        createListenerLooper(false, false, true);
         synchronized(mLock) {
-            try {
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Looper creation: wait was interrupted.");
+            mInitialized = false;
+            createListenerLooper(false, false, true);
+            waitForLooperInitialization_l();
+
+            getVirtualizer(0);
+            mChangedParameter = -1;
+            mVirtualizer.setStrength(TEST_STRENGTH);
+
+            int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+            while ((mChangedParameter == -1) && (looperWaitCount-- > 0)) {
+                try {
+                    mLock.wait();
+                } catch(Exception e) {
+                }
             }
-        }
-        assertTrue(mInitialized);
-        getVirtualizer(0);
-        synchronized(mLock) {
-            try {
-                mChangedParameter = -1;
-                mVirtualizer.setStrength(TEST_STRENGTH);
-                mLock.wait(1000);
-            } catch(Exception e) {
-                Log.e(TAG, "Create second effect: wait was interrupted.");
-            } finally {
-                releaseVirtualizer();
-                terminateListenerLooper();
-            }
+            terminateListenerLooper();
+            releaseVirtualizer();
         }
         assertEquals("parameter change not received",
                 Virtualizer.PARAM_STRENGTH, mChangedParameter);
@@ -297,6 +288,17 @@
         }
     }
 
+    private void waitForLooperInitialization_l() {
+        int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+        while (!mInitialized && (looperWaitCount-- > 0)) {
+            try {
+                mLock.wait();
+            } catch(Exception e) {
+            }
+        }
+        assertTrue(mInitialized);
+    }
+
     // Initializes the virtualizer listener looper
     class ListenerThread extends Thread {
         boolean mControl;
@@ -309,11 +311,19 @@
             mEnable = enable;
             mParameter = parameter;
         }
+
+        public void cleanUp() {
+            if (mVirtualizer2 != null) {
+                mVirtualizer2.setControlStatusListener(null);
+                mVirtualizer2.setEnableStatusListener(null);
+                mVirtualizer2.setParameterListener(
+                        (Virtualizer.OnParameterChangeListener)null);
+            }
+        }
     }
 
     private void createListenerLooper(boolean control, boolean enable, boolean parameter) {
-        mInitialized = false;
-        new ListenerThread(control, enable, parameter) {
+        mEffectListenerLooper = new ListenerThread(control, enable, parameter) {
             @Override
             public void run() {
                 // Set up a looper
@@ -326,67 +336,76 @@
                 mVirtualizer2 = new Virtualizer(0, 0);
                 assertNotNull("could not create virtualizer2", mVirtualizer2);
 
-                if (mControl) {
-                    mVirtualizer2.setControlStatusListener(
-                            new AudioEffect.OnControlStatusChangeListener() {
-                        public void onControlStatusChange(
-                                AudioEffect effect, boolean controlGranted) {
-                            synchronized(mLock) {
-                                if (effect == mVirtualizer2) {
-                                    mHasControl = controlGranted;
-                                    mLock.notify();
-                                }
-                            }
-                        }
-                    });
-                }
-                if (mEnable) {
-                    mVirtualizer2.setEnableStatusListener(
-                            new AudioEffect.OnEnableStatusChangeListener() {
-                        public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
-                            synchronized(mLock) {
-                                if (effect == mVirtualizer2) {
-                                    mIsEnabled = enabled;
-                                    mLock.notify();
-                                }
-                            }
-                        }
-                    });
-                }
-                if (mParameter) {
-                    mVirtualizer2.setParameterListener(new Virtualizer.OnParameterChangeListener() {
-                        public void onParameterChange(Virtualizer effect, int status,
-                                int param, short value)
-                        {
-                            synchronized(mLock) {
-                                if (effect == mVirtualizer2) {
-                                    mChangedParameter = param;
-                                    mLock.notify();
-                                }
-                            }
-                        }
-                    });
-                }
-
                 synchronized(mLock) {
+                    if (mControl) {
+                        mVirtualizer2.setControlStatusListener(
+                                new AudioEffect.OnControlStatusChangeListener() {
+                            public void onControlStatusChange(
+                                    AudioEffect effect, boolean controlGranted) {
+                                synchronized(mLock) {
+                                    if (effect == mVirtualizer2) {
+                                        mHasControl = controlGranted;
+                                        mLock.notify();
+                                    }
+                                }
+                            }
+                        });
+                    }
+                    if (mEnable) {
+                        mVirtualizer2.setEnableStatusListener(
+                                new AudioEffect.OnEnableStatusChangeListener() {
+                            public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
+                                synchronized(mLock) {
+                                    if (effect == mVirtualizer2) {
+                                        mIsEnabled = enabled;
+                                        mLock.notify();
+                                    }
+                                }
+                            }
+                        });
+                    }
+                    if (mParameter) {
+                        mVirtualizer2.setParameterListener(new Virtualizer.OnParameterChangeListener() {
+                            public void onParameterChange(Virtualizer effect, int status,
+                                    int param, short value)
+                            {
+                                synchronized(mLock) {
+                                    if (effect == mVirtualizer2) {
+                                        mChangedParameter = param;
+                                        mLock.notify();
+                                    }
+                                }
+                            }
+                        });
+                    }
+
                     mInitialized = true;
                     mLock.notify();
                 }
                 Looper.loop();  // Blocks forever until Looper.quit() is called.
             }
-        }.start();
+        };
+        mEffectListenerLooper.start();
     }
 
     // Terminates the listener looper thread.
     private void terminateListenerLooper() {
+        if (mEffectListenerLooper != null) {
+            mEffectListenerLooper.cleanUp();
+            if (mLooper != null) {
+                mLooper.quit();
+                mLooper = null;
+            }
+            try {
+                mEffectListenerLooper.join();
+            } catch(InterruptedException e) {
+            }
+            mEffectListenerLooper = null;
+        }
         if (mVirtualizer2 != null) {
             mVirtualizer2.release();
             mVirtualizer2 = null;
         }
-        if (mLooper != null) {
-            mLooper.quit();
-            mLooper = null;
-        }
     }
 
 }
\ No newline at end of file
diff --git a/tests/tests/media/src/android/media/cts/VisualizerTest.java b/tests/tests/media/src/android/media/cts/VisualizerTest.java
index 689b06b..e2a9fdd 100644
--- a/tests/tests/media/src/android/media/cts/VisualizerTest.java
+++ b/tests/tests/media/src/android/media/cts/VisualizerTest.java
@@ -30,6 +30,7 @@
     private final static int MIN_CAPTURE_RATE_MAX = 10000; // 10Hz
     private final static int MIN_CAPTURE_SIZE_MAX = 1024;
     private final static int MAX_CAPTURE_SIZE_MIN = 512;
+    private final static int MAX_LOOPER_WAIT_COUNT = 10;
 
     private Visualizer mVisualizer = null;
     private int mSession = -1;
@@ -40,6 +41,7 @@
     private byte[] mFft = null;
     private boolean mCaptureWaveform = false;
     private boolean mCaptureFft = false;
+    private Thread mListenerThread;
 
     //-----------------------------------------------------------------
     // VISUALIZER TESTS:
@@ -138,16 +140,11 @@
             assertEquals("getFft reports energy for silence",
                     0, energy);
 
-        } catch (IllegalArgumentException e) {
-            fail("Bad parameter value");
-        } catch (UnsupportedOperationException e) {
-            fail("get parameter() rejected");
         } catch (IllegalStateException e) {
-            fail("get parameter() called in wrong state");
+            fail("method called in wrong state");
         } catch (InterruptedException e) {
             fail("sleep() interrupted");
-        }
-        finally {
+        } finally {
             releaseVisualizer();
         }
     }
@@ -156,29 +153,27 @@
     public void test2_1ListenerCapture() throws Exception {
         try {
             getVisualizer(0);
-            createListenerLooper();
             synchronized(mLock) {
-                try {
-                    mLock.wait(1000);
-                } catch(Exception e) {
-                    Log.e(TAG, "Looper creation: wait was interrupted.");
-                }
+                mInitialized = false;
+                createListenerLooper();
+                waitForLooperInitialization_l();
             }
-            assertTrue(mInitialized);
-
             mVisualizer.setEnabled(true);
             assertTrue("visualizer not enabled", mVisualizer.getEnabled());
 
             Thread.sleep(100);
+
             // check capture on silence
             synchronized(mLock) {
-                try {
-                    mCaptureWaveform = true;
-                    mLock.wait(1000);
-                    mCaptureWaveform = false;
-                } catch(Exception e) {
-                    Log.e(TAG, "Capture waveform: wait was interrupted.");
+                mCaptureWaveform = true;
+                int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+                while ((mWaveform == null) && (looperWaitCount-- > 0)) {
+                    try {
+                        mLock.wait();
+                    } catch(Exception e) {
+                    }
                 }
+                mCaptureWaveform = false;
             }
             assertNotNull("waveform capture failed", mWaveform);
             int energy = computeEnergy(mWaveform, true);
@@ -186,25 +181,23 @@
                     0, energy);
 
             synchronized(mLock) {
-                try {
-                    mCaptureFft = true;
-                    mLock.wait(1000);
-                    mCaptureFft = false;
-                } catch(Exception e) {
-                    Log.e(TAG, "Capture FFT: wait was interrupted.");
+                mCaptureFft = true;
+                int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+                while ((mFft == null) && (looperWaitCount-- > 0)) {
+                    try {
+                        mLock.wait();
+                    } catch(Exception e) {
+                    }
                 }
+                mCaptureFft = false;
             }
             assertNotNull("FFT capture failed", mFft);
             energy = computeEnergy(mFft, false);
             assertEquals("getFft reports energy for silence",
                     0, energy);
 
-        } catch (IllegalArgumentException e) {
-            fail("Bad parameter value");
-        } catch (UnsupportedOperationException e) {
-            fail("get parameter() rejected");
         } catch (IllegalStateException e) {
-            fail("get parameter() called in wrong state");
+            fail("method called in wrong state");
         } catch (InterruptedException e) {
             fail("sleep() interrupted");
         } finally {
@@ -260,11 +253,21 @@
             mVisualizer.release();
             mVisualizer = null;
         }
-   }
+    }
+
+    private void waitForLooperInitialization_l() {
+        int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
+        while (!mInitialized && (looperWaitCount-- > 0)) {
+            try {
+                mLock.wait();
+            } catch(Exception e) {
+            }
+        }
+        assertTrue(mInitialized);
+    }
 
     private void createListenerLooper() {
-
-        new Thread() {
+        mListenerThread = new Thread() {
             @Override
             public void run() {
                 // Set up a looper to be used by mEffect.
@@ -274,52 +277,60 @@
                 // after we are done with it.
                 mLooper = Looper.myLooper();
 
-                if (mVisualizer != null) {
-                    mVisualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener() {
-                        public void onWaveFormDataCapture(
-                                Visualizer visualizer, byte[] waveform, int samplingRate) {
-                            synchronized(mLock) {
-                                if (visualizer == mVisualizer) {
-                                    if (mCaptureWaveform) {
-                                        mWaveform = waveform;
-                                        mLock.notify();
-                                    }
-                                }
-                            }
-                        }
-
-                        public void onFftDataCapture(
-                                Visualizer visualizer, byte[] fft, int samplingRate) {
-                            synchronized(mLock) {
-                                if (visualizer == mVisualizer) {
-                                    if (mCaptureFft) {
-                                        mFft = fft;
-                                        mLock.notify();
-                                    }
-                                }
-                            }
-                        }
-                    },
-                    10000,
-                    true,
-                    true);
-                }
-
                 synchronized(mLock) {
+                    if (mVisualizer != null) {
+                        mVisualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener() {
+                            public void onWaveFormDataCapture(
+                                    Visualizer visualizer, byte[] waveform, int samplingRate) {
+                                synchronized(mLock) {
+                                    if (visualizer == mVisualizer) {
+                                        if (mCaptureWaveform) {
+                                            mWaveform = waveform;
+                                            mLock.notify();
+                                        }
+                                    }
+                                }
+                            }
+
+                            public void onFftDataCapture(
+                                    Visualizer visualizer, byte[] fft, int samplingRate) {
+                                synchronized(mLock) {
+                                    Log.e(TAG, "onFftDataCapture 2 mCaptureFft: "+mCaptureFft);
+                                    if (visualizer == mVisualizer) {
+                                        if (mCaptureFft) {
+                                            mFft = fft;
+                                            mLock.notify();
+                                        }
+                                    }
+                                }
+                            }
+                        },
+                        10000,
+                        true,
+                        true);
+                    }
                     mInitialized = true;
                     mLock.notify();
                 }
                 Looper.loop();  // Blocks forever until Looper.quit() is called.
             }
-        }.start();
+        };
+        mListenerThread.start();
     }
     /*
      * Terminates the listener looper thread.
      */
     private void terminateListenerLooper() {
-        if (mLooper != null) {
-            mLooper.quit();
-            mLooper = null;
+        if (mListenerThread != null) {
+            if (mLooper != null) {
+                mLooper.quit();
+                mLooper = null;
+            }
+            try {
+                mListenerThread.join();
+            } catch(InterruptedException e) {
+            }
+            mListenerThread = null;
         }
     }
 }