/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.media.audiofx;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.ActivityThread;
import android.compat.annotation.UnsupportedAppUsage;
import android.media.AudioDeviceAttributes;
import android.media.AudioDeviceInfo;
import android.media.AudioSystem;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
import android.util.Log;

import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Objects;
import java.util.UUID;

/**
 * AudioEffect is the base class for controlling audio effects provided by the android audio
 * framework.
 * <p>Applications should not use the AudioEffect class directly but one of its derived classes to
 * control specific effects:
 * <ul>
 *   <li> {@link android.media.audiofx.Equalizer}</li>
 *   <li> {@link android.media.audiofx.Virtualizer}</li>
 *   <li> {@link android.media.audiofx.BassBoost}</li>
 *   <li> {@link android.media.audiofx.PresetReverb}</li>
 *   <li> {@link android.media.audiofx.EnvironmentalReverb}</li>
 *   <li> {@link android.media.audiofx.DynamicsProcessing}</li>
 * </ul>
 * <p>To apply the audio effect to a specific AudioTrack or MediaPlayer instance,
 * the application must specify the audio session ID of that instance when creating the AudioEffect.
 * (see {@link android.media.MediaPlayer#getAudioSessionId()} for details on audio sessions).
 * <p>NOTE: attaching insert effects (equalizer, bass boost, virtualizer) to the global audio output
 * mix by use of session 0 is deprecated.
 * <p>Creating an AudioEffect object will create the corresponding effect engine in the audio
 * framework if no instance of the same effect type exists in the specified audio session.
 * If one exists, this instance will be used.
 * <p>The application creating the AudioEffect object (or a derived class) will either receive
 * control of the effect engine or not depending on the priority parameter. If priority is higher
 * than the priority used by the current effect engine owner, the control will be transfered to the
 * new object. Otherwise control will remain with the previous object. In this case, the new
 * application will be notified of changes in effect engine state or control ownership by the
 * appropriate listener.
 */

public class AudioEffect {
    static {
        System.loadLibrary("audioeffect_jni");
        native_init();
    }

    private final static String TAG = "AudioEffect-JAVA";

    // effect type UUIDs are taken from hardware/libhardware/include/hardware/audio_effect.h

    /**
     * The following UUIDs define effect types corresponding to standard audio
     * effects whose implementation and interface conform to the OpenSL ES
     * specification. The definitions match the corresponding interface IDs in
     * OpenSLES_IID.h
     */
    /**
     * UUID for environmental reverberation effect
     */
    public static final UUID EFFECT_TYPE_ENV_REVERB = UUID
            .fromString("c2e5d5f0-94bd-4763-9cac-4e234d06839e");
    /**
     * UUID for preset reverberation effect
     */
    public static final UUID EFFECT_TYPE_PRESET_REVERB = UUID
            .fromString("47382d60-ddd8-11db-bf3a-0002a5d5c51b");
    /**
     * UUID for equalizer effect
     */
    public static final UUID EFFECT_TYPE_EQUALIZER = UUID
            .fromString("0bed4300-ddd6-11db-8f34-0002a5d5c51b");
    /**
     * UUID for bass boost effect
     */
    public static final UUID EFFECT_TYPE_BASS_BOOST = UUID
            .fromString("0634f220-ddd4-11db-a0fc-0002a5d5c51b");
    /**
     * UUID for virtualizer effect
     */
    public static final UUID EFFECT_TYPE_VIRTUALIZER = UUID
            .fromString("37cc2c00-dddd-11db-8577-0002a5d5c51b");

    /**
     * UUIDs for effect types not covered by OpenSL ES.
     */
    /**
     * UUID for Automatic Gain Control (AGC)
     */
    public static final UUID EFFECT_TYPE_AGC = UUID
            .fromString("0a8abfe0-654c-11e0-ba26-0002a5d5c51b");

    /**
     * UUID for Acoustic Echo Canceler (AEC)
     */
    public static final UUID EFFECT_TYPE_AEC = UUID
            .fromString("7b491460-8d4d-11e0-bd61-0002a5d5c51b");

    /**
     * UUID for Noise Suppressor (NS)
     */
    public static final UUID EFFECT_TYPE_NS = UUID
            .fromString("58b4b260-8e06-11e0-aa8e-0002a5d5c51b");

    /**
     * UUID for Loudness Enhancer
     */
    public static final UUID EFFECT_TYPE_LOUDNESS_ENHANCER = UUID
              .fromString("fe3199be-aed0-413f-87bb-11260eb63cf1");

    /**
     * UUID for Dynamics Processing
     */
    public static final UUID EFFECT_TYPE_DYNAMICS_PROCESSING = UUID
              .fromString("7261676f-6d75-7369-6364-28e2fd3ac39e");

    /**
     * Null effect UUID. See {@link AudioEffect(UUID, UUID, int, int)} for use.
     * @hide
     */
    @TestApi
    public static final UUID EFFECT_TYPE_NULL = UUID
            .fromString("ec7178ec-e5e1-4432-a3f4-4657e6795210");

    /**
     * State of an AudioEffect object that was not successfully initialized upon
     * creation
     * @hide
     */
    public static final int STATE_UNINITIALIZED = 0;
    /**
     * State of an AudioEffect object that is ready to be used.
     * @hide
     */
    public static final int STATE_INITIALIZED = 1;

    // to keep in sync with
    // frameworks/base/include/media/AudioEffect.h
    /**
     * Event id for engine control ownership change notification.
     * @hide
     */
    public static final int NATIVE_EVENT_CONTROL_STATUS = 0;
    /**
     * Event id for engine state change notification.
     * @hide
     */
    public static final int NATIVE_EVENT_ENABLED_STATUS = 1;
    /**
     * Event id for engine parameter change notification.
     * @hide
     */
    public static final int NATIVE_EVENT_PARAMETER_CHANGED = 2;

