Home | History | Annotate | Download | only in audiofx
      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.audiofx;
     18 
     19 import android.annotation.SdkConstant;
     20 import android.annotation.SdkConstant.SdkConstantType;
     21 import android.app.ActivityThread;
     22 import android.os.Handler;
     23 import android.os.Looper;
     24 import android.os.Message;
     25 import android.util.Log;
     26 import java.lang.ref.WeakReference;
     27 import java.nio.ByteOrder;
     28 import java.nio.ByteBuffer;
     29 import java.util.UUID;
     30 
     31 /**
     32  * AudioEffect is the base class for controlling audio effects provided by the android audio
     33  * framework.
     34  * <p>Applications should not use the AudioEffect class directly but one of its derived classes to
     35  * control specific effects:
     36  * <ul>
     37  *   <li> {@link android.media.audiofx.Equalizer}</li>
     38  *   <li> {@link android.media.audiofx.Virtualizer}</li>
     39  *   <li> {@link android.media.audiofx.BassBoost}</li>
     40  *   <li> {@link android.media.audiofx.PresetReverb}</li>
     41  *   <li> {@link android.media.audiofx.EnvironmentalReverb}</li>
     42  * </ul>
     43  * <p>To apply the audio effect to a specific AudioTrack or MediaPlayer instance,
     44  * the application must specify the audio session ID of that instance when creating the AudioEffect.
     45  * (see {@link android.media.MediaPlayer#getAudioSessionId()} for details on audio sessions).
     46  * <p>NOTE: attaching insert effects (equalizer, bass boost, virtualizer) to the global audio output
     47  * mix by use of session 0 is deprecated.
     48  * <p>Creating an AudioEffect object will create the corresponding effect engine in the audio
     49  * framework if no instance of the same effect type exists in the specified audio session.
     50  * If one exists, this instance will be used.
     51  * <p>The application creating the AudioEffect object (or a derived class) will either receive
     52  * control of the effect engine or not depending on the priority parameter. If priority is higher
     53  * than the priority used by the current effect engine owner, the control will be transfered to the
     54  * new object. Otherwise control will remain with the previous object. In this case, the new
     55  * application will be notified of changes in effect engine state or control ownership by the
     56  * appropriate listener.
     57  */
     58 
     59 public class AudioEffect {
     60     static {
     61         System.loadLibrary("audioeffect_jni");
     62         native_init();
     63     }
     64 
     65     private final static String TAG = "AudioEffect-JAVA";
     66 
     67     // effect type UUIDs are taken from hardware/libhardware/include/hardware/audio_effect.h
     68 
     69     /**
     70      * The following UUIDs define effect types corresponding to standard audio
     71      * effects whose implementation and interface conform to the OpenSL ES
     72      * specification. The definitions match the corresponding interface IDs in
     73      * OpenSLES_IID.h
     74      */
     75     /**
     76      * UUID for environmental reverberation effect
     77      */
     78     public static final UUID EFFECT_TYPE_ENV_REVERB = UUID
     79             .fromString("c2e5d5f0-94bd-4763-9cac-4e234d06839e");
     80     /**
     81      * UUID for preset reverberation effect
     82      */
     83     public static final UUID EFFECT_TYPE_PRESET_REVERB = UUID
     84             .fromString("47382d60-ddd8-11db-bf3a-0002a5d5c51b");
     85     /**
     86      * UUID for equalizer effect
     87      */
     88     public static final UUID EFFECT_TYPE_EQUALIZER = UUID
     89             .fromString("0bed4300-ddd6-11db-8f34-0002a5d5c51b");
     90     /**
     91      * UUID for bass boost effect
     92      */
     93     public static final UUID EFFECT_TYPE_BASS_BOOST = UUID
     94             .fromString("0634f220-ddd4-11db-a0fc-0002a5d5c51b");
     95     /**
     96      * UUID for virtualizer effect
     97      */
     98     public static final UUID EFFECT_TYPE_VIRTUALIZER = UUID
     99             .fromString("37cc2c00-dddd-11db-8577-0002a5d5c51b");
    100 
    101     /**
    102      * UUIDs for effect types not covered by OpenSL ES.
    103      */
    104     /**
    105      * UUID for Automatic Gain Control (AGC)
    106      */
    107     public static final UUID EFFECT_TYPE_AGC = UUID
    108             .fromString("0a8abfe0-654c-11e0-ba26-0002a5d5c51b");
    109 
    110     /**
    111      * UUID for Acoustic Echo Canceler (AEC)
    112      */
    113     public static final UUID EFFECT_TYPE_AEC = UUID
    114             .fromString("7b491460-8d4d-11e0-bd61-0002a5d5c51b");
    115 
    116     /**
    117      * UUID for Noise Suppressor (NS)
    118      */
    119     public static final UUID EFFECT_TYPE_NS = UUID
    120             .fromString("58b4b260-8e06-11e0-aa8e-0002a5d5c51b");
    121 
    122     /**
    123      * UUID for Loudness Enhancer
    124      */
    125     public static final UUID EFFECT_TYPE_LOUDNESS_ENHANCER = UUID
    126               .fromString("fe3199be-aed0-413f-87bb-11260eb63cf1");
    127 
    128     /**
    129      * Null effect UUID. Used when the UUID for effect type of
    130      * @hide
    131      */
    132     public static final UUID EFFECT_TYPE_NULL = UUID
    133             .fromString("ec7178ec-e5e1-4432-a3f4-4657e6795210");
    134 
    135     /**
    136      * State of an AudioEffect object that was not successfully initialized upon
    137      * creation
    138      * @hide
    139      */
    140     public static final int STATE_UNINITIALIZED = 0;
    141     /**
    142      * State of an AudioEffect object that is ready to be used.
    143      * @hide
    144      */
    145     public static final int STATE_INITIALIZED = 1;
    146 
    147     // to keep in sync with
    148     // frameworks/base/include/media/AudioEffect.h
    149     /**
    150      * Event id for engine control ownership change notification.
    151      * @hide
    152      */
    153     public static final int NATIVE_EVENT_CONTROL_STATUS = 0;
    154     /**
    155      * Event id for engine state change notification.
    156      * @hide
    157      */
    158     public static final int NATIVE_EVENT_ENABLED_STATUS = 1;
    159     /**
    160      * Event id for engine parameter change notification.
    161      * @hide
    162      */
    163     public static final int NATIVE_EVENT_PARAMETER_CHANGED = 2;
    164 
    165     /**
    166      * Successful operation.
    167      */
    168     public static final int SUCCESS = 0;
    169     /**
    170      * Unspecified error.
    171      */
    172     public static final int ERROR = -1;
    173     /**
    174      * Internal operation status. Not returned by any method.
    175      */
    176     public static final int ALREADY_EXISTS = -2;
    177     /**
    178      * Operation failed due to bad object initialization.
    179      */
    180     public static final int ERROR_NO_INIT = -3;
    181     /**
    182      * Operation failed due to bad parameter value.
    183      */
    184     public static final int ERROR_BAD_VALUE = -4;
    185     /**
    186      * Operation failed because it was requested in wrong state.
    187      */
    188     public static final int ERROR_INVALID_OPERATION = -5;
    189     /**
    190      * Operation failed due to lack of memory.
    191      */
    192     public static final int ERROR_NO_MEMORY = -6;
    193     /**
    194      * Operation failed due to dead remote object.
    195      */
    196     public static final int ERROR_DEAD_OBJECT = -7;
    197 
    198     /**
    199      * The effect descriptor contains information on a particular effect implemented in the
    200      * audio framework:<br>
    201      * <ul>
    202      *  <li>type: UUID identifying the effect type. May be one of:
    203      * {@link AudioEffect#EFFECT_TYPE_AEC}, {@link AudioEffect#EFFECT_TYPE_AGC},
    204      * {@link AudioEffect#EFFECT_TYPE_BASS_BOOST}, {@link AudioEffect#EFFECT_TYPE_ENV_REVERB},
    205      * {@link AudioEffect#EFFECT_TYPE_EQUALIZER}, {@link AudioEffect#EFFECT_TYPE_NS},
    206      * {@link AudioEffect#EFFECT_TYPE_PRESET_REVERB}, {@link AudioEffect#EFFECT_TYPE_VIRTUALIZER}.
    207      *  </li>
    208      *  <li>uuid: UUID for this particular implementation</li>
    209      *  <li>connectMode: {@link #EFFECT_INSERT} or {@link #EFFECT_AUXILIARY}</li>
    210      *  <li>name: human readable effect name</li>
    211      *  <li>implementor: human readable effect implementor name</li>
    212      * </ul>
    213      * The method {@link #queryEffects()} returns an array of Descriptors to facilitate effects
    214      * enumeration.
    215      */
    216     public static class Descriptor {
    217 
    218         public Descriptor() {
    219         }
    220 
    221         /**
    222          * @param type          UUID identifying the effect type. May be one of:
    223          * {@link AudioEffect#EFFECT_TYPE_AEC}, {@link AudioEffect#EFFECT_TYPE_AGC},
    224          * {@link AudioEffect#EFFECT_TYPE_BASS_BOOST}, {@link AudioEffect#EFFECT_TYPE_ENV_REVERB},
    225          * {@link AudioEffect#EFFECT_TYPE_EQUALIZER}, {@link AudioEffect#EFFECT_TYPE_NS},
    226          * {@link AudioEffect#EFFECT_TYPE_PRESET_REVERB},
    227          * {@link AudioEffect#EFFECT_TYPE_VIRTUALIZER}.
    228          * @param uuid         UUID for this particular implementation
    229          * @param connectMode  {@link #EFFECT_INSERT} or {@link #EFFECT_AUXILIARY}
    230          * @param name         human readable effect name
    231          * @param implementor  human readable effect implementor name
    232         *
    233         */
    234         public Descriptor(String type, String uuid, String connectMode,
    235                 String name, String implementor) {
    236             this.type = UUID.fromString(type);
    237             this.uuid = UUID.fromString(uuid);
    238             this.connectMode = connectMode;
    239             this.name = name;
    240             this.implementor = implementor;
    241         }
    242 
    243         /**
    244          *  Indicates the generic type of the effect (Equalizer, Bass boost ...).
    245          *  One of {@link AudioEffect#EFFECT_TYPE_AEC},
    246          *  {@link AudioEffect#EFFECT_TYPE_AGC}, {@link AudioEffect#EFFECT_TYPE_BASS_BOOST},
    247          *  {@link AudioEffect#EFFECT_TYPE_ENV_REVERB}, {@link AudioEffect#EFFECT_TYPE_EQUALIZER},
    248          *  {@link AudioEffect#EFFECT_TYPE_NS}, {@link AudioEffect#EFFECT_TYPE_PRESET_REVERB}
    249          *   or {@link AudioEffect#EFFECT_TYPE_VIRTUALIZER}.<br>
    250          *  For reverberation, bass boost, EQ and virtualizer, the UUID
    251          *  corresponds to the OpenSL ES Interface ID.
    252          */
    253         public UUID type;
    254         /**
    255          *  Indicates the particular implementation of the effect in that type. Several effects
    256          *  can have the same type but this uuid is unique to a given implementation.
    257          */
    258         public UUID uuid;
    259         /**
    260          *  Indicates if the effect is of insert category {@link #EFFECT_INSERT} or auxiliary
    261          *  category {@link #EFFECT_AUXILIARY}.
    262          *  Insert effects (typically an {@link Equalizer}) are applied
    263          *  to the entire audio source and usually not shared by several sources. Auxiliary effects
    264          *  (typically a reverberator) are applied to part of the signal (wet) and the effect output
    265          *  is added to the original signal (dry).
    266          *  Audio pre processing are applied to audio captured on a particular
    267          * {@link android.media.AudioRecord}.
    268          */
    269         public String connectMode;
    270         /**
    271          * Human readable effect name
    272          */
    273         public String name;
    274         /**
    275          * Human readable effect implementor name
    276          */
    277         public String implementor;
    278     };
    279 
    280     /**
    281      * Effect connection mode is insert. Specifying an audio session ID when creating the effect
    282      * will insert this effect after all players in the same audio session.
    283      */
    284     public static final String EFFECT_INSERT = "Insert";
    285     /**
    286      * Effect connection mode is auxiliary.
    287      * <p>Auxiliary effects must be created on session 0 (global output mix). In order for a
    288      * MediaPlayer or AudioTrack to be fed into this effect, they must be explicitely attached to
    289      * this effect and a send level must be specified.
    290      * <p>Use the effect ID returned by {@link #getId()} to designate this particular effect when
    291      * attaching it to the MediaPlayer or AudioTrack.
    292      */
    293     public static final String EFFECT_AUXILIARY = "Auxiliary";
    294     /**
    295      * Effect connection mode is pre processing.
    296      * The audio pre processing effects are attached to an audio input (AudioRecord).
    297      * @hide
    298      */
    299     public static final String EFFECT_PRE_PROCESSING = "Pre Processing";
    300 
    301     // --------------------------------------------------------------------------
    302     // Member variables
    303     // --------------------
    304     /**
    305      * Indicates the state of the AudioEffect instance
    306      */
    307     private int mState = STATE_UNINITIALIZED;
    308     /**
    309      * Lock to synchronize access to mState
    310      */
    311     private final Object mStateLock = new Object();
    312     /**
    313      * System wide unique effect ID
    314      */
    315     private int mId;
    316 
    317     // accessed by native methods
    318     private long mNativeAudioEffect;
    319     private long mJniData;
    320 
    321     /**
    322      * Effect descriptor
    323      */
    324     private Descriptor mDescriptor;
    325 
    326     /**
    327      * Listener for effect engine state change notifications.
    328      *
    329      * @see #setEnableStatusListener(OnEnableStatusChangeListener)
    330      */
    331     private OnEnableStatusChangeListener mEnableStatusChangeListener = null;
    332     /**
    333      * Listener for effect engine control ownership change notifications.
    334      *
    335      * @see #setControlStatusListener(OnControlStatusChangeListener)
    336      */
    337     private OnControlStatusChangeListener mControlChangeStatusListener = null;
    338     /**
    339      * Listener for effect engine control ownership change notifications.
    340      *
    341      * @see #setParameterListener(OnParameterChangeListener)
    342      */
    343     private OnParameterChangeListener mParameterChangeListener = null;
    344     /**
    345      * Lock to protect listeners updates against event notifications
    346      * @hide
    347      */
    348     public final Object mListenerLock = new Object();
    349     /**
    350      * Handler for events coming from the native code
    351      * @hide
    352      */
    353     public NativeEventHandler mNativeEventHandler = null;
    354 
    355     // --------------------------------------------------------------------------
    356     // Constructor, Finalize
    357     // --------------------
    358     /**
    359      * Class constructor.
    360      *
    361      * @param type type of effect engine created. See {@link #EFFECT_TYPE_ENV_REVERB},
    362      *            {@link #EFFECT_TYPE_EQUALIZER} ... Types corresponding to
    363      *            built-in effects are defined by AudioEffect class. Other types
    364      *            can be specified provided they correspond an existing OpenSL
    365      *            ES interface ID and the corresponsing effect is available on
    366      *            the platform. If an unspecified effect type is requested, the
    367      *            constructor with throw the IllegalArgumentException. This
    368      *            parameter can be set to {@link #EFFECT_TYPE_NULL} in which
    369      *            case only the uuid will be used to select the effect.
    370      * @param uuid unique identifier of a particular effect implementation.
    371      *            Must be specified if the caller wants to use a particular
    372      *            implementation of an effect type. This parameter can be set to
    373      *            {@link #EFFECT_TYPE_NULL} in which case only the type will
    374      *            be used to select the effect.
    375      * @param priority the priority level requested by the application for
    376      *            controlling the effect engine. As the same effect engine can
    377      *            be shared by several applications, this parameter indicates
    378      *            how much the requesting application needs control of effect
    379      *            parameters. The normal priority is 0, above normal is a
    380      *            positive number, below normal a negative number.
    381      * @param audioSession system wide unique audio session identifier.
    382      *            The effect will be attached to the MediaPlayer or AudioTrack in
    383      *            the same audio session.
    384      *
    385      * @throws java.lang.IllegalArgumentException
    386      * @throws java.lang.UnsupportedOperationException
    387      * @throws java.lang.RuntimeException
    388      * @hide
    389      */
    390 
    391     public AudioEffect(UUID type, UUID uuid, int priority, int audioSession)
    392             throws IllegalArgumentException, UnsupportedOperationException,
    393             RuntimeException {
    394         int[] id = new int[1];
    395         Descriptor[] desc = new Descriptor[1];
    396         // native initialization
    397         int initResult = native_setup(new WeakReference<AudioEffect>(this),
    398                 type.toString(), uuid.toString(), priority, audioSession, id,
    399                 desc, ActivityThread.currentOpPackageName());
    400         if (initResult != SUCCESS && initResult != ALREADY_EXISTS) {
    401             Log.e(TAG, "Error code " + initResult
    402                     + " when initializing AudioEffect.");
    403             switch (initResult) {
    404             case ERROR_BAD_VALUE:
    405                 throw (new IllegalArgumentException("Effect type: " + type
    406                         + " not supported."));
    407             case ERROR_INVALID_OPERATION:
    408                 throw (new UnsupportedOperationException(
    409                         "Effect library not loaded"));
    410             default:
    411                 throw (new RuntimeException(
    412                         "Cannot initialize effect engine for type: " + type
    413                                 + " Error: " + initResult));
    414             }
    415         }
    416         mId = id[0];
    417         mDescriptor = desc[0];
    418         synchronized (mStateLock) {
    419             mState = STATE_INITIALIZED;
    420         }
    421     }
    422 
    423     /**
    424      * Releases the native AudioEffect resources. It is a good practice to
    425      * release the effect engine when not in use as control can be returned to
    426      * other applications or the native resources released.
    427      */
    428     public void release() {
    429         synchronized (mStateLock) {
    430             native_release();
    431             mState = STATE_UNINITIALIZED;
    432         }
    433     }
    434 
    435     @Override
    436     protected void finalize() {
    437         native_finalize();
    438     }
    439 
    440     /**
    441      * Get the effect descriptor.
    442      *
    443      * @see android.media.audiofx.AudioEffect.Descriptor
    444      * @throws IllegalStateException
    445      */
    446     public Descriptor getDescriptor() throws IllegalStateException {
    447         checkState("getDescriptor()");
    448         return mDescriptor;
    449     }
    450 
    451     // --------------------------------------------------------------------------
    452     // Effects Enumeration
    453     // --------------------
    454 
    455     /**
    456      * Query all effects available on the platform. Returns an array of
    457      * {@link android.media.audiofx.AudioEffect.Descriptor} objects
    458      *
    459      * @throws IllegalStateException
    460      */
    461 
    462     static public Descriptor[] queryEffects() {
    463         return (Descriptor[]) native_query_effects();
    464     }
    465 
    466     /**
    467      * Query all audio pre-processing effects applied to the AudioRecord with the supplied
    468      * audio session ID. Returns an array of {@link android.media.audiofx.AudioEffect.Descriptor}
    469      * objects.
    470      * @param audioSession system wide unique audio session identifier.
    471      * @throws IllegalStateException
    472      * @hide
    473      */
    474 
    475     static public Descriptor[] queryPreProcessings(int audioSession) {
    476         return (Descriptor[]) native_query_pre_processing(audioSession);
    477     }
    478 
    479     /**
    480      * Checks if the device implements the specified effect type.
    481      * @param type the requested effect type.
    482      * @return true if the device implements the specified effect type, false otherwise.
    483      * @hide
    484      */
    485     public static boolean isEffectTypeAvailable(UUID type) {
    486         AudioEffect.Descriptor[] desc = AudioEffect.queryEffects();
    487         if (desc == null) {
    488             return false;
    489         }
    490 
    491         for (int i = 0; i < desc.length; i++) {
    492             if (desc[i].type.equals(type)) {
    493                 return true;
    494             }
    495         }
    496         return false;
    497     }
    498 
    499     // --------------------------------------------------------------------------
    500     // Control methods
    501     // --------------------
    502 
    503     /**
    504      * Enable or disable the effect.
    505      * Creating an audio effect does not automatically apply this effect on the audio source. It
    506      * creates the resources necessary to process this effect but the audio signal is still bypassed
    507      * through the effect engine. Calling this method will make that the effect is actually applied
    508      * or not to the audio content being played in the corresponding audio session.
    509      *
    510      * @param enabled the requested enable state
    511      * @return {@link #SUCCESS} in case of success, {@link #ERROR_INVALID_OPERATION}
    512      *         or {@link #ERROR_DEAD_OBJECT} in case of failure.
    513      * @throws IllegalStateException
    514      */
    515     public int setEnabled(boolean enabled) throws IllegalStateException {
    516         checkState("setEnabled()");
    517         return native_setEnabled(enabled);
    518     }
    519 
    520     /**
    521      * Set effect parameter. The setParameter method is provided in several
    522      * forms addressing most common parameter formats. This form is the most
    523      * generic one where the parameter and its value are both specified as an
    524      * array of bytes. The parameter and value type and length are therefore
    525      * totally free. For standard effect defined by OpenSL ES, the parameter
    526      * format and values must match the definitions in the corresponding OpenSL
    527      * ES interface.
    528      *
    529      * @param param the identifier of the parameter to set
    530      * @param value the new value for the specified parameter
    531      * @return {@link #SUCCESS} in case of success, {@link #ERROR_BAD_VALUE},
    532      *         {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION} or
    533      *         {@link #ERROR_DEAD_OBJECT} in case of failure
    534      * @throws IllegalStateException
    535      * @hide
    536      */
    537     public int setParameter(byte[] param, byte[] value)
    538             throws IllegalStateException {
    539         checkState("setParameter()");
    540         return native_setParameter(param.length, param, value.length, value);
    541     }
    542 
    543     /**
    544      * Set effect parameter. The parameter and its value are integers.
    545      *
    546      * @see #setParameter(byte[], byte[])
    547      * @hide
    548      */
    549     public int setParameter(int param, int value) throws IllegalStateException {
    550         byte[] p = intToByteArray(param);
    551         byte[] v = intToByteArray(value);
    552         return setParameter(p, v);
    553     }
    554 
    555     /**
    556      * Set effect parameter. The parameter is an integer and the value is a
    557      * short integer.
    558      *
    559      * @see #setParameter(byte[], byte[])
    560      * @hide
    561      */
    562     public int setParameter(int param, short value)
    563             throws IllegalStateException {
    564         byte[] p = intToByteArray(param);
    565         byte[] v = shortToByteArray(value);
    566         return setParameter(p, v);
    567     }
    568 
    569     /**
    570      * Set effect parameter. The parameter is an integer and the value is an
    571      * array of bytes.
    572      *
    573      * @see #setParameter(byte[], byte[])
    574      * @hide
    575      */
    576     public int setParameter(int param, byte[] value)
    577             throws IllegalStateException {
    578         byte[] p = intToByteArray(param);
    579         return setParameter(p, value);
    580     }
    581 
    582     /**
    583      * Set effect parameter. The parameter is an array of 1 or 2 integers and
    584      * the value is also an array of 1 or 2 integers
    585      *
    586      * @see #setParameter(byte[], byte[])
    587      * @hide
    588      */
    589     public int setParameter(int[] param, int[] value)
    590             throws IllegalStateException {
    591         if (param.length > 2 || value.length > 2) {
    592             return ERROR_BAD_VALUE;
    593         }
    594         byte[] p = intToByteArray(param[0]);
    595         if (param.length > 1) {
    596             byte[] p2 = intToByteArray(param[1]);
    597             p = concatArrays(p, p2);
    598         }
    599         byte[] v = intToByteArray(value[0]);
    600         if (value.length > 1) {
    601             byte[] v2 = intToByteArray(value[1]);
    602             v = concatArrays(v, v2);
    603         }
    604         return setParameter(p, v);
    605     }
    606 
    607     /**
    608      * Set effect parameter. The parameter is an array of 1 or 2 integers and
    609      * the value is an array of 1 or 2 short integers
    610      *
    611      * @see #setParameter(byte[], byte[])
    612      * @hide
    613      */
    614     public int setParameter(int[] param, short[] value)
    615             throws IllegalStateException {
    616         if (param.length > 2 || value.length > 2) {
    617             return ERROR_BAD_VALUE;
    618         }
    619         byte[] p = intToByteArray(param[0]);
    620         if (param.length > 1) {
    621             byte[] p2 = intToByteArray(param[1]);
    622             p = concatArrays(p, p2);
    623         }
    624 
    625         byte[] v = shortToByteArray(value[0]);
    626         if (value.length > 1) {
    627             byte[] v2 = shortToByteArray(value[1]);
    628             v = concatArrays(v, v2);
    629         }
    630         return setParameter(p, v);
    631     }
    632 
    633     /**
    634      * Set effect parameter. The parameter is an array of 1 or 2 integers and
    635      * the value is an array of bytes
    636      *
    637      * @see #setParameter(byte[], byte[])
    638      * @hide
    639      */
    640     public int setParameter(int[] param, byte[] value)
    641             throws IllegalStateException {
    642         if (param.length > 2) {
    643             return ERROR_BAD_VALUE;
    644         }
    645         byte[] p = intToByteArray(param[0]);
    646         if (param.length > 1) {
    647             byte[] p2 = intToByteArray(param[1]);
    648             p = concatArrays(p, p2);
    649         }
    650         return setParameter(p, value);
    651     }
    652 
    653     /**
    654      * Get effect parameter. The getParameter method is provided in several
    655      * forms addressing most common parameter formats. This form is the most
    656      * generic one where the parameter and its value are both specified as an
    657      * array of bytes. The parameter and value type and length are therefore
    658      * totally free.
    659      *
    660      * @param param the identifier of the parameter to set
    661      * @param value the new value for the specified parameter
    662      * @return the number of meaningful bytes in value array in case of success or
    663      *  {@link #ERROR_BAD_VALUE}, {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION}
    664      *  or {@link #ERROR_DEAD_OBJECT} in case of failure.
    665      * @throws IllegalStateException
    666      * @hide
    667      */
    668     public int getParameter(byte[] param, byte[] value)
    669             throws IllegalStateException {
    670         checkState("getParameter()");
    671         return native_getParameter(param.length, param, value.length, value);
    672     }
    673 
    674     /**
    675      * Get effect parameter. The parameter is an integer and the value is an
    676      * array of bytes.
    677      *
    678      * @see #getParameter(byte[], byte[])
    679      * @hide
    680      */
    681     public int getParameter(int param, byte[] value)
    682             throws IllegalStateException {
    683         byte[] p = intToByteArray(param);
    684 
    685         return getParameter(p, value);
    686     }
    687 
    688     /**
    689      * Get effect parameter. The parameter is an integer and the value is an
    690      * array of 1 or 2 integers
    691      *
    692      * @see #getParameter(byte[], byte[])
    693      * In case of success, returns the number of meaningful integers in value array.
    694      * @hide
    695      */
    696     public int getParameter(int param, int[] value)
    697             throws IllegalStateException {
    698         if (value.length > 2) {
    699             return ERROR_BAD_VALUE;
    700         }
    701         byte[] p = intToByteArray(param);
    702 
    703         byte[] v = new byte[value.length * 4];
    704 
    705         int status = getParameter(p, v);
    706 
    707         if (status == 4 || status == 8) {
    708             value[0] = byteArrayToInt(v);
    709             if (status == 8) {
    710                 value[1] = byteArrayToInt(v, 4);
    711             }
    712             status /= 4;
    713         } else {
    714             status = ERROR;
    715         }
    716         return status;
    717     }
    718 
    719     /**
    720      * Get effect parameter. The parameter is an integer and the value is an
    721      * array of 1 or 2 short integers
    722      *
    723      * @see #getParameter(byte[], byte[])
    724      * In case of success, returns the number of meaningful short integers in value array.
    725      * @hide
    726      */
    727     public int getParameter(int param, short[] value)
    728             throws IllegalStateException {
    729         if (value.length > 2) {
    730             return ERROR_BAD_VALUE;
    731         }
    732         byte[] p = intToByteArray(param);
    733 
    734         byte[] v = new byte[value.length * 2];
    735 
    736         int status = getParameter(p, v);
    737 
    738         if (status == 2 || status == 4) {
    739             value[0] = byteArrayToShort(v);
    740             if (status == 4) {
    741                 value[1] = byteArrayToShort(v, 2);
    742             }
    743             status /= 2;
    744         } else {
    745             status = ERROR;
    746         }
    747         return status;
    748     }
    749 
    750     /**
    751      * Get effect parameter. The parameter is an array of 1 or 2 integers and
    752      * the value is also an array of 1 or 2 integers
    753      *
    754      * @see #getParameter(byte[], byte[])
    755      * In case of success, the returns the number of meaningful integers in value array.
    756      * @hide
    757      */
    758     public int getParameter(int[] param, int[] value)
    759             throws IllegalStateException {
    760         if (param.length > 2 || value.length > 2) {
    761             return ERROR_BAD_VALUE;
    762         }
    763         byte[] p = intToByteArray(param[0]);
    764         if (param.length > 1) {
    765             byte[] p2 = intToByteArray(param[1]);
    766             p = concatArrays(p, p2);
    767         }
    768         byte[] v = new byte[value.length * 4];
    769 
    770         int status = getParameter(p, v);
    771 
    772         if (status == 4 || status == 8) {
    773             value[0] = byteArrayToInt(v);
    774             if (status == 8) {
    775                 value[1] = byteArrayToInt(v, 4);
    776             }
    777             status /= 4;
    778         } else {
    779             status = ERROR;
    780         }
    781         return status;
    782     }
    783 
    784     /**
    785      * Get effect parameter. The parameter is an array of 1 or 2 integers and
    786      * the value is an array of 1 or 2 short integers
    787      *
    788      * @see #getParameter(byte[], byte[])
    789      * In case of success, returns the number of meaningful short integers in value array.
    790      * @hide
    791      */
    792     public int getParameter(int[] param, short[] value)
    793             throws IllegalStateException {
    794         if (param.length > 2 || value.length > 2) {
    795             return ERROR_BAD_VALUE;
    796         }
    797         byte[] p = intToByteArray(param[0]);
    798         if (param.length > 1) {
    799             byte[] p2 = intToByteArray(param[1]);
    800             p = concatArrays(p, p2);
    801         }
    802         byte[] v = new byte[value.length * 2];
    803 
    804         int status = getParameter(p, v);
    805 
    806         if (status == 2 || status == 4) {
    807             value[0] = byteArrayToShort(v);
    808             if (status == 4) {
    809                 value[1] = byteArrayToShort(v, 2);
    810             }
    811             status /= 2;
    812         } else {
    813             status = ERROR;
    814         }
    815         return status;
    816     }
    817 
    818     /**
    819      * Get effect parameter. The parameter is an array of 1 or 2 integers and
    820      * the value is an array of bytes
    821      *
    822      * @see #getParameter(byte[], byte[])
    823      * @hide
    824      */
    825     public int getParameter(int[] param, byte[] value)
    826             throws IllegalStateException {
    827         if (param.length > 2) {
    828             return ERROR_BAD_VALUE;
    829         }
    830         byte[] p = intToByteArray(param[0]);
    831         if (param.length > 1) {
    832             byte[] p2 = intToByteArray(param[1]);
    833             p = concatArrays(p, p2);
    834         }
    835 
    836         return getParameter(p, value);
    837     }
    838 
    839     /**
    840      * Send a command to the effect engine. This method is intended to send
    841      * proprietary commands to a particular effect implementation.
    842      * In case of success, returns the number of meaningful bytes in reply array.
    843      * In case of failure, the returned value is negative and implementation specific.
    844      * @hide
    845      */
    846     public int command(int cmdCode, byte[] command, byte[] reply)
    847             throws IllegalStateException {
    848         checkState("command()");
    849         return native_command(cmdCode, command.length, command, reply.length, reply);
    850     }
    851 
    852     // --------------------------------------------------------------------------
    853     // Getters
    854     // --------------------
    855 
    856     /**
    857      * Returns effect unique identifier. This system wide unique identifier can
    858      * be used to attach this effect to a MediaPlayer or an AudioTrack when the
    859      * effect is an auxiliary effect (Reverb)
    860      *
    861      * @return the effect identifier.
    862      * @throws IllegalStateException
    863      */
    864     public int getId() throws IllegalStateException {
    865         checkState("getId()");
    866         return mId;
    867     }
    868 
    869     /**
    870      * Returns effect enabled state
    871      *
    872      * @return true if the effect is enabled, false otherwise.
    873      * @throws IllegalStateException
    874      */
    875     public boolean getEnabled() throws IllegalStateException {
    876         checkState("getEnabled()");
    877         return native_getEnabled();
    878     }
    879 
    880     /**
    881      * Checks if this AudioEffect object is controlling the effect engine.
    882      *
    883      * @return true if this instance has control of effect engine, false
    884      *         otherwise.
    885      * @throws IllegalStateException
    886      */
    887     public boolean hasControl() throws IllegalStateException {
    888         checkState("hasControl()");
    889         return native_hasControl();
    890     }
    891 
    892     // --------------------------------------------------------------------------
    893     // Initialization / configuration
    894     // --------------------
    895     /**
    896      * Sets the listener AudioEffect notifies when the effect engine is enabled
    897      * or disabled.
    898      *
    899      * @param listener
    900      */
    901     public void setEnableStatusListener(OnEnableStatusChangeListener listener) {
    902         synchronized (mListenerLock) {
    903             mEnableStatusChangeListener = listener;
    904         }
    905         if ((listener != null) && (mNativeEventHandler == null)) {
    906             createNativeEventHandler();
    907         }
    908     }
    909 
    910     /**
    911      * Sets the listener AudioEffect notifies when the effect engine control is
    912      * taken or returned.
    913      *
    914      * @param listener
    915      */
    916     public void setControlStatusListener(OnControlStatusChangeListener listener) {
    917         synchronized (mListenerLock) {
    918             mControlChangeStatusListener = listener;
    919         }
    920         if ((listener != null) && (mNativeEventHandler == null)) {
    921             createNativeEventHandler();
    922         }
    923     }
    924 
    925     /**
    926      * Sets the listener AudioEffect notifies when a parameter is changed.
    927      *
    928      * @param listener
    929      * @hide
    930      */
    931     public void setParameterListener(OnParameterChangeListener listener) {
    932         synchronized (mListenerLock) {
    933             mParameterChangeListener = listener;
    934         }
    935         if ((listener != null) && (mNativeEventHandler == null)) {
    936             createNativeEventHandler();
    937         }
    938     }
    939 
    940     // Convenience method for the creation of the native event handler
    941     // It is called only when a non-null event listener is set.
    942     // precondition:
    943     // mNativeEventHandler is null
    944     private void createNativeEventHandler() {
    945         Looper looper;
    946         if ((looper = Looper.myLooper()) != null) {
    947             mNativeEventHandler = new NativeEventHandler(this, looper);
    948         } else if ((looper = Looper.getMainLooper()) != null) {
    949             mNativeEventHandler = new NativeEventHandler(this, looper);
    950         } else {
    951             mNativeEventHandler = null;
    952         }
    953     }
    954 
    955     // ---------------------------------------------------------
    956     // Interface definitions
    957     // --------------------
    958     /**
    959      * The OnEnableStatusChangeListener interface defines a method called by the AudioEffect
    960      * when a the enabled state of the effect engine was changed by the controlling application.
    961      */
    962     public interface OnEnableStatusChangeListener {
    963         /**
    964          * Called on the listener to notify it that the effect engine has been
    965          * enabled or disabled.
    966          * @param effect the effect on which the interface is registered.
    967          * @param enabled new effect state.
    968          */
    969         void onEnableStatusChange(AudioEffect effect, boolean enabled);
    970     }
    971 
    972     /**
    973      * The OnControlStatusChangeListener interface defines a method called by the AudioEffect
    974      * when a the control of the effect engine is gained or lost by the application
    975      */
    976     public interface OnControlStatusChangeListener {
    977         /**
    978          * Called on the listener to notify it that the effect engine control
    979          * has been taken or returned.
    980          * @param effect the effect on which the interface is registered.
    981          * @param controlGranted true if the application has been granted control of the effect
    982          * engine, false otherwise.
    983          */
    984         void onControlStatusChange(AudioEffect effect, boolean controlGranted);
    985     }
    986 
    987     /**
    988      * The OnParameterChangeListener interface defines a method called by the AudioEffect
    989      * when a parameter is changed in the effect engine by the controlling application.
    990      * @hide
    991      */
    992     public interface OnParameterChangeListener {
    993         /**
    994          * Called on the listener to notify it that a parameter value has changed.
    995          * @param effect the effect on which the interface is registered.
    996          * @param status status of the set parameter operation.
    997          * @param param ID of the modified parameter.
    998          * @param value the new parameter value.
    999          */
   1000         void onParameterChange(AudioEffect effect, int status, byte[] param,
   1001                 byte[] value);
   1002     }
   1003 
   1004 
   1005     // -------------------------------------------------------------------------
   1006     // Audio Effect Control panel intents
   1007     // -------------------------------------------------------------------------
   1008 
   1009     /**
   1010      *  Intent to launch an audio effect control panel UI.
   1011      *  <p>The goal of this intent is to enable separate implementations of music/media player
   1012      *  applications and audio effect control application or services.
   1013      *  This will allow platform vendors to offer more advanced control options for standard effects
   1014      *  or control for platform specific effects.
   1015      *  <p>The intent carries a number of extras used by the player application to communicate
   1016      *  necessary pieces of information to the control panel application.
   1017      *  <p>The calling application must use the
   1018      *  {@link android.app.Activity#startActivityForResult(Intent, int)} method to launch the
   1019      *  control panel so that its package name is indicated and used by the control panel
   1020      *  application to keep track of changes for this particular application.
   1021      *  <p>The {@link #EXTRA_AUDIO_SESSION} extra will indicate an audio session to which the
   1022      *  audio effects should be applied. If no audio session is specified, either one of the
   1023      *  follownig will happen:
   1024      *  <p>- If an audio session was previously opened by the calling application with
   1025      *  {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} intent, the effect changes will
   1026      *  be applied to that session.
   1027      *  <p>- If no audio session is opened, the changes will be stored in the package specific
   1028      *  storage area and applied whenever a new audio session is opened by this application.
   1029      *  <p>The {@link #EXTRA_CONTENT_TYPE} extra will help the control panel application
   1030      *  customize both the UI layout and the default audio effect settings if none are already
   1031      *  stored for the calling application.
   1032      */
   1033     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
   1034     public static final String ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL =
   1035         "android.media.action.DISPLAY_AUDIO_EFFECT_CONTROL_PANEL";
   1036 
   1037     /**
   1038      *  Intent to signal to the effect control application or service that a new audio session
   1039      *  is opened and requires audio effects to be applied.
   1040      *  <p>This is different from {@link #ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL} in that no
   1041      *  UI should be displayed in this case. Music player applications can broadcast this intent
   1042      *  before starting playback to make sure that any audio effect settings previously selected
   1043      *  by the user are applied.
   1044      *  <p>The effect control application receiving this intent will look for previously stored
   1045      *  settings for the calling application, create all required audio effects and apply the
   1046      *  effect settings to the specified audio session.
   1047      *  <p>The calling package name is indicated by the {@link #EXTRA_PACKAGE_NAME} extra and the
   1048      *  audio session ID by the {@link #EXTRA_AUDIO_SESSION} extra. Both extras are mandatory.
   1049      *  <p>If no stored settings are found for the calling application, default settings for the
   1050      *  content type indicated by {@link #EXTRA_CONTENT_TYPE} will be applied. The default settings
   1051      *  for a given content type are platform specific.
   1052      */
   1053     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
   1054     public static final String ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION =
   1055         "android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION";
   1056 
   1057     /**
   1058      *  Intent to signal to the effect control application or service that an audio session
   1059      *  is closed and that effects should not be applied anymore.
   1060      *  <p>The effect control application receiving this intent will delete all effects on
   1061      *  this session and store current settings in package specific storage.
   1062      *  <p>The calling package name is indicated by the {@link #EXTRA_PACKAGE_NAME} extra and the
   1063      *  audio session ID by the {@link #EXTRA_AUDIO_SESSION} extra. Both extras are mandatory.
   1064      *  <p>It is good practice for applications to broadcast this intent when music playback stops
   1065      *  and/or when exiting to free system resources consumed by audio effect engines.
   1066      */
   1067     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
   1068     public static final String ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION =
   1069         "android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION";
   1070 
   1071     /**
   1072      * Contains the ID of the audio session the effects should be applied to.
   1073      * <p>This extra is for use with {@link #ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL},
   1074      * {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} and
   1075      * {@link #ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION} intents.
   1076      * <p>The extra value is of type int and is the audio session ID.
   1077      *  @see android.media.MediaPlayer#getAudioSessionId() for details on audio sessions.
   1078      */
   1079      public static final String EXTRA_AUDIO_SESSION = "android.media.extra.AUDIO_SESSION";
   1080 
   1081     /**
   1082      * Contains the package name of the calling application.
   1083      * <p>This extra is for use with {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} and
   1084      * {@link #ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION} intents.
   1085      * <p>The extra value is a string containing the full package name.
   1086      */
   1087     public static final String EXTRA_PACKAGE_NAME = "android.media.extra.PACKAGE_NAME";
   1088 
   1089     /**
   1090      * Indicates which type of content is played by the application.
   1091      * <p>This extra is for use with {@link #ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL} and
   1092      * {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} intents.
   1093      * <p>This information is used by the effect control application to customize UI and select
   1094      * appropriate default effect settings. The content type is one of the following:
   1095      * <ul>
   1096      *   <li>{@link #CONTENT_TYPE_MUSIC}</li>
   1097      *   <li>{@link #CONTENT_TYPE_MOVIE}</li>
   1098      *   <li>{@link #CONTENT_TYPE_GAME}</li>
   1099      *   <li>{@link #CONTENT_TYPE_VOICE}</li>
   1100      * </ul>
   1101      * If omitted, the content type defaults to {@link #CONTENT_TYPE_MUSIC}.
   1102      */
   1103     public static final String EXTRA_CONTENT_TYPE = "android.media.extra.CONTENT_TYPE";
   1104 
   1105     /**
   1106      * Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is music
   1107      */
   1108     public static final int  CONTENT_TYPE_MUSIC = 0;
   1109     /**
   1110      * Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is video or movie
   1111      */
   1112     public static final int  CONTENT_TYPE_MOVIE = 1;
   1113     /**
   1114      * Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is game audio
   1115      */
   1116     public static final int  CONTENT_TYPE_GAME = 2;
   1117     /**
   1118      * Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is voice audio
   1119      */
   1120     public static final int  CONTENT_TYPE_VOICE = 3;
   1121 
   1122 
   1123     // ---------------------------------------------------------
   1124     // Inner classes
   1125     // --------------------
   1126     /**
   1127      * Helper class to handle the forwarding of native events to the appropriate
   1128      * listeners
   1129      */
   1130     private class NativeEventHandler extends Handler {
   1131         private AudioEffect mAudioEffect;
   1132 
   1133         public NativeEventHandler(AudioEffect ae, Looper looper) {
   1134             super(looper);
   1135             mAudioEffect = ae;
   1136         }
   1137 
   1138         @Override
   1139         public void handleMessage(Message msg) {
   1140             if (mAudioEffect == null) {
   1141                 return;
   1142             }
   1143             switch (msg.what) {
   1144             case NATIVE_EVENT_ENABLED_STATUS:
   1145                 OnEnableStatusChangeListener enableStatusChangeListener = null;
   1146                 synchronized (mListenerLock) {
   1147                     enableStatusChangeListener = mAudioEffect.mEnableStatusChangeListener;
   1148                 }
   1149                 if (enableStatusChangeListener != null) {
   1150                     enableStatusChangeListener.onEnableStatusChange(
   1151                             mAudioEffect, (boolean) (msg.arg1 != 0));
   1152                 }
   1153                 break;
   1154             case NATIVE_EVENT_CONTROL_STATUS:
   1155                 OnControlStatusChangeListener controlStatusChangeListener = null;
   1156                 synchronized (mListenerLock) {
   1157                     controlStatusChangeListener = mAudioEffect.mControlChangeStatusListener;
   1158                 }
   1159                 if (controlStatusChangeListener != null) {
   1160                     controlStatusChangeListener.onControlStatusChange(
   1161                             mAudioEffect, (boolean) (msg.arg1 != 0));
   1162                 }
   1163                 break;
   1164             case NATIVE_EVENT_PARAMETER_CHANGED:
   1165                 OnParameterChangeListener parameterChangeListener = null;
   1166                 synchronized (mListenerLock) {
   1167                     parameterChangeListener = mAudioEffect.mParameterChangeListener;
   1168                 }
   1169                 if (parameterChangeListener != null) {
   1170                     // arg1 contains offset of parameter value from start of
   1171                     // byte array
   1172                     int vOffset = msg.arg1;
   1173                     byte[] p = (byte[]) msg.obj;
   1174                     // See effect_param_t in EffectApi.h for psize and vsize
   1175                     // fields offsets
   1176                     int status = byteArrayToInt(p, 0);
   1177                     int psize = byteArrayToInt(p, 4);
   1178                     int vsize = byteArrayToInt(p, 8);
   1179                     byte[] param = new byte[psize];
   1180                     byte[] value = new byte[vsize];
   1181                     System.arraycopy(p, 12, param, 0, psize);
   1182                     System.arraycopy(p, vOffset, value, 0, vsize);
   1183 
   1184                     parameterChangeListener.onParameterChange(mAudioEffect,
   1185                             status, param, value);
   1186                 }
   1187                 break;
   1188 
   1189             default:
   1190                 Log.e(TAG, "handleMessage() Unknown event type: " + msg.what);
   1191                 break;
   1192             }
   1193         }
   1194     }
   1195 
   1196     // ---------------------------------------------------------
   1197     // Java methods called from the native side
   1198     // --------------------
   1199     @SuppressWarnings("unused")
   1200     private static void postEventFromNative(Object effect_ref, int what,
   1201             int arg1, int arg2, Object obj) {
   1202         AudioEffect effect = (AudioEffect) ((WeakReference) effect_ref).get();
   1203         if (effect == null) {
   1204             return;
   1205         }
   1206         if (effect.mNativeEventHandler != null) {
   1207             Message m = effect.mNativeEventHandler.obtainMessage(what, arg1,
   1208                     arg2, obj);
   1209             effect.mNativeEventHandler.sendMessage(m);
   1210         }
   1211 
   1212     }
   1213 
   1214     // ---------------------------------------------------------
   1215     // Native methods called from the Java side
   1216     // --------------------
   1217 
   1218     private static native final void native_init();
   1219 
   1220     private native final int native_setup(Object audioeffect_this, String type,
   1221             String uuid, int priority, int audioSession, int[] id, Object[] desc,
   1222             String opPackageName);
   1223 
   1224     private native final void native_finalize();
   1225 
   1226     private native final void native_release();
   1227 
   1228     private native final int native_setEnabled(boolean enabled);
   1229 
   1230     private native final boolean native_getEnabled();
   1231 
   1232     private native final boolean native_hasControl();
   1233 
   1234     private native final int native_setParameter(int psize, byte[] param,
   1235             int vsize, byte[] value);
   1236 
   1237     private native final int native_getParameter(int psize, byte[] param,
   1238             int vsize, byte[] value);
   1239 
   1240     private native final int native_command(int cmdCode, int cmdSize,
   1241             byte[] cmdData, int repSize, byte[] repData);
   1242 
   1243     private static native Object[] native_query_effects();
   1244 
   1245     private static native Object[] native_query_pre_processing(int audioSession);
   1246 
   1247     // ---------------------------------------------------------
   1248     // Utility methods
   1249     // ------------------
   1250 
   1251     /**
   1252     * @hide
   1253     */
   1254     public void checkState(String methodName) throws IllegalStateException {
   1255         synchronized (mStateLock) {
   1256             if (mState != STATE_INITIALIZED) {
   1257                 throw (new IllegalStateException(methodName
   1258                         + " called on uninitialized AudioEffect."));
   1259             }
   1260         }
   1261     }
   1262 
   1263     /**
   1264      * @hide
   1265      */
   1266     public void checkStatus(int status) {
   1267         if (isError(status)) {
   1268             switch (status) {
   1269             case AudioEffect.ERROR_BAD_VALUE:
   1270                 throw (new IllegalArgumentException(
   1271                         "AudioEffect: bad parameter value"));
   1272             case AudioEffect.ERROR_INVALID_OPERATION:
   1273                 throw (new UnsupportedOperationException(
   1274                         "AudioEffect: invalid parameter operation"));
   1275             default:
   1276                 throw (new RuntimeException("AudioEffect: set/get parameter error"));
   1277             }
   1278         }
   1279     }
   1280 
   1281     /**
   1282      * @hide
   1283      */
   1284     public static boolean isError(int status) {
   1285         return (status < 0);
   1286     }
   1287 
   1288     /**
   1289      * @hide
   1290      */
   1291     public static int byteArrayToInt(byte[] valueBuf) {
   1292         return byteArrayToInt(valueBuf, 0);
   1293 
   1294     }
   1295 
   1296     /**
   1297      * @hide
   1298      */
   1299     public static int byteArrayToInt(byte[] valueBuf, int offset) {
   1300         ByteBuffer converter = ByteBuffer.wrap(valueBuf);
   1301         converter.order(ByteOrder.nativeOrder());
   1302         return converter.getInt(offset);
   1303 
   1304     }
   1305 
   1306     /**
   1307      * @hide
   1308      */
   1309     public static byte[] intToByteArray(int value) {
   1310         ByteBuffer converter = ByteBuffer.allocate(4);
   1311         converter.order(ByteOrder.nativeOrder());
   1312         converter.putInt(value);
   1313         return converter.array();
   1314     }
   1315 
   1316     /**
   1317      * @hide
   1318      */
   1319     public static short byteArrayToShort(byte[] valueBuf) {
   1320         return byteArrayToShort(valueBuf, 0);
   1321     }
   1322 
   1323     /**
   1324      * @hide
   1325      */
   1326     public static short byteArrayToShort(byte[] valueBuf, int offset) {
   1327         ByteBuffer converter = ByteBuffer.wrap(valueBuf);
   1328         converter.order(ByteOrder.nativeOrder());
   1329         return converter.getShort(offset);
   1330 
   1331     }
   1332 
   1333     /**
   1334      * @hide
   1335      */
   1336     public static byte[] shortToByteArray(short value) {
   1337         ByteBuffer converter = ByteBuffer.allocate(2);
   1338         converter.order(ByteOrder.nativeOrder());
   1339         short sValue = (short) value;
   1340         converter.putShort(sValue);
   1341         return converter.array();
   1342     }
   1343 
   1344     /**
   1345      * @hide
   1346      */
   1347     public static byte[] concatArrays(byte[]... arrays) {
   1348         int len = 0;
   1349         for (byte[] a : arrays) {
   1350             len += a.length;
   1351         }
   1352         byte[] b = new byte[len];
   1353 
   1354         int offs = 0;
   1355         for (byte[] a : arrays) {
   1356             System.arraycopy(a, 0, b, offs, a.length);
   1357             offs += a.length;
   1358         }
   1359         return b;
   1360     }
   1361 }
   1362