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