    /**
     * Successful operation.
     */
    public static final int SUCCESS = 0;
    /**
     * Unspecified error.
     */
    public static final int ERROR = -1;
    /**
     * Internal operation status. Not returned by any method.
     */
    public static final int ALREADY_EXISTS = -2;
    /**
     * Operation failed due to bad object initialization.
     */
    public static final int ERROR_NO_INIT = -3;
    /**
     * Operation failed due to bad parameter value.
     */
    public static final int ERROR_BAD_VALUE = -4;
    /**
     * Operation failed because it was requested in wrong state.
     */
    public static final int ERROR_INVALID_OPERATION = -5;
    /**
     * Operation failed due to lack of memory.
     */
    public static final int ERROR_NO_MEMORY = -6;
    /**
     * Operation failed due to dead remote object.
     */
    public static final int ERROR_DEAD_OBJECT = -7;

    /**
     * The effect descriptor contains information on a particular effect implemented in the
     * audio framework:<br>
     * <ul>
     *  <li>type: UUID identifying the effect type. May be one of:
     * {@link AudioEffect#EFFECT_TYPE_AEC}, {@link AudioEffect#EFFECT_TYPE_AGC},
     * {@link AudioEffect#EFFECT_TYPE_BASS_BOOST}, {@link AudioEffect#EFFECT_TYPE_ENV_REVERB},
     * {@link AudioEffect#EFFECT_TYPE_EQUALIZER}, {@link AudioEffect#EFFECT_TYPE_NS},
     * {@link AudioEffect#EFFECT_TYPE_PRESET_REVERB}, {@link AudioEffect#EFFECT_TYPE_VIRTUALIZER},
     * {@link AudioEffect#EFFECT_TYPE_DYNAMICS_PROCESSING}.
     *  </li>
     *  <li>uuid: UUID for this particular implementation</li>
     *  <li>connectMode: {@link #EFFECT_INSERT} or {@link #EFFECT_AUXILIARY}</li>
     *  <li>name: human readable effect name</li>
     *  <li>implementor: human readable effect implementor name</li>
     * </ul>
     * The method {@link #queryEffects()} returns an array of Descriptors to facilitate effects
     * enumeration.
     */
    public static class Descriptor {

        public Descriptor() {
        }

        /**
         *  Indicates the generic type of the effect (Equalizer, Bass boost ...).
         *  One of {@link AudioEffect#EFFECT_TYPE_AEC},
         *  {@link AudioEffect#EFFECT_TYPE_AGC}, {@link AudioEffect#EFFECT_TYPE_BASS_BOOST},
         *  {@link AudioEffect#EFFECT_TYPE_ENV_REVERB}, {@link AudioEffect#EFFECT_TYPE_EQUALIZER},
         *  {@link AudioEffect#EFFECT_TYPE_NS}, {@link AudioEffect#EFFECT_TYPE_PRESET_REVERB}
         *  {@link AudioEffect#EFFECT_TYPE_VIRTUALIZER}
         *   or {@link AudioEffect#EFFECT_TYPE_DYNAMICS_PROCESSING}.<br>
         *  For reverberation, bass boost, EQ and virtualizer, the UUID
         *  corresponds to the OpenSL ES Interface ID.
         */
        public UUID type;
        /**
         *  Indicates the particular implementation of the effect in that type. Several effects
         *  can have the same type but this uuid is unique to a given implementation.
         */
        public UUID uuid;
        /**
         *  Indicates if the effect is of insert category {@link #EFFECT_INSERT} or auxiliary
         *  category {@link #EFFECT_AUXILIARY}.
         *  Insert effects (typically an {@link Equalizer}) are applied
         *  to the entire audio source and usually not shared by several sources. Auxiliary effects
         *  (typically a reverberator) are applied to part of the signal (wet) and the effect output
         *  is added to the original signal (dry).
         *  Audio pre processing are applied to audio captured on a particular
         * {@link android.media.AudioRecord}.
         */
        public String connectMode;
        /**
         * Human readable effect name
         */
        public String name;
        /**
         * Human readable effect implementor name
         */
        public String implementor;

        /**
         * @param type          UUID identifying the effect type. May be one of:
         * {@link AudioEffect#EFFECT_TYPE_AEC}, {@link AudioEffect#EFFECT_TYPE_AGC},
         * {@link AudioEffect#EFFECT_TYPE_BASS_BOOST}, {@link AudioEffect#EFFECT_TYPE_ENV_REVERB},
         * {@link AudioEffect#EFFECT_TYPE_EQUALIZER}, {@link AudioEffect#EFFECT_TYPE_NS},
         * {@link AudioEffect#EFFECT_TYPE_PRESET_REVERB},
         * {@link AudioEffect#EFFECT_TYPE_VIRTUALIZER},
         * {@link AudioEffect#EFFECT_TYPE_DYNAMICS_PROCESSING}.
         * @param uuid         UUID for this particular implementation
         * @param connectMode  {@link #EFFECT_INSERT} or {@link #EFFECT_AUXILIARY}
         * @param name         human readable effect name
         * @param implementor  human readable effect implementor name
        *
        */
        public Descriptor(String type, String uuid, String connectMode,
                String name, String implementor) {
            this.type = UUID.fromString(type);
            this.uuid = UUID.fromString(uuid);
            this.connectMode = connectMode;
            this.name = name;
            this.implementor = implementor;
        }

        /** @hide */
        @TestApi
        public Descriptor(Parcel in) {
            type = UUID.fromString(in.readString());
            uuid = UUID.fromString(in.readString());
            connectMode = in.readString();
            name = in.readString();
            implementor = in.readString();
        }

        @Override
        public int hashCode() {
            return Objects.hash(type, uuid, connectMode, name, implementor);
        }

        /** @hide */
        @TestApi
        public void writeToParcel(Parcel dest) {
            dest.writeString(type.toString());
            dest.writeString(uuid.toString());
            dest.writeString(connectMode);
            dest.writeString(name);
            dest.writeString(implementor);
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || !(o instanceof Descriptor)) return false;

            Descriptor that = (Descriptor) o;

