Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.media.cts;
     18 
     19 import android.media.audiofx.AudioEffect;
     20 import android.media.AudioFormat;
     21 import android.media.AudioManager;
     22 import android.media.audiofx.BassBoost;
     23 import android.os.Looper;
     24 import android.test.AndroidTestCase;
     25 import android.util.Log;
     26 
     27 public class BassBoostTest extends PostProcTestBase {
     28 
     29     private String TAG = "BassBoostTest";
     30     private final static short TEST_STRENGTH = 500;
     31     private final static short TEST_STRENGTH2 = 1000;
     32     private final static float STRENGTH_TOLERANCE = 1.1f;  // 10%
     33     private final static int MAX_LOOPER_WAIT_COUNT = 10;
     34 
     35     private BassBoost mBassBoost = null;
     36     private BassBoost mBassBoost2 = null;
     37     private ListenerThread mEffectListenerLooper = null;
     38 
     39     //-----------------------------------------------------------------
     40     // BASS BOOST TESTS:
     41     //----------------------------------
     42 
     43     //-----------------------------------------------------------------
     44     // 0 - constructor
     45     //----------------------------------
     46 
     47     //Test case 0.0: test constructor and release
     48     public void test0_0ConstructorAndRelease() throws Exception {
     49         if (!isBassBoostAvailable()) {
     50             return;
     51         }
     52         BassBoost eq = null;
     53         try {
     54             eq = new BassBoost(0, getSessionId());
     55             try {
     56                 assertTrue("invalid effect ID", (eq.getId() != 0));
     57             } catch (IllegalStateException e) {
     58                 fail("BassBoost not initialized");
     59             }
     60             // test passed
     61         } catch (IllegalArgumentException e) {
     62             fail("BassBoost not found");
     63         } catch (UnsupportedOperationException e) {
     64             fail("Effect library not loaded");
     65         } finally {
     66             if (eq != null) {
     67                 eq.release();
     68             }
     69         }
     70     }
     71 
     72 
     73     //-----------------------------------------------------------------
     74     // 1 - get/set parameters
     75     //----------------------------------
     76 
     77     //Test case 1.0: test strength
     78     public void test1_0Strength() throws Exception {
     79         if (!isBassBoostAvailable()) {
     80             return;
     81         }
     82         getBassBoost(getSessionId());
     83         try {
     84             if (mBassBoost.getStrengthSupported()) {
     85                 short strength = mBassBoost.getRoundedStrength();
     86                 strength = (strength == TEST_STRENGTH) ? TEST_STRENGTH2 : TEST_STRENGTH;
     87                 mBassBoost.setStrength((short)strength);
     88                 short strength2 = mBassBoost.getRoundedStrength();
     89                 // allow STRENGTH_TOLERANCE difference between set strength and rounded strength
     90                 assertTrue("got incorrect strength",
     91                         ((float)strength2 > (float)strength / STRENGTH_TOLERANCE) &&
     92                         ((float)strength2 < (float)strength * STRENGTH_TOLERANCE));
     93             } else {
     94                 short strength = mBassBoost.getRoundedStrength();
     95                 assertTrue("got incorrect strength", strength >= 0 && strength <= 1000);
     96             }
     97             // test passed
     98         } catch (IllegalArgumentException e) {
     99             fail("Bad parameter value");
    100         } catch (UnsupportedOperationException e) {
    101             fail("get parameter() rejected");
    102         } catch (IllegalStateException e) {
    103             fail("get parameter() called in wrong state");
    104         } finally {
    105             releaseBassBoost();
    106         }
    107     }
    108 
    109     //Test case 1.1: test properties
    110     public void test1_1Properties() throws Exception {
    111         if (!isBassBoostAvailable()) {
    112             return;
    113         }
    114         getBassBoost(getSessionId());
    115         try {
    116             BassBoost.Settings settings = mBassBoost.getProperties();
    117             String str = settings.toString();
    118             settings = new BassBoost.Settings(str);
    119 
    120             short strength = settings.strength;
    121             if (mBassBoost.getStrengthSupported()) {
    122                 strength = (strength == TEST_STRENGTH) ? TEST_STRENGTH2 : TEST_STRENGTH;
    123             }
    124             settings.strength = strength;
    125             mBassBoost.setProperties(settings);
    126             settings = mBassBoost.getProperties();
    127 
    128             if (mBassBoost.getStrengthSupported()) {
    129                 // allow STRENGTH_TOLERANCE difference between set strength and rounded strength
    130                 assertTrue("got incorrect strength",
    131                         ((float)settings.strength > (float)strength / STRENGTH_TOLERANCE) &&
    132                         ((float)settings.strength < (float)strength * STRENGTH_TOLERANCE));
    133             }
    134             // test passed
    135         } catch (IllegalArgumentException e) {
    136             fail("Bad parameter value");
    137         } catch (UnsupportedOperationException e) {
    138             fail("get parameter() rejected");
    139         } catch (IllegalStateException e) {
    140             fail("get parameter() called in wrong state");
    141         } finally {
    142             releaseBassBoost();
    143         }
    144     }
    145 
    146     //Test case 1.2: test setStrength() throws exception after release
    147     public void test1_2SetStrengthAfterRelease() throws Exception {
    148         if (!isBassBoostAvailable()) {
    149             return;
    150         }
    151         getBassBoost(getSessionId());
    152         mBassBoost.release();
    153         try {
    154             mBassBoost.setStrength(TEST_STRENGTH);
    155             fail("setStrength() processed after release()");
    156         } catch (IllegalStateException e) {
    157             // test passed
    158         } finally {
    159             releaseBassBoost();
    160         }
    161     }
    162 
    163     //-----------------------------------------------------------------
    164     // 2 - Effect enable/disable
    165     //----------------------------------
    166 
    167     //Test case 2.0: test setEnabled() and getEnabled() in valid state
    168     public void test2_0SetEnabledGetEnabled() throws Exception {
    169         if (!isBassBoostAvailable()) {
    170             return;
    171         }
    172         getBassBoost(getSessionId());
    173         try {
    174             mBassBoost.setEnabled(true);
    175             assertTrue("invalid state from getEnabled", mBassBoost.getEnabled());
    176             mBassBoost.setEnabled(false);
    177             assertFalse("invalid state to getEnabled", mBassBoost.getEnabled());
    178             // test passed
    179         } catch (IllegalStateException e) {
    180             fail("setEnabled() in wrong state");
    181         } finally {
    182             releaseBassBoost();
    183         }
    184     }
    185 
    186     //Test case 2.1: test setEnabled() throws exception after release
    187     public void test2_1SetEnabledAfterRelease() throws Exception {
    188         if (!isBassBoostAvailable()) {
    189             return;
    190         }
    191         getBassBoost(getSessionId());
    192         mBassBoost.release();
    193         try {
    194             mBassBoost.setEnabled(true);
    195             fail("setEnabled() processed after release()");
    196         } catch (IllegalStateException e) {
    197             // test passed
    198         } finally {
    199             releaseBassBoost();
    200         }
    201     }
    202 
    203     //-----------------------------------------------------------------
    204     // 3 priority and listeners
    205     //----------------------------------
    206 
    207     //Test case 3.0: test control status listener
    208     public void test3_0ControlStatusListener() throws Exception {
    209         if (!isBassBoostAvailable()) {
    210             return;
    211         }
    212         synchronized(mLock) {
    213             mHasControl = true;
    214             mInitialized = false;
    215             createListenerLooper(true, false, false);
    216             waitForLooperInitialization_l();
    217 
    218             getBassBoost(mSession);
    219             int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
    220             while (mHasControl && (looperWaitCount-- > 0)) {
    221                 try {
    222                     mLock.wait();
    223                 } catch(Exception e) {
    224                 }
    225             }
    226             terminateListenerLooper();
    227             releaseBassBoost();
    228         }
    229         assertFalse("effect control not lost by effect1", mHasControl);
    230     }
    231 
    232     //Test case 3.1: test enable status listener
    233     public void test3_1EnableStatusListener() throws Exception {
    234         if (!isBassBoostAvailable()) {
    235             return;
    236         }
    237         synchronized(mLock) {
    238             mInitialized = false;
    239             createListenerLooper(false, true, false);
    240             waitForLooperInitialization_l();
    241 
    242             mBassBoost2.setEnabled(true);
    243             mIsEnabled = true;
    244             getBassBoost(mSession);
    245             mBassBoost.setEnabled(false);
    246             int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
    247             while (mIsEnabled && (looperWaitCount-- > 0)) {
    248                 try {
    249                     mLock.wait();
    250                 } catch(Exception e) {
    251                 }
    252             }
    253             terminateListenerLooper();
    254             releaseBassBoost();
    255         }
    256         assertFalse("enable status not updated", mIsEnabled);
    257     }
    258 
    259     //Test case 3.2: test parameter changed listener
    260     public void test3_2ParameterChangedListener() throws Exception {
    261         if (!isBassBoostAvailable()) {
    262             return;
    263         }
    264         synchronized(mLock) {
    265             mInitialized = false;
    266             createListenerLooper(false, false, true);
    267             waitForLooperInitialization_l();
    268 
    269             getBassBoost(mSession);
    270             mChangedParameter = -1;
    271             mBassBoost.setStrength(TEST_STRENGTH);
    272             int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
    273             while ((mChangedParameter == -1) && (looperWaitCount-- > 0)) {
    274                 try {
    275                     mLock.wait();
    276                 } catch(Exception e) {
    277                 }
    278             }
    279             terminateListenerLooper();
    280             releaseBassBoost();
    281         }
    282         assertEquals("parameter change not received",
    283                 BassBoost.PARAM_STRENGTH, mChangedParameter);
    284     }
    285 
    286     //-----------------------------------------------------------------
    287     // private methods
    288     //----------------------------------
    289 
    290     private void getBassBoost(int session) {
    291          if (mBassBoost == null || session != mSession) {
    292              if (session != mSession && mBassBoost != null) {
    293                  mBassBoost.release();
    294                  mBassBoost = null;
    295              }
    296              try {
    297                 mBassBoost = new BassBoost(0, session);
    298                 mSession = session;
    299             } catch (IllegalArgumentException e) {
    300                 Log.e(TAG, "getBassBoost() BassBoost not found exception: "+e);
    301             } catch (UnsupportedOperationException e) {
    302                 Log.e(TAG, "getBassBoost() Effect library not loaded exception: "+e);
    303             }
    304          }
    305          assertNotNull("could not create mBassBoost", mBassBoost);
    306     }
    307 
    308     private void releaseBassBoost() {
    309         if (mBassBoost != null) {
    310             mBassBoost.release();
    311             mBassBoost = null;
    312         }
    313     }
    314 
    315     private void waitForLooperInitialization_l() {
    316         int looperWaitCount = MAX_LOOPER_WAIT_COUNT;
    317         while (!mInitialized && (looperWaitCount-- > 0)) {
    318             try {
    319                 mLock.wait();
    320             } catch(Exception e) {
    321             }
    322         }
    323         assertTrue(mInitialized);
    324     }
    325 
    326     // Initializes the bassboot listener looper
    327     class ListenerThread extends Thread {
    328         boolean mControl;
    329         boolean mEnable;
    330         boolean mParameter;
    331 
    332         public ListenerThread(boolean control, boolean enable, boolean parameter) {
    333             super();
    334             mControl = control;
    335             mEnable = enable;
    336             mParameter = parameter;
    337         }
    338 
    339         public void cleanUp() {
    340             if (mBassBoost2 != null) {
    341                 mBassBoost2.setControlStatusListener(null);
    342                 mBassBoost2.setEnableStatusListener(null);
    343                 mBassBoost2.setParameterListener(
    344                         (BassBoost.OnParameterChangeListener)null);
    345             }
    346         }
    347     }
    348 
    349     private void createListenerLooper(boolean control, boolean enable, boolean parameter) {
    350         mEffectListenerLooper = new ListenerThread(control, enable, parameter) {
    351             @Override
    352             public void run() {
    353                 // Set up a looper
    354                 Looper.prepare();
    355 
    356                 // Save the looper so that we can terminate this thread
    357                 // after we are done with it.
    358                 mLooper = Looper.myLooper();
    359 
    360                 mSession = getSessionId();
    361                 mBassBoost2 = new BassBoost(0, mSession);
    362                 assertNotNull("could not create bassboot2", mBassBoost2);
    363 
    364                 synchronized(mLock) {
    365                     if (mControl) {
    366                         mBassBoost2.setControlStatusListener(
    367                                 new AudioEffect.OnControlStatusChangeListener() {
    368                             public void onControlStatusChange(
    369                                     AudioEffect effect, boolean controlGranted) {
    370                                 synchronized(mLock) {
    371                                     if (effect == mBassBoost2) {
    372                                         mHasControl = controlGranted;
    373                                         mLock.notify();
    374                                     }
    375                                 }
    376                             }
    377                         });
    378                     }
    379                     if (mEnable) {
    380                         mBassBoost2.setEnableStatusListener(
    381                                 new AudioEffect.OnEnableStatusChangeListener() {
    382                             public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
    383                                 synchronized(mLock) {
    384                                     if (effect == mBassBoost2) {
    385                                         mIsEnabled = enabled;
    386                                         mLock.notify();
    387                                     }
    388                                 }
    389                             }
    390                         });
    391                     }
    392                     if (mParameter) {
    393                         mBassBoost2.setParameterListener(new BassBoost.OnParameterChangeListener() {
    394                             public void onParameterChange(BassBoost effect, int status,
    395                                     int param, short value)
    396                             {
    397                                 synchronized(mLock) {
    398                                     if (effect == mBassBoost2) {
    399                                         mChangedParameter = param;
    400                                         mLock.notify();
    401                                     }
    402                                 }
    403                             }
    404                         });
    405                     }
    406 
    407                     mInitialized = true;
    408                     mLock.notify();
    409                 }
    410                 Looper.loop();  // Blocks forever until Looper.quit() is called.
    411             }
    412         };
    413         mEffectListenerLooper.start();
    414     }
    415 
    416     // Terminates the listener looper thread.
    417     private void terminateListenerLooper() {
    418         if (mEffectListenerLooper != null) {
    419             mEffectListenerLooper.cleanUp();
    420             if (mLooper != null) {
    421                 mLooper.quit();
    422                 mLooper = null;
    423             }
    424             try {
    425                 mEffectListenerLooper.join();
    426             } catch(InterruptedException e) {
    427             }
    428             mEffectListenerLooper = null;
    429         }
    430 
    431         if (mBassBoost2 != null) {
    432             mBassBoost2.release();
    433             mBassBoost2 = null;
    434         }
    435     }
    436 }
    437