            return (type.equals(that.type)
                    && uuid.equals(that.uuid)
                    && connectMode.equals(that.connectMode)
                    && name.equals(that.name)
                    && implementor.equals(that.implementor));
        }
    }

    /**
     * Effect connection mode is insert. Specifying an audio session ID when creating the effect
     * will insert this effect after all players in the same audio session.
     */
    public static final String EFFECT_INSERT = "Insert";
    /**
     * Effect connection mode is auxiliary.
     * <p>Auxiliary effects must be created on session 0 (global output mix). In order for a
     * MediaPlayer or AudioTrack to be fed into this effect, they must be explicitely attached to
     * this effect and a send level must be specified.
     * <p>Use the effect ID returned by {@link #getId()} to designate this particular effect when
     * attaching it to the MediaPlayer or AudioTrack.
     */
    public static final String EFFECT_AUXILIARY = "Auxiliary";
    /**
     * Effect connection mode is pre processing.
     * The audio pre processing effects are attached to an audio input stream or device
     */
    public static final String EFFECT_PRE_PROCESSING = "Pre Processing";
    /**
     * Effect connection mode is post processing.
     * The audio post processing effects are attached to an audio output stream or device
     */
    public static final String EFFECT_POST_PROCESSING = "Post Processing";

    // --------------------------------------------------------------------------
    // Member variables
    // --------------------
    /**
     * Indicates the state of the AudioEffect instance
     */
    private int mState = STATE_UNINITIALIZED;
    /**
     * Lock to synchronize access to mState
     */
    private final Object mStateLock = new Object();
    /**
     * System wide unique effect ID
     */
    private int mId;

    // accessed by native methods
    private long mNativeAudioEffect;
    private long mJniData;

    /**
     * Effect descriptor
     */
    private Descriptor mDescriptor;

    /**
     * Listener for effect engine state change notifications.
     *
     * @see #setEnableStatusListener(OnEnableStatusChangeListener)
     */
    private OnEnableStatusChangeListener mEnableStatusChangeListener = null;
    /**
     * Listener for effect engine control ownership change notifications.
     *
     * @see #setControlStatusListener(OnControlStatusChangeListener)
     */
    private OnControlStatusChangeListener mControlChangeStatusListener = null;
    /**
     * Listener for effect engine control ownership change notifications.
     *
     * @see #setParameterListener(OnParameterChangeListener)
     */
    private OnParameterChangeListener mParameterChangeListener = null;
    /**
     * Lock to protect listeners updates against event notifications
     * @hide
     */
    public final Object mListenerLock = new Object();
    /**
     * Handler for events coming from the native code
     * @hide
     */
    public NativeEventHandler mNativeEventHandler = null;

    // --------------------------------------------------------------------------
    // Constructor, Finalize
    // --------------------
    /**
     * Class constructor.
     *
     * @param type type of effect engine created. See {@link #EFFECT_TYPE_ENV_REVERB},
     *            {@link #EFFECT_TYPE_EQUALIZER} ... Types corresponding to
     *            built-in effects are defined by AudioEffect class. Other types
     *            can be specified provided they correspond an existing OpenSL
     *            ES interface ID and the corresponsing effect is available on
     *            the platform. If an unspecified effect type is requested, the
     *            constructor with throw the IllegalArgumentException. This
     *            parameter can be set to {@link #EFFECT_TYPE_NULL} in which
     *            case only the uuid will be used to select the effect.
     * @param uuid unique identifier of a particular effect implementation.
     *            Must be specified if the caller wants to use a particular
     *            implementation of an effect type. This parameter can be set to
     *            {@link #EFFECT_TYPE_NULL} in which case only the type will
     *            be used to select the effect.
     * @param priority the priority level requested by the application for
     *            controlling the effect engine. As the same effect engine can
     *            be shared by several applications, this parameter indicates
     *            how much the requesting application needs control of effect
     *            parameters. The normal priority is 0, above normal is a
     *            positive number, below normal a negative number.
     * @param audioSession system wide unique audio session identifier.
     *            The effect will be attached to the MediaPlayer or AudioTrack in
     *            the same audio session.
     *
     * @throws java.lang.IllegalArgumentException
     * @throws java.lang.UnsupportedOperationException
     * @throws java.lang.RuntimeException
     * @hide
     */

    @UnsupportedAppUsage
    public AudioEffect(UUID type, UUID uuid, int priority, int audioSession)
            throws IllegalArgumentException, UnsupportedOperationException,
            RuntimeException {
        this(type, uuid, priority, audioSession, null);
    }

    /**
     * Constructs an AudioEffect attached to a particular audio device.
     * The device does not have to be attached when the effect is created. The effect will only
     * be applied when the device is actually selected for playback or capture.
     * @param uuid unique identifier of a particular effect implementation.
     * @param device the device the effect must be attached to.
     *
     * @throws java.lang.IllegalArgumentException
     * @throws java.lang.UnsupportedOperationException
     * @throws java.lang.RuntimeException
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.MODIFY_DEFAULT_AUDIO_EFFECTS)
    public AudioEffect(@NonNull UUID uuid, @NonNull AudioDeviceAttributes device) {
        this(EFFECT_TYPE_NULL, Objects.requireNonNull(uuid),
                0, -2, Objects.requireNonNull(device));
    }

    private AudioEffect(UUID type, UUID uuid, int priority,
            int audioSession, @Nullable AudioDeviceAttributes device)
            throws IllegalArgumentException, UnsupportedOperationException,
            RuntimeException {
        this(type, uuid, priority, audioSession, device, false);
    }

    private AudioEffect(UUID type, UUID uuid, int priority,
            int audioSession, @Nullable AudioDeviceAttributes device, boolean probe)
            throws IllegalArgumentException, UnsupportedOperationException,
            RuntimeException {
        int[] id = new int[1];
        Descriptor[] desc = new Descriptor[1];

        int deviceType = AudioSystem.DEVICE_NONE;
        String deviceAddress = "";
        if (device != null) {
            deviceType = AudioDeviceInfo.convertDeviceTypeToInternalDevice(device.getType());
            deviceAddress = device.getAddress();
        }

        // native initialization
        int initResult = native_setup(new WeakReference<AudioEffect>(this),
                type.toString(), uuid.toString(), priority, audioSession,
                deviceType, deviceAddress,
                id, desc, ActivityThread.currentOpPackageName(), probe);
        if (initResult != SUCCESS && initResult != ALREADY_EXISTS) {
            Log.e(TAG, "Error code " + initResult
                    + " when initializing AudioEffect.");
            switch (initResult) {
            case ERROR_BAD_VALUE:
                throw (new IllegalArgumentException("Effect type: " + type
                        + " not supported."));
            case ERROR_INVALID_OPERATION:
                throw (new UnsupportedOperationException(
                        "Effect library not loaded"));
            default:
                throw (new RuntimeException(
                        "Cannot initialize effect engine for type: " + type
                                + " Error: " + initResult));
            }
        }
        mId = id[0];
        mDescriptor = desc[0];
        if (!probe) {
            synchronized (mStateLock) {
                mState = STATE_INITIALIZED;
            }
        }
    }

    /**
     * Checks if an AudioEffect identified by the supplied uuid can be attached
     * to an audio device described by the supplied AudioDeviceAttributes.
     * @param uuid unique identifier of a particular effect implementation.
     * @param device the device the effect would be attached to.
     * @return true if possible, false otherwise.
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.MODIFY_DEFAULT_AUDIO_EFFECTS)
    public static boolean isEffectSupportedForDevice(
            @NonNull UUID uuid, @NonNull AudioDeviceAttributes device) {
        try {
            AudioEffect fx = new AudioEffect(
                    EFFECT_TYPE_NULL, Objects.requireNonNull(uuid),
                    0, -2, Objects.requireNonNull(device), true);
            fx.release();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * Releases the native AudioEffect resources. It is a good practice to
     * release the effect engine when not in use as control can be returned to
     * other applications or the native resources released.
     */
    public void release() {
        synchronized (mStateLock) {
            native_release();
            mState = STATE_UNINITIALIZED;
        }
    }

    @Override
    protected void finalize() {
        native_finalize();
    }

    /**
     * Get the effect descriptor.
     *
     * @see android.media.audiofx.AudioEffect.Descriptor
     * @throws IllegalStateException
     */
    public Descriptor getDescriptor() throws IllegalStateException {
        checkState("getDescriptor()");
        return mDescriptor;
    }

    // --------------------------------------------------------------------------
    // Effects Enumeration
    // --------------------

    /**
     * Query all effects available on the platform. Returns an array of
     * {@link android.media.audiofx.AudioEffect.Descriptor} objects
     *
     * @throws IllegalStateException
     */

    static public Descriptor[] queryEffects() {
        return (Descriptor[]) native_query_effects();
    }

    /**
     * Query all audio pre-processing effects applied to the AudioRecord with the supplied
     * audio session ID. Returns an array of {@link android.media.audiofx.AudioEffect.Descriptor}
     * objects.
     * @param audioSession system wide unique audio session identifier.
     * @throws IllegalStateException
     * @hide
     */

    static public Descriptor[] queryPreProcessings(int audioSession) {
        return (Descriptor[]) native_query_pre_processing(audioSession);
    }

    /**
     * Checks if the device implements the specified effect type.
     * @param type the requested effect type.
     * @return true if the device implements the specified effect type, false otherwise.
     * @hide
     */
    @TestApi
    public static boolean isEffectTypeAvailable(UUID type) {
        AudioEffect.Descriptor[] desc = AudioEffect.queryEffects();
        if (desc == null) {
            return false;
        }

        for (int i = 0; i < desc.length; i++) {
            if (desc[i].type.equals(type)) {
                return true;
            }
        }
        return false;
    }

    // --------------------------------------------------------------------------
    // Control methods
    // --------------------

    /**
     * Enable or disable the effect.
     * Creating an audio effect does not automatically apply this effect on the audio source. It
     * creates the resources necessary to process this effect but the audio signal is still bypassed
     * through the effect engine. Calling this method will make that the effect is actually applied
     * or not to the audio content being played in the corresponding audio session.
     *
     * @param enabled the requested enable state
     * @return {@link #SUCCESS} in case of success, {@link #ERROR_INVALID_OPERATION}
     *         or {@link #ERROR_DEAD_OBJECT} in case of failure.
     * @throws IllegalStateException
     */
    public int setEnabled(boolean enabled) throws IllegalStateException {
        checkState("setEnabled()");
        return native_setEnabled(enabled);
    }

    /**
     * Set effect parameter. The setParameter method is provided in several
     * forms addressing most common parameter formats. This form is the most
     * generic one where the parameter and its value are both specified as an
     * array of bytes. The parameter and value type and length are therefore
     * totally free. For standard effect defined by OpenSL ES, the parameter
     * format and values must match the definitions in the corresponding OpenSL
     * ES interface.
     *
     * @param param the identifier of the parameter to set
     * @param value the new value for the specified parameter
     * @return {@link #SUCCESS} in case of success, {@link #ERROR_BAD_VALUE},
     *         {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION} or
     *         {@link #ERROR_DEAD_OBJECT} in case of failure
     * @throws IllegalStateException
     * @hide
     */
    @TestApi
    public int setParameter(byte[] param, byte[] value)
            throws IllegalStateException {
        checkState("setParameter()");
        return native_setParameter(param.length, param, value.length, value);
    }

    /**
     * Set effect parameter. The parameter and its value are integers.
     *
     * @see #setParameter(byte[], byte[])
     * @hide
     */
    @TestApi
    public int setParameter(int param, int value) throws IllegalStateException {
        byte[] p = intToByteArray(param);
        byte[] v = intToByteArray(value);
        return setParameter(p, v);
    }

    /**
     * Set effect parameter. The parameter is an integer and the value is a
     * short integer.
     *
     * @see #setParameter(byte[], byte[])
     * @hide
     */
    @TestApi
    public int setParameter(int param, short value)
            throws IllegalStateException {
        byte[] p = intToByteArray(param);
        byte[] v = shortToByteArray(value);
        return setParameter(p, v);
    }

    /**
     * Set effect parameter. The parameter is an integer and the value is an
     * array of bytes.
     *
     * @see #setParameter(byte[], byte[])
     * @hide
     */
    @TestApi
    public int setParameter(int param, byte[] value)
            throws IllegalStateException {
        byte[] p = intToByteArray(param);
        return setParameter(p, value);
    }

    /**
     * Set effect parameter. The parameter is an array of 1 or 2 integers and
     * the value is also an array of 1 or 2 integers
     *
     * @see #setParameter(byte[], byte[])
     * @hide
     */
    @TestApi
    public int setParameter(int[] param, int[] value)
            throws IllegalStateException {
        if (param.length > 2 || value.length > 2) {
            return ERROR_BAD_VALUE;
        }
        byte[] p = intToByteArray(param[0]);
        if (param.length > 1) {
            byte[] p2 = intToByteArray(param[1]);
            p = concatArrays(p, p2);
        }
        byte[] v = intToByteArray(value[0]);
        if (value.length > 1) {
            byte[] v2 = intToByteArray(value[1]);
            v = concatArrays(v, v2);
        }
        return setParameter(p, v);
    }

    /**
     * Set effect parameter. The parameter is an array of 1 or 2 integers and
     * the value is an array of 1 or 2 short integers
     *
     * @see #setParameter(byte[], byte[])
     * @hide
     */
    @UnsupportedAppUsage
    public int setParameter(int[] param, short[] value)
            throws IllegalStateException {
        if (param.length > 2 || value.length > 2) {
            return ERROR_BAD_VALUE;
        }
        byte[] p = intToByteArray(param[0]);
        if (param.length > 1) {
            byte[] p2 = intToByteArray(param[1]);
            p = concatArrays(p, p2);
        }

        byte[] v = shortToByteArray(value[0]);
        if (value.length > 1) {
            byte[] v2 = shortToByteArray(value[1]);
            v = concatArrays(v, v2);
        }
        return setParameter(p, v);
    }

    /**
     * Set effect parameter. The parameter is an array of 1 or 2 integers and
     * the value is an array of bytes
     *
     * @see #setParameter(byte[], byte[])
     * @hide
     */
    @TestApi
    public int setParameter(int[] param, byte[] value)
            throws IllegalStateException {
        if (param.length > 2) {
            return ERROR_BAD_VALUE;
        }
        byte[] p = intToByteArray(param[0]);
        if (param.length > 1) {
            byte[] p2 = intToByteArray(param[1]);
            p = concatArrays(p, p2);
        }
        return setParameter(p, value);
    }

    /**
     * Get effect parameter. The getParameter method is provided in several
     * forms addressing most common parameter formats. This form is the most
     * generic one where the parameter and its value are both specified as an
     * array of bytes. The parameter and value type and length are therefore
     * totally free.
     *
     * @param param the identifier of the parameter to set
     * @param value the new value for the specified parameter
     * @return the number of meaningful bytes in value array in case of success or
     *  {@link #ERROR_BAD_VALUE}, {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION}
     *  or {@link #ERROR_DEAD_OBJECT} in case of failure.
     * @throws IllegalStateException
     * @hide
     */
    @TestApi
    public int getParameter(byte[] param, byte[] value)
            throws IllegalStateException {
        checkState("getParameter()");
        return native_getParameter(param.length, param, value.length, value);
    }

    /**
     * Get effect parameter. The parameter is an integer and the value is an
     * array of bytes.
     *
     * @see #getParameter(byte[], byte[])
     * @hide
     */
    @TestApi
    public int getParameter(int param, byte[] value)
            throws IllegalStateException {
        byte[] p = intToByteArray(param);

        return getParameter(p, value);
    }

    /**
     * Get effect parameter. The parameter is an integer and the value is an
     * array of 1 or 2 integers
     *
     * @see #getParameter(byte[], byte[])
     * In case of success, returns the number of meaningful integers in value array.
     * @hide
     */
    @TestApi
    public int getParameter(int param, int[] value)
            throws IllegalStateException {
        if (value.length > 2) {
            return ERROR_BAD_VALUE;
        }
        byte[] p = intToByteArray(param);

        byte[] v = new byte[value.length * 4];

        int status = getParameter(p, v);

        if (status == 4 || status == 8) {
            value[0] = byteArrayToInt(v);
            if (status == 8) {
                value[1] = byteArrayToInt(v, 4);
            }
            status /= 4;
        } else {
            status = ERROR;
        }
        return status;
    }

    /**
     * Get effect parameter. The parameter is an integer and the value is an
     * array of 1 or 2 short integers
     *
     * @see #getParameter(byte[], byte[])
     * In case of success, returns the number of meaningful short integers in value array.
     * @hide
     */
    @TestApi
    public int getParameter(int param, short[] value)
            throws IllegalStateException {
        if (value.length > 2) {
            return ERROR_BAD_VALUE;
        }
        byte[] p = intToByteArray(param);

        byte[] v = new byte[value.length * 2];

        int status = getParameter(p, v);

        if (status == 2 || status == 4) {
            value[0] = byteArrayToShort(v);
            if (status == 4) {
                value[1] = byteArrayToShort(v, 2);
            }
            status /= 2;
        } else {
            status = ERROR;
        }
        return status;
    }

    /**
     * Get effect parameter. The parameter is an array of 1 or 2 integers and
     * the value is also an array of 1 or 2 integers
     *
     * @see #getParameter(byte[], byte[])
     * In case of success, the returns the number of meaningful integers in value array.
     * @hide
     */
    @UnsupportedAppUsage
    public int getParameter(int[] param, int[] value)
            throws IllegalStateException {
        if (param.length > 2 || value.length > 2) {
            return ERROR_BAD_VALUE;
        }
        byte[] p = intToByteArray(param[0]);
        if (param.length > 1) {
            byte[] p2 = intToByteArray(param[1]);
            p = concatArrays(p, p2);
        }
        byte[] v = new byte[value.length * 4];

        int status = getParameter(p, v);

        if (status == 4 || status == 8) {
            value[0] = byteArrayToInt(v);
            if (status == 8) {
                value[1] = byteArrayToInt(v, 4);
            }
            status /= 4;
        } else {
            status = ERROR;
        }
        return status;
    }

    /**
     * Get effect parameter. The parameter is an array of 1 or 2 integers and
     * the value is an array of 1 or 2 short integers
     *
     * @see #getParameter(byte[], byte[])
     * In case of success, returns the number of meaningful short integers in value array.
     * @hide
     */
    @TestApi
    public int getParameter(int[] param, short[] value)
            throws IllegalStateException {
        if (param.length > 2 || value.length > 2) {
            return ERROR_BAD_VALUE;
        }
        byte[] p = intToByteArray(param[0]);
        if (param.length > 1) {
            byte[] p2 = intToByteArray(param[1]);
            p = concatArrays(p, p2);
        }
        byte[] v = new byte[value.length * 2];

        int status = getParameter(p, v);

        if (status == 2 || status == 4) {
            value[0] = byteArrayToShort(v);
            if (status == 4) {
                value[1] = byteArrayToShort(v, 2);
            }
            status /= 2;
        } else {
            status = ERROR;
        }
        return status;
    }

    /**
     * Get effect parameter. The parameter is an array of 1 or 2 integers and
     * the value is an array of bytes
     *
     * @see #getParameter(byte[], byte[])
     * @hide
     */
    @UnsupportedAppUsage
    public int getParameter(int[] param, byte[] value)
            throws IllegalStateException {
        if (param.length > 2) {
            return ERROR_BAD_VALUE;
        }
        byte[] p = intToByteArray(param[0]);
        if (param.length > 1) {
            byte[] p2 = intToByteArray(param[1]);
            p = concatArrays(p, p2);
        }

        return getParameter(p, value);
    }

    /**
     * Send a command to the effect engine. This method is intended to send
     * proprietary commands to a particular effect implementation.
     * In case of success, returns the number of meaningful bytes in reply array.
     * In case of failure, the returned value is negative and implementation specific.
     * @hide
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    public int command(int cmdCode, byte[] command, byte[] reply)
            throws IllegalStateException {
        checkState("command()");
        return native_command(cmdCode, command.length, command, reply.length, reply);
    }

    // --------------------------------------------------------------------------
    // Getters
    // --------------------

    /**
     * Returns effect unique identifier. This system wide unique identifier can
     * be used to attach this effect to a MediaPlayer or an AudioTrack when the
     * effect is an auxiliary effect (Reverb)
     *
     * @return the effect identifier.
     * @throws IllegalStateException
     */
    public int getId() throws IllegalStateException {
        checkState("getId()");
        return mId;
    }

    /**
     * Returns effect enabled state
     *
     * @return true if the effect is enabled, false otherwise.
     * @throws IllegalStateException
     */
    public boolean getEnabled() throws IllegalStateException {
        checkState("getEnabled()");
        return native_getEnabled();
    }

    /**
     * Checks if this AudioEffect object is controlling the effect engine.
     *
     * @return true if this instance has control of effect engine, false
     *         otherwise.
     * @throws IllegalStateException
     */
    public boolean hasControl() throws IllegalStateException {
        checkState("hasControl()");
        return native_hasControl();
    }

    // --------------------------------------------------------------------------
    // Initialization / configuration
    // --------------------
    /**
     * Sets the listener AudioEffect notifies when the effect engine is enabled
     * or disabled.
     *
     * @param listener
     */
    public void setEnableStatusListener(OnEnableStatusChangeListener listener) {
        synchronized (mListenerLock) {
            mEnableStatusChangeListener = listener;
        }
        if ((listener != null) && (mNativeEventHandler == null)) {
            createNativeEventHandler();
        }
    }

    /**
     * Sets the listener AudioEffect notifies when the effect engine control is
     * taken or returned.
     *
     * @param listener
     */
    public void setControlStatusListener(OnControlStatusChangeListener listener) {
        synchronized (mListenerLock) {
            mControlChangeStatusListener = listener;
        }
        if ((listener != null) && (mNativeEventHandler == null)) {
            createNativeEventHandler();
        }
    }

    /**
     * Sets the listener AudioEffect notifies when a parameter is changed.
     *
     * @param listener
     * @hide
     */
    @TestApi
    public void setParameterListener(OnParameterChangeListener listener) {
        synchronized (mListenerLock) {
            mParameterChangeListener = listener;
        }
        if ((listener != null) && (mNativeEventHandler == null)) {
            createNativeEventHandler();
        }
    }

    // Convenience method for the creation of the native event handler
    // It is called only when a non-null event listener is set.
    // precondition:
    // mNativeEventHandler is null
    private void createNativeEventHandler() {
        Looper looper;
        if ((looper = Looper.myLooper()) != null) {
            mNativeEventHandler = new NativeEventHandler(this, looper);
        } else if ((looper = Looper.getMainLooper()) != null) {
            mNativeEventHandler = new NativeEventHandler(this, looper);
        } else {
            mNativeEventHandler = null;
        }
    }

    // ---------------------------------------------------------
    // Interface definitions
    // --------------------
    /**
     * The OnEnableStatusChangeListener interface defines a method called by the AudioEffect
     * when the enabled state of the effect engine was changed by the controlling application.
     */
    public interface OnEnableStatusChangeListener {
        /**
         * Called on the listener to notify it that the effect engine has been
         * enabled or disabled.
         * @param effect the effect on which the interface is registered.
         * @param enabled new effect state.
         */
        void onEnableStatusChange(AudioEffect effect, boolean enabled);
    }

    /**
     * The OnControlStatusChangeListener interface defines a method called by the AudioEffect
     * when control of the effect engine is gained or lost by the application
     */
    public interface OnControlStatusChangeListener {
        /**
         * Called on the listener to notify it that the effect engine control
         * has been taken or returned.
         * @param effect the effect on which the interface is registered.
         * @param controlGranted true if the application has been granted control of the effect
         * engine, false otherwise.
         */
        void onControlStatusChange(AudioEffect effect, boolean controlGranted);
    }

    /**
     * The OnParameterChangeListener interface defines a method called by the AudioEffect
     * when a parameter is changed in the effect engine by the controlling application.
     * @hide
     */
    @TestApi
    public interface OnParameterChangeListener {
        /**
         * Called on the listener to notify it that a parameter value has changed.
         * @param effect the effect on which the interface is registered.
         * @param status status of the set parameter operation.
         * @param param ID of the modified parameter.
         * @param value the new parameter value.
         */
        void onParameterChange(AudioEffect effect, int status, byte[] param,
                byte[] value);
    }


    // -------------------------------------------------------------------------
    // Audio Effect Control panel intents
    // -------------------------------------------------------------------------

    /**
     *  Intent to launch an audio effect control panel UI.
     *  <p>The goal of this intent is to enable separate implementations of music/media player
     *  applications and audio effect control application or services.
     *  This will allow platform vendors to offer more advanced control options for standard effects
     *  or control for platform specific effects.
     *  <p>The intent carries a number of extras used by the player application to communicate
     *  necessary pieces of information to the control panel application.
     *  <p>The calling application must use the
     *  {@link android.app.Activity#startActivityForResult(Intent, int)} method to launch the
     *  control panel so that its package name is indicated and used by the control panel
     *  application to keep track of changes for this particular application.
     *  <p>The {@link #EXTRA_AUDIO_SESSION} extra will indicate an audio session to which the
     *  audio effects should be applied. If no audio session is specified, either one of the
     *  follownig will happen:
     *  <p>- If an audio session was previously opened by the calling application with
     *  {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} intent, the effect changes will
     *  be applied to that session.
     *  <p>- If no audio session is opened, the changes will be stored in the package specific
     *  storage area and applied whenever a new audio session is opened by this application.
     *  <p>The {@link #EXTRA_CONTENT_TYPE} extra will help the control panel application
     *  customize both the UI layout and the default audio effect settings if none are already
     *  stored for the calling application.
     */
    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL =
        "android.media.action.DISPLAY_AUDIO_EFFECT_CONTROL_PANEL";

    /**
     *  Intent to signal to the effect control application or service that a new audio session
     *  is opened and requires audio effects to be applied.
     *  <p>This is different from {@link #ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL} in that no
     *  UI should be displayed in this case. Music player applications can broadcast this intent
     *  before starting playback to make sure that any audio effect settings previously selected
     *  by the user are applied.
     *  <p>The effect control application receiving this intent will look for previously stored
     *  settings for the calling application, create all required audio effects and apply the
     *  effect settings to the specified audio session.
     *  <p>The calling package name is indicated by the {@link #EXTRA_PACKAGE_NAME} extra and the
     *  audio session ID by the {@link #EXTRA_AUDIO_SESSION} extra. Both extras are mandatory.
     *  <p>If no stored settings are found for the calling application, default settings for the
     *  content type indicated by {@link #EXTRA_CONTENT_TYPE} will be applied. The default settings
     *  for a given content type are platform specific.
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION =
        "android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION";

    /**
     *  Intent to signal to the effect control application or service that an audio session
     *  is closed and that effects should not be applied anymore.
     *  <p>The effect control application receiving this intent will delete all effects on
     *  this session and store current settings in package specific storage.
     *  <p>The calling package name is indicated by the {@link #EXTRA_PACKAGE_NAME} extra and the
     *  audio session ID by the {@link #EXTRA_AUDIO_SESSION} extra. Both extras are mandatory.
     *  <p>It is good practice for applications to broadcast this intent when music playback stops
     *  and/or when exiting to free system resources consumed by audio effect engines.
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION =
        "android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION";

    /**
     * Contains the ID of the audio session the effects should be applied to.
     * <p>This extra is for use with {@link #ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL},
     * {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} and
     * {@link #ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION} intents.
     * <p>The extra value is of type int and is the audio session ID.
     *  @see android.media.MediaPlayer#getAudioSessionId() for details on audio sessions.
     */
     public static final String EXTRA_AUDIO_SESSION = "android.media.extra.AUDIO_SESSION";

    /**
     * Contains the package name of the calling application.
     * <p>This extra is for use with {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} and
     * {@link #ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION} intents.
     * <p>The extra value is a string containing the full package name.
     */
    public static final String EXTRA_PACKAGE_NAME = "android.media.extra.PACKAGE_NAME";

    /**
     * Indicates which type of content is played by the application.
     * <p>This extra is for use with {@link #ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL} and
     * {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} intents.
     * <p>This information is used by the effect control application to customize UI and select
     * appropriate default effect settings. The content type is one of the following:
     * <ul>
     *   <li>{@link #CONTENT_TYPE_MUSIC}</li>
     *   <li>{@link #CONTENT_TYPE_MOVIE}</li>
     *   <li>{@link #CONTENT_TYPE_GAME}</li>
     *   <li>{@link #CONTENT_TYPE_VOICE}</li>
     * </ul>
     * If omitted, the content type defaults to {@link #CONTENT_TYPE_MUSIC}.
     */
    public static final String EXTRA_CONTENT_TYPE = "android.media.extra.CONTENT_TYPE";

    /**
     * Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is music
     */
    public static final int  CONTENT_TYPE_MUSIC = 0;
    /**
     * Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is video or movie
     */
    public static final int  CONTENT_TYPE_MOVIE = 1;
    /**
     * Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is game audio
     */
    public static final int  CONTENT_TYPE_GAME = 2;
    /**
     * Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is voice audio
     */
    public static final int  CONTENT_TYPE_VOICE = 3;


    // ---------------------------------------------------------
    // Inner classes
    // --------------------
    /**
     * Helper class to handle the forwarding of native events to the appropriate
     * listeners
     */
    private class NativeEventHandler extends Handler {
        private AudioEffect mAudioEffect;

        public NativeEventHandler(AudioEffect ae, Looper looper) {
            super(looper);
            mAudioEffect = ae;
        }

        @Override
        public void handleMessage(Message msg) {
            if (mAudioEffect == null) {
                return;
            }
            switch (msg.what) {
            case NATIVE_EVENT_ENABLED_STATUS:
                OnEnableStatusChangeListener enableStatusChangeListener = null;
                synchronized (mListenerLock) {
                    enableStatusChangeListener = mAudioEffect.mEnableStatusChangeListener;
                }
                if (enableStatusChangeListener != null) {
                    enableStatusChangeListener.onEnableStatusChange(
                            mAudioEffect, (boolean) (msg.arg1 != 0));
                }
                break;
            case NATIVE_EVENT_CONTROL_STATUS:
                OnControlStatusChangeListener controlStatusChangeListener = null;
                synchronized (mListenerLock) {
                    controlStatusChangeListener = mAudioEffect.mControlChangeStatusListener;
                }
                if (controlStatusChangeListener != null) {
                    controlStatusChangeListener.onControlStatusChange(
                            mAudioEffect, (boolean) (msg.arg1 != 0));
                }
                break;
            case NATIVE_EVENT_PARAMETER_CHANGED:
                OnParameterChangeListener parameterChangeListener = null;
                synchronized (mListenerLock) {
                    parameterChangeListener = mAudioEffect.mParameterChangeListener;
                }
                if (parameterChangeListener != null) {
                    // arg1 contains offset of parameter value from start of
                    // byte array
                    int vOffset = msg.arg1;
                    byte[] p = (byte[]) msg.obj;
                    // See effect_param_t in EffectApi.h for psize and vsize
                    // fields offsets
                    int status = byteArrayToInt(p, 0);
                    int psize = byteArrayToInt(p, 4);
                    int vsize = byteArrayToInt(p, 8);
                    byte[] param = new byte[psize];
                    byte[] value = new byte[vsize];
                    System.arraycopy(p, 12, param, 0, psize);
                    System.arraycopy(p, vOffset, value, 0, vsize);

                    parameterChangeListener.onParameterChange(mAudioEffect,
                            status, param, value);
                }
                break;

            default:
                Log.e(TAG, "handleMessage() Unknown event type: " + msg.what);
                break;
            }
        }
    }

    // ---------------------------------------------------------
    // Java methods called from the native side
    // --------------------
    @SuppressWarnings("unused")
    private static void postEventFromNative(Object effect_ref, int what,
            int arg1, int arg2, Object obj) {
        AudioEffect effect = (AudioEffect) ((WeakReference) effect_ref).get();
        if (effect == null) {
            return;
        }
        if (effect.mNativeEventHandler != null) {
            Message m = effect.mNativeEventHandler.obtainMessage(what, arg1,
                    arg2, obj);
            effect.mNativeEventHandler.sendMessage(m);
        }

    }

    // ---------------------------------------------------------
    // Native methods called from the Java side
    // --------------------

    private static native final void native_init();

    private native final int native_setup(Object audioeffect_this, String type,
            String uuid, int priority, int audioSession,
            int deviceType, String deviceAddress, int[] id, Object[] desc,
            String opPackageName, boolean probe);

    private native final void native_finalize();

    private native final void native_release();

    private native final int native_setEnabled(boolean enabled);

    private native final boolean native_getEnabled();

    private native final boolean native_hasControl();

    private native final int native_setParameter(int psize, byte[] param,
            int vsize, byte[] value);

    private native final int native_getParameter(int psize, byte[] param,
            int vsize, byte[] value);

    private native final int native_command(int cmdCode, int cmdSize,
            byte[] cmdData, int repSize, byte[] repData);

    private static native Object[] native_query_effects();

    private static native Object[] native_query_pre_processing(int audioSession);

    // ---------------------------------------------------------
    // Utility methods
    // ------------------

    /**
    * @hide
    */
    @UnsupportedAppUsage
    public void checkState(String methodName) throws IllegalStateException {
        synchronized (mStateLock) {
            if (mState != STATE_INITIALIZED) {
                throw (new IllegalStateException(methodName
                        + " called on uninitialized AudioEffect."));
            }
        }
    }

    /**
     * @hide
     */
    public void checkStatus(int status) {
        if (isError(status)) {
            switch (status) {
            case AudioEffect.ERROR_BAD_VALUE:
                throw (new IllegalArgumentException(
                        "AudioEffect: bad parameter value"));
            case AudioEffect.ERROR_INVALID_OPERATION:
                throw (new UnsupportedOperationException(
                        "AudioEffect: invalid parameter operation"));
            default:
                throw (new RuntimeException("AudioEffect: set/get parameter error"));
            }
        }
    }

    /**
     * @hide
     */
    @TestApi
    public static boolean isError(int status) {
        return (status < 0);
    }

    /**
     * @hide
     */
    @TestApi
    public static int byteArrayToInt(byte[] valueBuf) {
        return byteArrayToInt(valueBuf, 0);

    }

    /**
     * @hide
     */
    public static int byteArrayToInt(byte[] valueBuf, int offset) {
        ByteBuffer converter = ByteBuffer.wrap(valueBuf);
        converter.order(ByteOrder.nativeOrder());
        return converter.getInt(offset);

    }

    /**
     * @hide
     */
    @TestApi
    public static byte[] intToByteArray(int value) {
        ByteBuffer converter = ByteBuffer.allocate(4);
        converter.order(ByteOrder.nativeOrder());
        converter.putInt(value);
        return converter.array();
    }

    /**
     * @hide
     */
    @TestApi
    public static short byteArrayToShort(byte[] valueBuf) {
        return byteArrayToShort(valueBuf, 0);
    }

    /**
     * @hide
     */
    public static short byteArrayToShort(byte[] valueBuf, int offset) {
        ByteBuffer converter = ByteBuffer.wrap(valueBuf);
        converter.order(ByteOrder.nativeOrder());
        return converter.getShort(offset);

    }

    /**
     * @hide
     */
    @TestApi
    public static byte[] shortToByteArray(short value) {
        ByteBuffer converter = ByteBuffer.allocate(2);
        converter.order(ByteOrder.nativeOrder());
        short sValue = (short) value;
        converter.putShort(sValue);
        return converter.array();
    }

    /**
     * @hide
     */
    public static float byteArrayToFloat(byte[] valueBuf) {
        return byteArrayToFloat(valueBuf, 0);

    }

    /**
     * @hide
     */
    public static float byteArrayToFloat(byte[] valueBuf, int offset) {
        ByteBuffer converter = ByteBuffer.wrap(valueBuf);
        converter.order(ByteOrder.nativeOrder());
        return converter.getFloat(offset);

    }

    /**
     * @hide
     */
    public static byte[] floatToByteArray(float value) {
        ByteBuffer converter = ByteBuffer.allocate(4);
        converter.order(ByteOrder.nativeOrder());
        converter.putFloat(value);
        return converter.array();
    }

    /**
     * @hide
     */
    public static byte[] concatArrays(byte[]... arrays) {
        int len = 0;
        for (byte[] a : arrays) {
            len += a.length;
        }
        byte[] b = new byte[len];

        int offs = 0;
        for (byte[] a : arrays) {
            System.arraycopy(a, 0, b, offs, a.length);
            offs += a.length;
        }
        return b;
    }
}
