/******************************************************************************
 *
 *  Copyright 2021 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 com.android.bluetooth.acm;

import static android.Manifest.permission.BLUETOOTH_CONNECT;

import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission;

import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothA2dp.OptionalCodecsPreferenceStatus;
import android.bluetooth.BluetoothA2dp.OptionalCodecsSupportStatus;
import android.bluetooth.BluetoothCodecConfig;
import android.bluetooth.BluetoothCodecStatus;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.HandlerThread;
import android.os.Handler;
import android.os.Binder;
import android.os.IBinder;
import android.os.ParcelUuid;
import android.util.Log;
import android.os.Message;
import android.bluetooth.BluetoothGroupCallback;
import com.android.bluetooth.groupclient.GroupService;
import android.bluetooth.DeviceGroup;
import android.bluetooth.BluetoothDeviceGroup;
import com.android.bluetooth.apm.ActiveDeviceManagerService;
import com.android.bluetooth.apm.VolumeManager;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import android.os.SystemProperties;
import com.android.bluetooth.BluetoothMetricsProto;
import com.android.bluetooth.BluetoothStatsLog;
import com.android.bluetooth.Utils;
import android.bluetooth.BluetoothAdapter;
import com.android.bluetooth.apm.ApmConst;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.MetricsLogger;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.btservice.ServiceFactory;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import com.android.bluetooth.vcp.VcpController;
/**
 * Provides Bluetooth ACM profile, as a service in the Bluetooth application.
 * @hide
 */
public class AcmService extends ProfileService {
    private static final boolean DBG = true;
    private static final String TAG = "AcmService";
    private String mAcmName;
    public static final int ACM_AUDIO_UNICAST = 25;
    public static final int INVALID_SET_ID = 0x10;
    private static AcmService sAcmService;
    private BluetoothAdapter mAdapter;
    private AdapterService mAdapterService;
    private HandlerThread mStateMachinesThread;
    private static final int LOCK_RELEASED = 0;                    // (LOCK Released successfully)
    private static final int LOCK_RELEASED_TIMEOUT = 1;          // (LOCK Released by timeout)
    private static final int ALL_LOCKS_ACQUIRED = 2;              // (LOCK Acquired for all requested set members)
    private static final int SOME_LOCKS_ACQUIRED_REASON_TIMEOUT = 3; // (Request timeout for some set members)
    private static final int SOME_LOCKS_ACQUIRED_REASON_DISC = 4;   // (Some of the set members were disconnected)
    private static final int LOCK_DENIED = 5;                     // (Denied by one of the set members)
    private static final int INVALID_REQUEST_PARAMS = 6;         // (Upper layer provided invalid parameters)
    private static final int LOCK_RELEASE_NOT_ALLOWED = 7;           // (Response from remote (PTS))
    private static final int INVALID_VALUE = 8;
    @VisibleForTesting
    AcmNativeInterface mAcmNativeInterface;
    @VisibleForTesting
    ServiceFactory mFactory = new ServiceFactory();

    static final int CONTEXT_TYPE_UNKNOWN = 0;
    static final int CONTEXT_TYPE_MUSIC = 1;
    static final int CONTEXT_TYPE_VOICE = 2;
    static final int CONTEXT_TYPE_MUSIC_VOICE = 3;
    static final int CONTEXT_TYPE_BROADCAST_AUDIO = 6;

    private AcmCodecConfig mAcmCodecConfig;
    private final Object mAudioManagerLock = new Object();
    private final Object mBtLeaLock = new Object();
    private final Object mBtAcmLock = new Object();
    private String mLeaChannelMode = "stereo";
    private AudioManager mAudioManager;
    @GuardedBy("mStateMachines")
    private BluetoothDevice mGroupBdAddress = null;
    private BluetoothDevice mActiveDevice = null;
    private BluetoothDevice mActiveDeviceVoice = null;
    private int mActiveDeviceProfile = 0;
    private int mActiveDeviceVoiceProfile = 0;
    private final ConcurrentMap<BluetoothDevice, AcmStateMachine> mStateMachines =
            new ConcurrentHashMap<>();
    private HashMap<BluetoothDevice, BluetoothAcmDevice> mAcmDevices =
                     new HashMap<BluetoothDevice, BluetoothAcmDevice>();

    // Upper limit of all ACM devices: Bonded or Connected
    private static final int MAX_ACM_STATE_MACHINES = 50;
    // Upper limit of all ACM devices that are Connected or Connecting
    private int mMaxConnectedAudioDevices = 1;
    CsipManager mCsipManager = null;
    boolean mIsCsipRegistered = false;
    boolean mShoPend = false;
    boolean mVoiceShoPend = false;
    //volume
    private int mAudioStreamMax;
    private int mActiveDeviceLocalMediaVol;
    private int mActiveDeviceLocalVoiceVol;
    private boolean mActiveDeviceIsMuted;
    private static final int VCP_MAX_VOL = 255;
    private VcpController mVcpController;

    private BroadcastReceiver mBondStateChangedReceiver;
    private final ReentrantReadWriteLock mAcmNativeInterfaceLock = new ReentrantReadWriteLock();
    public int mCsipAppId = -1;

    private static final int SET_EBMONO_CFG = 1;
    private static final int SET_EBSTEREO_CFG = 2;
    private static final int MonoCfg_Timeout = 3000;
    private static final int StereoCfg_Timeout = 3000;
    private Handler mHandler = new Handler() {
       @Override
       public void handleMessage(Message msg)
       {
         synchronized(mBtLeaLock) {
           switch (msg.what) {
               case SET_EBMONO_CFG:
                   Log.d(TAG, "setparameters to Mono");
                   synchronized (mAudioManagerLock) {
                        if(mAudioManager != null)
                           mAudioManager.setParameters("LEAMono=true");
                   }
                   mLeaChannelMode = "mono";
                   break;
               case SET_EBSTEREO_CFG:
                   Log.d(TAG, "setparameters to stereo");
                   synchronized (mAudioManagerLock) {
                       if(mAudioManager != null)
                           mAudioManager.setParameters("LEAMono=false");
                   }
                   mLeaChannelMode = "stereo";
                   break;
              default:
                   break;
           }
         }
       }
    };

    @Override
    protected void create() {
        Log.i(TAG, "create()");
    }

    @Override
    protected boolean start() {
        Log.i(TAG, "start()");
        String propValue;

        if (sAcmService != null) {
            Log.w(TAG, "AcmService is already running");
            return true;
        }

        // Step 1: Get AdapterService, AcmNativeInterface.
        // None of them can be null.
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        mAdapterService = Objects.requireNonNull(AdapterService.getAdapterService(),
                "AdapterService cannot be null when AcmService starts");
        mAcmNativeInterface = Objects.requireNonNull(AcmNativeInterface.getInstance(),
                "AcmNativeInterface cannot be null when AcmService starts");

        mAdapterService = Objects.requireNonNull(AdapterService.getAdapterService(),
                "AdapterService cannot be null when StreamAudioService starts");

        Log.i(TAG, "mAdapterService.isHostAdvAudioUnicastFeatureSupported() returned "
                  + mAdapterService.isHostAdvAudioUnicastFeatureSupported());
        Log.i(TAG, "mAdapterService.isHostAdvAudioStereoRecordingFeatureSupported() returned "
                  + mAdapterService.isHostAdvAudioStereoRecordingFeatureSupported());
        Log.i(TAG, "mAdapterService.isAdvUnicastAudioFeatEnabled() returned "
                  + mAdapterService.isAdvUnicastAudioFeatEnabled());

        // SOC supports unicast, host supports unicast and stereo recording
        if (mAdapterService.isHostAdvAudioUnicastFeatureSupported() &&
            mAdapterService.isHostAdvAudioStereoRecordingFeatureSupported() &&
            mAdapterService.isAdvUnicastAudioFeatEnabled()) {

            Log.i(TAG, "SOC supports unicast, host supports unicast, stereo recording");
            // set properties only if they are not set to allow user enable/disable
            // the features explicitly
            propValue = SystemProperties.get("persist.vendor.service.bt.bap.enable_ucast");

            if (propValue == null || propValue.length() == 0 || !propValue.equals("false")) {
                SystemProperties.set("persist.vendor.service.bt.bap.enable_ucast", "true");
            } else {
                Log.i(TAG, "persist.vendor.service.bt.bap.enable_ucast is already set to "
                        + propValue);
            }

            propValue = SystemProperties.get("persist.vendor.service.bt.recording_supported");
            if (propValue == null || propValue.length() == 0 || !propValue.equals("false")) {
                SystemProperties.set("persist.vendor.service.bt.recording_supported", "true");
                 Log.i(TAG, "persist.vendor.service.bt.recording_supported set to true");
            } else {
                Log.i(TAG, "persist.vendor.service.bt.recording_supported is already set to "
                        + propValue);
            }
        }

        Log.i(TAG, "mAdapterService.isHostQHSFeatureSupported() returned "
                  + mAdapterService.isHostQHSFeatureSupported());

        // SOC supports unicast, host supports unicast and QHS
        if (mAdapterService.isHostAdvAudioUnicastFeatureSupported() &&
            mAdapterService.isHostQHSFeatureSupported() &&
            mAdapterService.isAdvUnicastAudioFeatEnabled()) {

            Log.i(TAG, "SOC supports unicast, host supports unicast, QHS");
            // set properties only if they are not set to allow user enable/disable
            // the features explicitly
            propValue = SystemProperties.get("persist.vendor.btstack.qhs_enable");

            if (propValue == null || propValue.length() == 0 || !propValue.equals("false")) {
                SystemProperties.set("persist.vendor.btstack.qhs_enable", "true");
            } else {
                Log.i(TAG, "persist.vendor.service.bt.bap.enable_ucast is already set to "
                        + propValue);
            }
        }

        Log.i(TAG, "isHostAdvAudioLC3QFeatureSupported(): "
                         + mAdapterService.isHostAdvAudioLC3QFeatureSupported());

        // SOC supports unicast, host supports unicast and LC3Q
        if (mAdapterService.isHostAdvAudioUnicastFeatureSupported() &&
            mAdapterService.isHostAdvAudioLC3QFeatureSupported() &&
            mAdapterService.isAdvUnicastAudioFeatEnabled()) {

            Log.i(TAG, "host supports LC3Q");
            // set properties only if they are not set to allow user enable/disable
            // the features explicitly
            propValue = SystemProperties.get("persist.vendor.service.bt.is_lc3q_supported");

            if (propValue == null || propValue.length() == 0 || !propValue.equals("false")) {
                SystemProperties.set("persist.vendor.service.bt.is_lc3q_supported", "true");
            } else {
                Log.i(TAG, "persist.vendor.service.bt.is_lc3q_supported is already set to "
                        + propValue);
            }
        }

        // Step 2: Get maximum number of connected audio devices
        mMaxConnectedAudioDevices = mAdapterService.getMaxConnectedAudioDevices();
        Log.i(TAG, "Max connected audio devices set to " + mMaxConnectedAudioDevices);


        String LeaChannelMode = SystemProperties.get("persist.vendor.btstack.Lea.defaultchannelmode");
        if (!LeaChannelMode.isEmpty() && "mono".equals(LeaChannelMode)) {
            mLeaChannelMode = "mono";
        }
        Log.d(TAG, "Default LEA ChannelMode: " + LeaChannelMode);
        // Step 3: Start handler thread for state machines
        mStateMachines.clear();
        mStateMachinesThread = new HandlerThread("AcmService.StateMachines");
        mStateMachinesThread.start();

        // Step 4: Setup codec config
        mAcmCodecConfig = new AcmCodecConfig(this, mAcmNativeInterface);

        if (mAdapterService.isAdvUnicastAudioFeatEnabled()) {
          Log.d(TAG, "Initialize AcmNativeInterface");
          // Step 5: Initialize native interface
          mAcmNativeInterface.init(mMaxConnectedAudioDevices,
                                   mAcmCodecConfig.codecConfigPriorities());
        }

        // Step 6: Setup broadcast receivers
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        mBondStateChangedReceiver = new BondStateChangedReceiver();
        registerReceiver(mBondStateChangedReceiver, filter);
        synchronized (mAudioManagerLock) {
             mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
             Objects.requireNonNull(mAudioManager,
                                "AudioManager cannot be null when AcmService starts");
             mAudioStreamMax = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        }
        // Step 7: Mark service as started
        setAcmService(this);

        //step 8: Register CSIP module
        mCsipManager = new CsipManager();

        //step 9: Get Vcp Controller
        mVcpController = VcpController.make(this);
        Objects.requireNonNull(mVcpController, "mVcpController cannot be null when AcmService starts");
        return true;
    }

    @Override
    protected boolean stop() {
        Log.i(TAG, "stop()");
        if (sAcmService == null) {
            Log.w(TAG, "stop() called before start()");
            return true;
        }

        // Step 9: do quit Vcp Controller
        if (mVcpController != null) {
            mVcpController.doQuit();
        }

        // Step 8: Mark service as stopped
        setAcmService(null);

        unregisterReceiver(mBondStateChangedReceiver);
        mBondStateChangedReceiver = null;
        // Step 6: Cleanup native interface
        mAcmNativeInterface.cleanup();
        mAcmNativeInterface = null;

        // Step 5: Clear codec config
        mAcmCodecConfig = null;

        // Step 4: Destroy state machines and stop handler thread
        synchronized (mStateMachines) {
            for (AcmStateMachine sm : mStateMachines.values()) {
                sm.doQuit();
                sm.cleanup();
            }
            mStateMachines.clear();
        }
        mStateMachinesThread.quitSafely();
        mStateMachinesThread = null;

        // Step 2: Reset maximum number of connected audio devices
        mMaxConnectedAudioDevices = 1;

        // Step 1: Clear AdapterService, AcmNativeInterface, AudioManager
        mAcmNativeInterface = null;
        mAdapterService = null;
        if (mAcmDevices != null)
            mAcmDevices.clear();

        mCsipManager.unregisterCsip();
        mCsipManager = null;
        return true;
    }

    @Override
    protected void cleanup() {
        Log.i(TAG, "cleanup()");
    }

    @Override
    protected IProfileServiceBinder initBinder() {
        return new AcmBinder(this);
    }

    private class BluetoothAcmDevice {
        private BluetoothDevice mGrpDevice; // group bd address
        private int mState;
        private int msetID;

        BluetoothAcmDevice(BluetoothDevice device, int state, int setID) {
            mGrpDevice = device;
            mState = state;
            msetID = setID;
        }
    }

    private BluetoothDevice getAddressFromString(String address) {
        return mAdapter.getRemoteDevice(address);
    }

    public BluetoothDevice makeGroupBdAddress(BluetoothDevice device, int state, int setid) {
        Log.i(TAG, " Set id : " + setid + " Num of connected acm devices: " + mAcmDevices.size());
        boolean setIdMatched = false;
        if (setid == INVALID_SET_ID) {
            Log.d(TAG, "Device is not part of any group");
            BluetoothAcmDevice acmDevice = new BluetoothAcmDevice(device, state, setid);
            mAcmDevices.put(device, acmDevice);
            mGroupBdAddress = acmDevice.mGrpDevice;
            return mGroupBdAddress;
        }
       // BluetoothDevice bdaddr = null;
        if (mAcmDevices == null) {
            Log.d(TAG, "Hash Map is NULL");
            return mGroupBdAddress;
        }
        if (mAcmDevices.containsKey(device)) {
            Log.d(TAG, "Device is available in Hash Map");
            BluetoothAcmDevice acmDevice = mAcmDevices.get(device);
            mGroupBdAddress = acmDevice.mGrpDevice;
            return mGroupBdAddress;
        }
        if (mAcmDevices.size() != 0) {
            for (BluetoothDevice dm : mAcmDevices.keySet()) {
                BluetoothAcmDevice d = mAcmDevices.get(dm);
                if (d.msetID == setid) {
                    setIdMatched = true;
                    Log.d(TAG, "Device is part of same set ID");
                    BluetoothAcmDevice acmDevice = new BluetoothAcmDevice(d.mGrpDevice, state, setid);
                    mAcmDevices.put(device, acmDevice);
                    mGroupBdAddress = acmDevice.mGrpDevice;
                    break;
                }
            }
        }
        if (!setIdMatched) {
            Log.d(TAG, "create new group or device is not part of existing set ID");
            String address = "9E:8B:00:00:00:0";
            BluetoothDevice bdaddr = getAddressFromString(address + setid);
            BluetoothAcmDevice acmDevice = new BluetoothAcmDevice(bdaddr, state, setid);
            mAcmDevices.put(device, acmDevice);
            mGroupBdAddress = bdaddr;
        }
        return mGroupBdAddress;
    }

    public void handleAcmDeviceStateChange(BluetoothDevice device, int state, int setid) {
        Log.d(TAG, "handleAcmDeviceStateChange: device: " + device + ", state: " + state
                + " Set id : " + setid);
        Log.i(TAG, " Num of connected ACM devices: " + mAcmDevices.size());
        boolean update = false;
        if (device == null || mAcmDevices.size() == 0)
            return;
        BluetoothAcmDevice acmDevice = mAcmDevices.get(device);
        //check if current active group address is same as this device group address
        if (acmDevice != null && mGroupBdAddress != acmDevice.mGrpDevice) {
            Log.d(TAG, "Inactive device is disconnected");
            update = true;
        }
        if (state == BluetoothProfile.STATE_DISCONNECTED) {
            Log.d(TAG, "Remove Device from hash map");
            mAcmDevices.remove(device);
        } else {
            acmDevice.mState = state;
            Log.d(TAG, "Update state");
        }
        for (BluetoothDevice dm : mAcmDevices.keySet()) {
            BluetoothAcmDevice d = mAcmDevices.get(dm);
            if (d.msetID == setid) {
                if (d.mState == BluetoothProfile.STATE_CONNECTED) {
                    update = true;
                    Log.d(TAG, "Atleast one member is connected");
                    break;
                }
            }
        }
        if (!update) {
            /*if (!mAcmNativeInterface.setActiveDevice(null, 0)) {//send unknown context type
                Log.w(TAG, "setActiveDevice(null): Cannot remove active device in native layer");
            }*/
        }
    }

    public static synchronized AcmService getAcmService() {
        if (sAcmService == null) {
            Log.w(TAG, "getAcmService(): service is null");
            return null;
        }
        if (!sAcmService.isAvailable()) {
            Log.w(TAG, "getAcmService(): service is not available");
            return null;
        }
        return sAcmService;
    }

    private static synchronized void setAcmService(AcmService instance) {
        if (DBG) {
            Log.d(TAG, "setAcmService(): set to: " + instance);
        }
        sAcmService = instance;
    }

    public boolean connect(BluetoothDevice device, int contextType,
                           int profileType, int preferredContext) {

        if (DBG) {
            Log.d(TAG, "connect(): " + device + " contextType: " + contextType
                    + " profileType: " + profileType + " preferredContext: " + preferredContext);
        }
        if (device.getAddress().contains("9E:8B:00:00:00")) {
            Log.d(TAG, "Connect request for group");
            byte[] addrByte = Utils.getByteAddress(device);
            int set_id = addrByte[5];
            List<BluetoothDevice> d = mCsipManager.getSetMembers(set_id);
            if (d == null) {
                Log.d(TAG, "No set member found");
                return false;
            }
            Iterator<BluetoothDevice> members = d.iterator();
            if (members != null) {
                while (members.hasNext()) {
                    BluetoothDevice addr = members.next();
                    Log.d(TAG, "connect member: " + addr);
                    synchronized (mStateMachines) {
                        if (!connectionAllowedCheckMaxDevices(addr)) {
                            // when mMaxConnectedAudioDevices is one, disconnect current device first.
                            if (mMaxConnectedAudioDevices == 1) {
                                List<BluetoothDevice> sinks = getDevicesMatchingConnectionStates(
                                        new int[] {BluetoothProfile.STATE_CONNECTED,
                                                BluetoothProfile.STATE_CONNECTING,
                                                BluetoothProfile.STATE_DISCONNECTING});
                                for (BluetoothDevice sink : sinks) {
                                    if (sink.equals(addr)) {
                                        Log.w(TAG, "Connecting to device " + addr + " : disconnect skipped");
                                        continue;
                                    }
                                    disconnect(sink, contextType);
                                }
                            } else {
                                Log.e(TAG, "Cannot connect to " + addr + " : too many connected devices");
                                return false;
                            }
                        }
                        AcmStateMachine smConnect = getOrCreateStateMachine(addr);
                        if (smConnect == null) {
                            Log.e(TAG, "Cannot connect to " + addr + " : no state machine");
                            return false;
                        }
                        Message msg = smConnect.obtainMessage(AcmStateMachine.CONNECT);
                        msg.obj = preferredContext;
                        msg.arg1 = contextType;
                        msg.arg2 = profileType;
                        smConnect.sendMessage(msg);
                    }
                }
            }
            return true;
        }
        synchronized (mStateMachines) {
            if (!connectionAllowedCheckMaxDevices(device)) {
                // when mMaxConnectedAudioDevices is one, disconnect current device first.
                if (mMaxConnectedAudioDevices == 1) {
                    List<BluetoothDevice> sinks = getDevicesMatchingConnectionStates(
                            new int[] {BluetoothProfile.STATE_CONNECTED,
                                    BluetoothProfile.STATE_CONNECTING,
                                    BluetoothProfile.STATE_DISCONNECTING});
                    for (BluetoothDevice sink : sinks) {
                        if (sink.equals(device)) {
                            Log.w(TAG, "Connecting to device " + device + " : disconnect skipped");
                            continue;
                        }
                        disconnect(sink, contextType);
                    }
                } else {
                    Log.e(TAG, "Cannot connect to " + device + " : too many connected devices");
                    return false;
                }
            }
            AcmStateMachine smConnect = getOrCreateStateMachine(device);
            if (smConnect == null) {
                Log.e(TAG, "Cannot connect to " + device + " : no state machine");
                return false;
            }
            Message msg = smConnect.obtainMessage(AcmStateMachine.CONNECT);
            msg.obj = preferredContext;
            msg.arg1 = contextType;
            msg.arg2 = profileType;
            smConnect.sendMessage(msg);
            return true;
        }
    }

    /**
     * Disconnects Acm for the remote bluetooth device
     *
     * @param device is the device with which we would like to disconnect acm
     * @return true if profile disconnected, false if device not connected over acm
     */
    public boolean disconnect(BluetoothDevice device, int contextType) {

        if (DBG) {
            Log.d(TAG, "disconnect(): " + device);
        }

        if (device.getAddress().contains("9E:8B:00:00:00")) {
            Log.d(TAG, "Disonnect request for group");
            byte[] addrByte = Utils.getByteAddress(device);
            int set_id = addrByte[5];
            List<BluetoothDevice> d = mCsipManager.getSetMembers(set_id);
            if (d == null) {
                Log.d(TAG, "No set member found");
                return false;
            }
            Iterator<BluetoothDevice> members = d.iterator();
            if (members != null) {
                while (members.hasNext()) {
                    BluetoothDevice addr = members.next();
                    Log.d(TAG, "disconnect member: " + device);
                    synchronized (mStateMachines) {
                        AcmStateMachine sm = mStateMachines.get(addr);
                        if (sm == null) {
                            Log.e(TAG, "Ignored disconnect request for " + addr + " : no state machine");
                            return false;
                        }
                        Message msg = sm.obtainMessage(AcmStateMachine.DISCONNECT);
                        msg.obj = contextType;
                        sm.sendMessage(msg);
                    }
                }
                return true;
            }
        }
        synchronized (mStateMachines) {
            AcmStateMachine sm = mStateMachines.get(device);
            if (sm == null) {
                Log.e(TAG, "Ignored disconnect request for " + device + " : no state machine");
                return false;
            }
            Message msg = sm.obtainMessage(AcmStateMachine.DISCONNECT);
            msg.obj = contextType;
            sm.sendMessage(msg);
            return true;
        }
    }

    public List<BluetoothDevice> getConnectedDevices() {

        synchronized (mStateMachines) {
            List<BluetoothDevice> devices = new ArrayList<>();
            for (AcmStateMachine sm : mStateMachines.values()) {
                if (sm.isConnected()) {
                    devices.add(sm.getDevice());
                }
            }
            return devices;
        }
    }

    //check if it can be a list ?
    public BluetoothDevice getCsipLockRequestedDevice() {

        synchronized (mStateMachines) {
            BluetoothDevice device = null;
            for (AcmStateMachine sm : mStateMachines.values()) {
                if (sm.isCsipLockRequested()) {
                    device = sm.getDevice();
                }
            }
            return device;
        }
    }

    public boolean IsLockSupportAvailable(BluetoothDevice device) {
        boolean isLockSupported = false;
        /*int setId = mSetCoordinator.getRemoteSetId(device, ACM_UUID);
        DeviceGroup set = mSetCoordinator.getDeviceGroup(setId);
        isLockSupported = set.mLockSupport;*/
        //isLockSupported = mAdapterService.isCsipLockSupport(device);
        Log.d(TAG, "Exclusive Access SupportAvaible for:" + device + "returns " + isLockSupported);
        return isLockSupported;
    }

    /**
     * Check whether can connect to a peer device.
     * The check considers the maximum number of connected peers.
     *
     * @param device the peer device to connect to
     * @return true if connection is allowed, otherwise false
     */
    private boolean connectionAllowedCheckMaxDevices(BluetoothDevice device) {
        int connected = 0;
        // Count devices that are in the process of connecting or already connected
        synchronized (mStateMachines) {
            for (AcmStateMachine sm : mStateMachines.values()) {
                switch (sm.getConnectionState()) {
                    case BluetoothProfile.STATE_CONNECTING:
                    case BluetoothProfile.STATE_CONNECTED:
                        if (Objects.equals(device, sm.getDevice())) {
                            return true;    // Already connected or accounted for
                        }
                        connected++;
                        break;
                    default:
                        break;
                }
            }
        }
        return (connected < mMaxConnectedAudioDevices);
    }

    List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {

        List<BluetoothDevice> devices = new ArrayList<>();
        if (states == null) {
            return devices;
        }
        final BluetoothDevice[] bondedDevices = mAdapterService.getBondedDevices();
        if (bondedDevices == null) {
            return devices;
        }
        synchronized (mStateMachines) {
            for (BluetoothDevice device : bondedDevices) {
                /*if (!ArrayUtils.contains(mAdapterService.getRemoteUuids(device),
                                                 BluetoothUuid.ACM_SINK)) {
                    continue;
                }*/
                int connectionState = BluetoothProfile.STATE_DISCONNECTED;
                AcmStateMachine sm = mStateMachines.get(device);
                if (sm != null) {
                    connectionState = sm.getConnectionState();
                }
                for (int state : states) {
                    if (connectionState == state) {
                        devices.add(device);
                        break;
                    }
                }
            }
            return devices;
        }
    }

    /**
     * Get the list of devices that have state machines.
     *
     * @return the list of devices that have state machines
     */
    @VisibleForTesting
    List<BluetoothDevice> getDevices() {
        List<BluetoothDevice> devices = new ArrayList<>();
        synchronized (mStateMachines) {
            for (AcmStateMachine sm : mStateMachines.values()) {
                devices.add(sm.getDevice());
            }
            return devices;
        }
    }

    public int getConnectionState(BluetoothDevice device) {

        synchronized (mStateMachines) {
            AcmStateMachine sm = mStateMachines.get(device);
            if (sm == null) {
                return BluetoothProfile.STATE_DISCONNECTED;
            }
            return sm.getConnectionState();
        }
    }

    public int getCsipConnectionState(BluetoothDevice device) {

        synchronized (mStateMachines) {
            AcmStateMachine sm = mStateMachines.get(device);
            if (sm == null) {
                return BluetoothProfile.STATE_DISCONNECTED;
            }
            return sm.getCsipConnectionState();
        }
    }

    // Handle messages from native (JNI) to Java
    void messageFromNative(AcmStackEvent stackEvent) {
        Objects.requireNonNull(stackEvent.device,
                               "Device should never be null, event: " + stackEvent);
        synchronized (mStateMachines) {
            BluetoothDevice device = stackEvent.device;
            AcmStateMachine sm = mStateMachines.get(device);
            if (sm == null) {
                if (stackEvent.type == AcmStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED) {
                    switch (stackEvent.valueInt1) {
                        case AcmStackEvent.CONNECTION_STATE_CONNECTED:
                        case AcmStackEvent.CONNECTION_STATE_CONNECTING:
                            // Create a new state machine only when connecting to a device
                            if (!connectionAllowedCheckMaxDevices(device)) {
                                Log.e(TAG, "Cannot connect to " + device
                                        + " : too many connected devices");
                                return;
                            }
                            sm = getOrCreateStateMachine(device);
                            break;
                        default:
                            break;
                    }
                }
            }
            if (sm == null) {
                Log.e(TAG, "Cannot process stack event: no state machine: " + stackEvent);
                return;
            }
            sm.sendMessage(AcmStateMachine.STACK_EVENT, stackEvent);
        }
    }

    private AcmStateMachine getOrCreateStateMachine(BluetoothDevice device) {
        if (device == null) {
            Log.e(TAG, "getOrCreateStateMachine failed: device cannot be null");
            return null;
        }
        synchronized (mStateMachines) {
            AcmStateMachine sm = mStateMachines.get(device);
            if (sm != null) {
                return sm;
            }
            // Limit the maximum number of state machines to avoid DoS attack
            if (mStateMachines.size() >= MAX_ACM_STATE_MACHINES) {
                Log.e(TAG, "Maximum number of ACM state machines reached: "
                        + MAX_ACM_STATE_MACHINES);
                return null;
            }
            if (DBG) {
                Log.d(TAG, "Creating a new state machine for " + device);
            }
            sm = AcmStateMachine.make(device, this, mAcmNativeInterface,
                                      mStateMachinesThread.getLooper());
            mStateMachines.put(device, sm);
            return sm;
        }
    }

    private class BondStateChangedReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (!BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(intent.getAction())) {
                return;
            }
            int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
                                           BluetoothDevice.ERROR);
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            Objects.requireNonNull(device, "ACTION_BOND_STATE_CHANGED with no EXTRA_DEVICE");
            bondStateChanged(device, state);
        }
    }

    /**
     * Process a change in the bonding state for a device.
     *
     * @param device the device whose bonding state has changed
     * @param bondState the new bond state for the device. Possible values are:
     * {@link BluetoothDevice#BOND_NONE},
     * {@link BluetoothDevice#BOND_BONDING},
     * {@link BluetoothDevice#BOND_BONDED}.
     */
    @VisibleForTesting
    void bondStateChanged(BluetoothDevice device, int bondState) {
        if (DBG) {
            Log.d(TAG, "Bond state changed for device: " + device + " state: " + bondState);
        }
        // Remove state machine if the bonding for a device is removed
        if (bondState != BluetoothDevice.BOND_NONE) {
            return;
        }
        synchronized (mStateMachines) {
            AcmStateMachine sm = mStateMachines.get(device);
            if (sm == null) {
                return;
            }
            if (sm.getConnectionState() != BluetoothProfile.STATE_DISCONNECTED) {
                return;
            }
        }
        removeStateMachine(device);
    }

    private void removeStateMachine(BluetoothDevice device) {
        synchronized (mStateMachines) {
            AcmStateMachine sm = mStateMachines.get(device);
            if (sm == null) {
                Log.w(TAG, "removeStateMachine: device " + device
                        + " does not have a state machine");
                return;
            }
            Log.i(TAG, "removeStateMachine: removing state machine for device: " + device);
            sm.doQuit();
            sm.cleanup();
            mStateMachines.remove(device);
            mAcmDevices.remove(device);
        }
    }

    void updateLeaChannelMode(int state, BluetoothDevice device) {
        BluetoothDevice peerLeaDevice = null;
        peerLeaDevice = getLeaPeerDevice(device);
        if (peerLeaDevice == null) {
            Log.d(TAG, "updateLeaChannelMode: peer device is NULL");
            return;
        }
        Log.d(TAG, "LeaChannelMode: " + mLeaChannelMode + "state: " + state);
        synchronized(mBtLeaLock) {
            if ("mono".equals(mLeaChannelMode)) {
                if ((state == BluetoothA2dp.STATE_PLAYING) && (peerLeaDevice!= null)
                     && peerLeaDevice.isConnected() && isAcmPlayingMusic(peerLeaDevice)) {
                    Log.d(TAG, "updateLeaChannelMode: send delay message to set stereo ");
                    Message msg = mHandler.obtainMessage(SET_EBSTEREO_CFG);
                    mHandler.sendMessageDelayed(msg, StereoCfg_Timeout);
                } else if (state == BluetoothA2dp.STATE_PLAYING) {
                    Log.d(TAG, "updateLeaChannelMode: setparameters to Mono");
                    synchronized (mAudioManagerLock) {
                        if (mAudioManager != null) {
                            Log.d(TAG, "updateLeaChannelMode: Acquired mVariableLock");
                            mAudioManager.setParameters("LeaChannelConfig=mono");
                        }
                    }
                    Log.d(TAG, "updateLeaChannelMode: Released mVariableLock");
                }
                if ((state == BluetoothA2dp.STATE_NOT_PLAYING) &&
                       isAcmPlayingMusic(peerLeaDevice)) {
                    if (mHandler.hasMessages(StereoCfg_Timeout)) {
                        Log.d(TAG, "updateLeaChannelMode:remove delay message for stereo");
                        mHandler.removeMessages(StereoCfg_Timeout);
                    }
                }
            } else if ("stereo".equals(mLeaChannelMode)) {
                if ((state == BluetoothA2dp.STATE_PLAYING) &&
                     (getConnectionState(peerLeaDevice) != BluetoothProfile.STATE_CONNECTED
                     || !isAcmPlayingMusic(peerLeaDevice))) {
                    Log.d(TAG, "updateLeaChannelMode: send delay message to set mono");
                    Message msg = mHandler.obtainMessage(SET_EBMONO_CFG);
                    mHandler.sendMessageDelayed(msg, MonoCfg_Timeout);
                }
                if ((state == BluetoothA2dp.STATE_PLAYING) && isAcmPlayingMusic(peerLeaDevice)) {
                    if (mHandler.hasMessages(SET_EBMONO_CFG)) {
                        Log.d(TAG, "updateLeaChannelMode: remove delay message to set mono");
                        mHandler.removeMessages(SET_EBMONO_CFG);
                    }
                }
                if ((state == BluetoothA2dp.STATE_NOT_PLAYING) && isAcmPlayingMusic(peerLeaDevice)) {
                    Log.d(TAG, "setparameters to Mono");
                    synchronized (mAudioManagerLock) {
                        if (mAudioManager != null)
                            mAudioManager.setParameters("LeaChannelConfig=mono");
                    }
                    mLeaChannelMode = "mono";
                }
            }
        }
    }

    private BluetoothDevice getLeaPeerDevice(BluetoothDevice device) {
        synchronized (mStateMachines) {
            AcmStateMachine sm = mStateMachines.get(device);
            if (sm == null) {
                return null;
            }
            return sm.getPeerDevice();
        }
    }

    public boolean isPeerDeviceConnected(BluetoothDevice device, int setid) {
        boolean isConnected = false;
        if (mAcmDevices.size() != 0) {
            for (BluetoothDevice dm : mAcmDevices.keySet()) {
                BluetoothAcmDevice d = mAcmDevices.get(dm);
                if ((d.msetID == setid) && !Objects.equals(dm, device)) {
                    if (d.mState == BluetoothProfile.STATE_CONNECTED) {
                        isConnected = true;
                        Log.d(TAG, "At least one member is in connected state");
                        break;
                    }
                }
            }
        }
        return isConnected;
    }

    public boolean isPeerDeviceStreamingMusic(BluetoothDevice device, int setid) {
        boolean isStreaming = false;
        if (mAcmDevices.size() != 0) {
            for (BluetoothDevice dm : mAcmDevices.keySet()) {
                BluetoothAcmDevice d = mAcmDevices.get(dm);
                if ((d.msetID == setid) && !Objects.equals(dm, device)) {
                    if (d.mState == BluetoothProfile.STATE_CONNECTED) {
                        synchronized (mBtAcmLock) {
                            AcmStateMachine sm = mStateMachines.get(dm);
                            if (sm == null) {
                                return false;
                            }
                            if (sm.isMusicPlaying()) {
                                isStreaming = true;
                                Log.d(TAG, "At least one member is streaming for music");
                                break;
                            }
                        }
                    }
                }
            }
        }
        return isStreaming;
    }

    public boolean isShoPendingStop() {
        Log.d(TAG, "isShoPendingStop " + mShoPend);
        return mShoPend;
    }

    public void resetShoPendingStop() {
        mShoPend = false;
    }

    public boolean isVoiceShoPendingStop() {
        Log.d(TAG, "isVoiceShoPendingStop " + mVoiceShoPend);
        return mVoiceShoPend;
    }

    public void resetVoiceShoPendingStop() {
        mVoiceShoPend = false;
    }

    public BluetoothDevice getVoiceActiveDevice() {
        return mActiveDeviceVoice;
    }

    public void removePeersFromBgWl(BluetoothDevice device, int setid) {
        synchronized (mStateMachines) {
            BluetoothDevice d = null;
            List<BluetoothDevice> members = mCsipManager.getSetMembers(setid);
            if (members == null) {
                Log.d(TAG, "No set member found");
                return;
            }
            Iterator<BluetoothDevice> i = members.iterator();
            if (i != null) {
                while (i.hasNext()) {
                    d = i.next();
                    if (!(Objects.equals(d, device))) {
                        Log.d(TAG, "Device: " + d);
                        AcmStateMachine sm = mStateMachines.get(d);
                        if (sm == null) {
                            return;
                        }
                        sm.removeDevicefromBgWL();
                    }
                }
            }
        }
    }

    public boolean isAcmPlayingMusic(BluetoothDevice device) {
        if (DBG) {
            Log.d(TAG, "isAcmPlayingMusic(" + device + ")");
        }
        synchronized (mBtAcmLock) {
            AcmStateMachine sm = mStateMachines.get(device);
            if (sm == null) {
                return false;
            }
            return sm.isMusicPlaying();
        }
    }

    public boolean isAcmPlayingVoice(BluetoothDevice device) {
        if (DBG) {
            Log.d(TAG, "isAcmPlayingVoice(" + device + ")");
        }
        synchronized (mBtAcmLock) {
            AcmStateMachine sm = mStateMachines.get(device);
            if (sm == null) {
                return false;
            }
            return sm.isVoicePlaying();
        }
    }

    public BluetoothDevice getGroup(BluetoothDevice device) {
        Log.d(TAG, "Get group address for (" + device + ")");
        if (device.getAddress().contains("9E:8B:00:00:00")) {
            Log.d(TAG, "Called for group address");
            return device;
        }
        BluetoothDevice dm = null;

        if (mAcmDevices != null) {
            Log.d(TAG, "Hash Map is not NULL");
            BluetoothAcmDevice d = mAcmDevices.get(device);
            if (d != null)
                dm = d.mGrpDevice;
        }
        if (dm == null) {
            Log.d(TAG, "Group address is NULL, make New");
            int Id = mCsipManager.getCsipSetId(device, null /*ACM_UUID*/); //TODO: UUID what to set ?
            dm = makeGroupBdAddress(device, BluetoothProfile.STATE_DISCONNECTED, Id);
        }
        return dm;
    }

    public int setActiveDevice(BluetoothDevice device, int contextType, int profileType, boolean playReq) {

        Log.d(TAG, "setActiveDevice: " + device + " contextType: " + contextType + " profileType: " + profileType +
                " play req: " + playReq + " mActiveDeviceProfile: " + mActiveDeviceProfile+ " mActiveDeviceVoiceProfile: " + mActiveDeviceVoiceProfile);

        if (Objects.equals(device, mActiveDevice) && contextType == CONTEXT_TYPE_MUSIC && (mActiveDeviceProfile == profileType)) {
            Log.e(TAG, "setActiveDevice(" + device + "): already set to active for media and profileType same as active profile");
            return ActiveDeviceManagerService.ALREADY_ACTIVE;
        }
        if (Objects.equals(device, mActiveDeviceVoice) && contextType == CONTEXT_TYPE_VOICE && (mActiveDeviceVoiceProfile == profileType)) {
            Log.e(TAG, "setActiveDevice(" + device + "): already set to active for voice and profileType same as active profile");
            return ActiveDeviceManagerService.ALREADY_ACTIVE;
        }
        if (contextType == CONTEXT_TYPE_MUSIC) {
            mShoPend = false;
            if ((device == null) && (mActiveDevice != null)) {
                if (mActiveDevice.getAddress().contains("9E:8B:00:00:00")) {
                    byte[] addrByte = Utils.getByteAddress(mActiveDevice);
                    int set_id = addrByte[5];
                    List<BluetoothDevice> members = mCsipManager.getSetMembers(set_id);
                    if (members == null) {
                        Log.d(TAG, "No set member found");
                    }
                    Iterator<BluetoothDevice> i = members.iterator();
                    if (i != null) {
                        while (i.hasNext()) {
                            BluetoothDevice addr = i.next();
                            Log.d(TAG, "isAcmPlayingMusic(addr) " + isAcmPlayingMusic(addr));
                            if (isAcmPlayingMusic(addr)) {
                                mShoPend = true;
                                break;
                            }
                        }
                    }
                } else {
                    Log.d(TAG, "TWM active device");
                    mShoPend = isAcmPlayingMusic(mActiveDevice);
                }
            }
            Log.d(TAG, "mShoPend " + mShoPend);
        } else if (contextType == CONTEXT_TYPE_VOICE) {
            mVoiceShoPend = false;
            if (mActiveDeviceVoice != null) {
                if (mActiveDeviceVoice.getAddress().contains("9E:8B:00:00:00")) {
                    byte[] addrByte = Utils.getByteAddress(mActiveDeviceVoice);
                    int set_id = addrByte[5];
                    List<BluetoothDevice> members = mCsipManager.getSetMembers(set_id);
                    if (members == null) {
                        Log.d(TAG, "No set member found");
                    }
                    Iterator<BluetoothDevice> i = members.iterator();
                    if (i != null) {
                        while (i.hasNext()) {
                            BluetoothDevice addr = i.next();
                            Log.d(TAG, "isAcmPlayingVoice(addr) " + isAcmPlayingVoice(addr));
                            if (isAcmPlayingVoice(addr)) {
                                mVoiceShoPend = true;
                                break;
                            }
                        }
                    }
                } else {
                    Log.d(TAG, "TWM active device");
                    mVoiceShoPend = isAcmPlayingVoice(mActiveDeviceVoice);
                }
            }
            Log.d(TAG, "mVoiceShoPend " + mVoiceShoPend);
        }
        Log.d(TAG, "old mActiveDevice: " + mActiveDevice + " & old mActiveDeviceVoice: " + mActiveDeviceVoice);

        if (setActiveDeviceAcm(device, contextType, profileType)) {
            if (contextType == CONTEXT_TYPE_MUSIC) {
              mActiveDevice = device;
              mActiveDeviceProfile = profileType;
            } else if (contextType == CONTEXT_TYPE_VOICE) {
              mActiveDeviceVoice = device;
              mActiveDeviceVoiceProfile = profileType;
            }
            Log.d(TAG, "new mActiveDevice: " + mActiveDevice + " & new mActiveDeviceVoice: " + mActiveDeviceVoice);
            if(!playReq) {
               if (mShoPend || mVoiceShoPend) {
                   Log.d(TAG, "setActiveDevice(" + device + "): returns with status " + ActiveDeviceManagerService.SHO_PENDING);
                   return ActiveDeviceManagerService.SHO_PENDING;
               } else {
                   Log.d(TAG, "setActiveDevice(" + device + "): returns with status " + ActiveDeviceManagerService.SHO_SUCCESS);
                   return ActiveDeviceManagerService.SHO_SUCCESS;
               }
            } else {
                Log.d(TAG, "setActiveDevice(" + device + "): returns with status " + ActiveDeviceManagerService.SHO_PENDING);
                return ActiveDeviceManagerService.SHO_PENDING;
            }
        }
        Log.d(TAG, "setActiveDevice(" + device + "): returns with status " + ActiveDeviceManagerService.SHO_FAILED);
        mShoPend = false;
        mVoiceShoPend = false;
        return ActiveDeviceManagerService.SHO_FAILED;
    }

    private boolean setActiveDeviceAcm(BluetoothDevice device, int contextType, int profileType) {
        Log.d(TAG, "setActiveDeviceAcm: " + device);
        try {
            mAcmNativeInterfaceLock.readLock().lock();
            if (mAcmNativeInterface != null && !mAcmNativeInterface.setActiveDevice(device, profileType)) {
              Log.e(TAG, "setActiveDevice(" + device + "): Cannot set as active in native layer");
              return false;
            }
        } finally {
            mAcmNativeInterfaceLock.readLock().unlock();
        }
        Log.d(TAG, "setActiveDeviceAcm(" + device + "): returns true");
        return true;
    }

    public void setCodecConfigPreference(BluetoothDevice device,
                                          BluetoothCodecConfig codecConfig, int contextType) {

        if (DBG) {
            Log.d(TAG, "setCodecConfigPreference(" + device + "): "
                    + Objects.toString(codecConfig));
        }
        mAcmCodecConfig.setCodecConfigPreference(device, codecConfig, contextType);
    }

    public void ChangeCodecConfigPreference(BluetoothDevice device,
                                            String mesg) {

        if (DBG) {
            Log.d(TAG, "ChangeCodecConfigPreference " + device + "string: " + mesg);
        }
        if (device == null)
            return;
        mAcmName = mesg;
        synchronized (mStateMachines) {
            if (mAcmDevices.size() != 0) {
                for (BluetoothDevice dm : mAcmDevices.keySet()) {
                    BluetoothAcmDevice d = mAcmDevices.get(dm);
                    if (Objects.equals(device, d.mGrpDevice)) {
                        if (d.mState == BluetoothProfile.STATE_CONNECTED) {
                            AcmStateMachine sm = getOrCreateStateMachine(dm);
                            if (sm == null) {
                                //TODO:handle this case
                                continue;
                            }
                            Message msg = sm.obtainMessage(AcmStateMachine.CODEC_CONFIG_CHANGED);
                            msg.obj = d.msetID;
                            sm.sendMessage(msg);
                        }
                    }
                }
            }
        }
    }

    public boolean StartStream(BluetoothDevice device, int contextType) {
        if (DBG) {
            Log.d(TAG, "startStream for " + device+ " context type: " + contextType);
        }
        if (device == null)
            return false;
        synchronized (mStateMachines) {
            if (mAcmDevices.size() != 0) {
                for (BluetoothDevice dm : mAcmDevices.keySet()) {
                    BluetoothAcmDevice d = mAcmDevices.get(dm);
                    if (Objects.equals(device, d.mGrpDevice)) {
                        if (d.mState == BluetoothProfile.STATE_CONNECTED) {
                            AcmStateMachine sm = getOrCreateStateMachine(dm);
                            if (sm == null) {
                                //TODO:handle this case
                                continue;
                            }
                            Message msg = sm.obtainMessage(AcmStateMachine.START_STREAM);
                            msg.obj = contextType;
                            sm.sendMessage(msg);
                        }
                    }
                }
            }
        }
        return true;
    }

    public boolean StopStream(BluetoothDevice device, int contextType) {
        if (DBG) {
            Log.d(TAG, "stopStream for " + device+ " context type: " + contextType);
        }
        if (device == null)
            return false;
        synchronized (mStateMachines) {
            if (mAcmDevices.size() != 0) {
                for (BluetoothDevice dm : mAcmDevices.keySet()) {
                    BluetoothAcmDevice d = mAcmDevices.get(dm);
                    if (Objects.equals(device, d.mGrpDevice)) {
                        if (d.mState == BluetoothProfile.STATE_CONNECTED) {
                            AcmStateMachine sm = getOrCreateStateMachine(dm);
                            if (sm == null) {
                                //TODO:handle this case
                                continue;
                            }
                            Message msg = sm.obtainMessage(AcmStateMachine.STOP_STREAM);
                            msg.obj = contextType;
                            sm.sendMessage(msg);
                        }
                    }
                }
            }
        }
        return true;
    }

    public void setAbsoluteVolume(BluetoothDevice grpAddr, int volumeLevel, int audioType) {
        //Convert volume level to VCP level before sending.
        int vcpVolume = convertToVcpVolume(volumeLevel);
        BluetoothDevice activeDevice = null;
        Log.d(TAG, "AudioVolumeLevel " + volumeLevel + " vcpVolume "  + vcpVolume);

        if (audioType == ApmConst.AudioFeatures.MEDIA_AUDIO ||
                audioType == ApmConst.AudioFeatures.CALL_AUDIO) {
            ActiveDeviceManagerService activeDeviceManager =
                    ActiveDeviceManagerService.get(this);
            activeDevice = activeDeviceManager.getActiveDevice(audioType);
            Log.d(TAG, "activeDevice " + activeDevice + " grpAddr "  + grpAddr
                    + " audioType " + audioType);
            if (!grpAddr.equals(activeDevice)) {
                Log.e(TAG, "Ignore setAbsoluteVolume for inactive device");
                return;
            }
        } else if (audioType == ApmConst.AudioFeatures.BROADCAST_AUDIO) {
            Log.d(TAG, "No active device, grpAddr " + grpAddr + " is broadcast device or group");
        } else {
            Log.e(TAG, "Invalid audio type for set volume, ignore this request");
            return;
        }

        if (audioType == ApmConst.AudioFeatures.MEDIA_AUDIO) {
            mActiveDeviceLocalMediaVol = volumeLevel;
        } else if (audioType == ApmConst.AudioFeatures.CALL_AUDIO) {
            mActiveDeviceLocalVoiceVol = volumeLevel;
        }

        if (grpAddr.getAddress().contains("9E:8B:00:00:00")) {
            Log.d(TAG, "setAbsoluteVolume for group addr, send abs vol to all members");
            byte[] addrByte = Utils.getByteAddress(grpAddr);
            int set_id = addrByte[5];
            List<BluetoothDevice> members = mCsipManager.getSetMembers(set_id);
            if (members == null) {
                Log.d(TAG, "No set member found");
                return;
            }
            Iterator<BluetoothDevice> i = members.iterator();
            if (i != null) {
              while (i.hasNext()) {
                BluetoothDevice addr = i.next();
                Log.d(TAG, "send vol to member: " + addr);
                mVcpController.setAbsoluteVolume(addr, vcpVolume, audioType);
              }
            }
        } else {
            Log.d(TAG, "setAbsoluteVolume for single addr, send abs vol to " + grpAddr);
            mVcpController.setAbsoluteVolume(grpAddr, vcpVolume, audioType);
        }
    }

    public void setMute(BluetoothDevice grpAddr, boolean enableMute) {
        if (mActiveDevice == null) {
            Log.d(TAG, "No active device set, this grpAddr " + grpAddr + " is broadcast group");
        } else {
            Log.d(TAG, "mActiveDevice " + mActiveDevice + " grpAddr "  + grpAddr);
        }

        if (grpAddr.getAddress().contains("9E:8B:00:00:00")) {
            Log.d(TAG, "setMute for group addr, send mute/unmute to all members");
            byte[] addrByte = Utils.getByteAddress(grpAddr);
            int set_id = addrByte[5];
            List<BluetoothDevice> members = mCsipManager.getSetMembers(set_id);
            if (members == null) {
                Log.d(TAG, "No set member found");
                return;
            }
            Iterator<BluetoothDevice> i = members.iterator();
            if (i != null) {
              while (i.hasNext()) {
                BluetoothDevice addr = i.next();
                Log.d(TAG, "send setMute to member: " + addr);
                mVcpController.setMute(addr, enableMute);
              }
            }
        } else {
            Log.d(TAG, "setMute for single addr, send mute/unmute to " + grpAddr);
            mVcpController.setMute(grpAddr, enableMute);
        }
    }

    public void onVolumeStateChanged(BluetoothDevice device, int vol, int audioType) {
        VolumeManager service = VolumeManager.get();
        //Get or Make group address
        BluetoothDevice grpDev = getGroup(device);

        if (audioType == ApmConst.AudioFeatures.BROADCAST_AUDIO) {
            Log.d(TAG, "volume notification for Broadcast audio");
        } else if (audioType == ApmConst.AudioFeatures.MEDIA_AUDIO) {
            Log.d(TAG, "volume notification for Media audio");
        } else if (audioType == ApmConst.AudioFeatures.CALL_AUDIO) {
            Log.d(TAG, "volume notification for Call audio");
        } else {
            // remote volume change case
            Log.d(TAG, "Volume change from remote: " + device +  " vcp vol " + vol);
            audioType = service.getActiveAudioType(device);
        }

        //Convert vol
        int audioVolume = convertToAudioStreamVolume(vol);
        Log.d(TAG, "vcp vol " + vol + " audioVolume " + audioVolume);

        if (audioType == ApmConst.AudioFeatures.BROADCAST_AUDIO) {
            Log.d(TAG, "update volume to APM for Broadcast audio");
            service.onVolumeChange(grpDev, audioVolume, audioType);
        } else if (audioType == ApmConst.AudioFeatures.MEDIA_AUDIO) {
            //Check if new vol is diff than active group vol
            Log.d(TAG, "new vol: " + audioVolume + " mActiveDeviceLocalMediaVol: " + mActiveDeviceLocalMediaVol);
            if (mActiveDeviceLocalMediaVol != audioVolume) {
                Log.d(TAG, "new vol is different than mActiveDeviceLocalMediaVol update APM");
                service.onVolumeChange(grpDev, audioVolume, audioType);
                mActiveDeviceLocalMediaVol = audioVolume;
            } else {
                Log.d(TAG, "local active media vol same as device new vol, ignore sending to APM");
            }
        } else if (audioType == ApmConst.AudioFeatures.CALL_AUDIO) {
            Log.d(TAG, "new vol: " + audioVolume + " mActiveDeviceLocalVoiceVol: " + mActiveDeviceLocalVoiceVol);
            if (mActiveDeviceLocalVoiceVol != audioVolume) {
                Log.d(TAG, "new vol is different than mActiveDeviceLocalVoiceVol update APM");
                service.onVolumeChange(grpDev, audioVolume, audioType);
                mActiveDeviceLocalVoiceVol = audioVolume;
            } else {
                Log.d(TAG, "local active call vol same as device new vol, ignore sending to APM");
            }
        } else {
            Log.d(TAG, "No audio is streaming and is inactive device, ignore sending to APM");
        }

        //Check if this device is group device, then take lock (ignored for now) and update vol to other members as well.
        applyVolToOtherMembers(device, mCsipManager.getCsipSetId(device, null /*ACM_UUID*/), vol, audioType);
    }

    public void onMuteStatusChanged(BluetoothDevice device, boolean isMuted) {
        VolumeManager service = VolumeManager.get();
        //Get or Make group address
        BluetoothDevice grpDev = getGroup(device);
        //default context type
        int c_type = CONTEXT_TYPE_UNKNOWN;

        Log.d(TAG, "isMuted " + isMuted + " mActiveDeviceIsMuted " + mActiveDeviceIsMuted);

        if (!mVcpController.isBroadcastDevice(device) && ((mActiveDevice == null) || (mActiveDevice != grpDev))) {
            Log.d(TAG, "unicast-mode, either Active device null or muteStatus changed for inactive device -- return");
            return;
        }

        if ((mActiveDevice == null) || (mActiveDevice != grpDev)) {
            Log.d(TAG, "No Active device or device is not active, seems in Broadcast mode");
            c_type = CONTEXT_TYPE_BROADCAST_AUDIO;
        } else {
            Log.d(TAG, "mActiveDevice " + mActiveDevice + " grpDev "  + grpDev + " device " + device);
            c_type = CONTEXT_TYPE_MUSIC;
        }

        //Check if new mute state is diff than active group mute state
        if (mActiveDeviceIsMuted != isMuted) {
            Log.d(TAG, "new mute state is different than mActiveDeviceIsMuted update APM");
            service.onMuteStatusChange(grpDev, isMuted, CONTEXT_TYPE_MUSIC);
            mActiveDeviceIsMuted = isMuted;
        } else {
            Log.d(TAG, "local active device mute state same as device new mute state, ignore sending to APM, but send to other members");
        }

        //Check if this device is group device, then take lock(ignored for now) and update mute state to other members as well.
        applyMuteStateToOtherMembers(device, mCsipManager.getCsipSetId(device, null /*ACM_UUID*/), isMuted);
    }

    public void setAbsVolSupport(BluetoothDevice device, boolean isAbsVolSupported, int initialVol) {
        VolumeManager service = VolumeManager.get();
        //Get or Make group address
        BluetoothDevice grpDev = getGroup(device);
        if (grpDev == null) {
            Log.d(TAG, "Group not created, return");
            return;
        }
        if ((mVcpController.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED) && isAbsVolSupported) {
            if (!isVcpPeerDeviceConnected(device, mCsipManager.getCsipSetId(device, null /*ACM_UUID*/))) {
                Log.d(TAG, "VCP Peer device not connected, this is 1st member, update support to APM ");
                //get current vol from VCP and send to APM during connection.
                Log.d(TAG, "VCP initialVol " + initialVol + " when connected device " + device);
                Log.d(TAG, "Update APM with connection vol " + convertToAudioStreamVolume(initialVol));
                service.setAbsoluteVolumeSupport(grpDev, isAbsVolSupported, convertToAudioStreamVolume(initialVol), ApmConst.AudioProfiles.VCP);

                //get current mute state from VCP and sent to APM during connection.
                Log.d(TAG, "VCP mute state " + mVcpController.isMute(device) + " when connected device " + device);
                service.onMuteStatusChange(grpDev, mVcpController.isMute(device), CONTEXT_TYPE_MUSIC);
            } else {
                Log.d(TAG, "VCP Peer device connected, this is not 1st member, skip update to APM");
            }
        } else if ((mVcpController.getConnectionState(device) == BluetoothProfile.STATE_DISCONNECTED) && !isAbsVolSupported) {
            if (isVcpPeerDeviceConnected(device, mCsipManager.getCsipSetId(device, null /*ACM_UUID*/))) {
                Log.d(TAG, "VCP Peer device connected, this is not last member, skip update to APM ");
            } else {
                Log.d(TAG, "VCP Peer device not connected, this is last member, update to APM");
                service.setAbsoluteVolumeSupport(grpDev, isAbsVolSupported, ApmConst.AudioProfiles.VCP);
            }
        }
    }

    public boolean isVcpPeerDeviceConnected(BluetoothDevice device, int setid) {
      boolean isVcpPeerConnected = false;
      if (setid == INVALID_SET_ID)
          return isVcpPeerConnected;
      List<BluetoothDevice> members = mCsipManager.getSetMembers(setid);
      if (members == null) {
          Log.d(TAG, "No set member found");
          return isVcpPeerConnected;
      }
      Iterator<BluetoothDevice> i = members.iterator();
      if (i != null) {
          while (i.hasNext()) {
              BluetoothDevice addr = i.next();
              if (!Objects.equals(addr, device) && (mVcpController.getConnectionState(addr) == BluetoothProfile.STATE_CONNECTED)) {
                  isVcpPeerConnected = true;
                  Log.d(TAG, "At least one other vcp member is in connected state");
                  break;
              }
          }
      }
      return isVcpPeerConnected;
    }

    private int convertToAudioStreamVolume(int volume) {
        // Rescale volume to match AudioSystem's volume
        return (int) Math.round((double) volume * mAudioStreamMax / VCP_MAX_VOL);
    }

    private int convertToVcpVolume(int volume) {
        return (int) Math.ceil((double) volume * VCP_MAX_VOL / mAudioStreamMax);
    }

    private void applyVolToOtherMembers(BluetoothDevice device, int setid, int volume, int audioType) {
        if (setid == INVALID_SET_ID)
            return;
        List<BluetoothDevice> members = mCsipManager.getSetMembers(setid);
        if (members == null) {
            Log.d(TAG, "No set member found");
            return;
        }
        Iterator<BluetoothDevice> i = members.iterator();
        if (i != null) {
            while (i.hasNext()) {
                BluetoothDevice addr = i.next();
                if (!Objects.equals(addr, device)) {
                    Log.d(TAG, "send vol changed to addr " + addr);
                    mVcpController.setAbsoluteVolume(addr, volume, audioType);
                }
            }
        }
    }

    private void applyMuteStateToOtherMembers(BluetoothDevice device, int setid, boolean muteState) {
        if (setid == INVALID_SET_ID)
            return;
        List<BluetoothDevice> members = mCsipManager.getSetMembers(setid);
        if (members == null) {
            Log.d(TAG, "No set member found");
            return;
        }
        Iterator<BluetoothDevice> i = members.iterator();
        if (i != null) {
            while (i.hasNext()) {
                BluetoothDevice addr = i.next();
                if (!Objects.equals(addr, device)) {
                    Log.d(TAG, "send mute state to addr " + addr);
                    mVcpController.setMute(addr, muteState);
                }
            }
        }
    }

    public int getVcpConnState(BluetoothDevice device) {
        return mVcpController.getConnectionState(device);
    }

    public int getVcpConnMode(BluetoothDevice device) {
        return mVcpController.getConnectionMode(device);
    }

    public boolean isVcpMute(BluetoothDevice device) {
        return mVcpController.isMute(device);
    }

    public String getAcmName() {
        return mAcmName;
    }

    private static class AcmBinder extends Binder implements IProfileServiceBinder {
        AcmBinder(AcmService service) {
        }
        @Override
        public void cleanup() {
        }
    }

    private BluetoothGroupCallback mBluetoothGroupCallback = new BluetoothGroupCallback() {
        public void onGroupClientAppRegistered(int status, int appId) {
            Log.d(TAG, "onGroupClientAppRegistered, status: " + status + "appId: " + appId);
            if (status == 0) {
                mCsipManager.updateAppId(appId);
                mIsCsipRegistered = true;
            } else {
                Log.e(TAG, "DeviceGroup registeration failed, status:" + status);
            }
        }

        public void onConnectionStateChanged (int state, BluetoothDevice device) {
            Log.d(TAG, "onConnectionStateChanged: Device: " + device + "state: " + state);
            //notify statemachine about device connection state
            synchronized (mStateMachines) {
                  AcmStateMachine sm = getOrCreateStateMachine(device);
                  Message msg = sm.obtainMessage(AcmStateMachine.CSIP_CONNECTION_STATE_CHANGED);
                  msg.obj = state;
                  sm.sendMessage(msg);
            }
        }

        public void onExclusiveAccessChanged (int setId, int value, int status,
                                                   List<BluetoothDevice> devices) {
            Log.d(TAG, "onExclusiveAccessChanged: setId" + setId + devices + "status:" + status);

            //notify the statemachine about CSIP Lock status
            switch (status) {
                case ALL_LOCKS_ACQUIRED: {
                    synchronized (mStateMachines) {
                        for (BluetoothDevice device : devices) {
                            AcmStateMachine sm = getOrCreateStateMachine(device);
                            if (sm == null) {
                                //TODO:handle this case
                                continue;
                            }
                            Message msg = sm.obtainMessage(AcmStateMachine.CSIP_LOCK_STATUS_LOCKED);
                            msg.obj = setId;
                            msg.arg1 = value;
                            sm.sendMessage(msg);
                        }
                    }
                    break;
                }

                case SOME_LOCKS_ACQUIRED_REASON_TIMEOUT: //check if need to handle separately
                case SOME_LOCKS_ACQUIRED_REASON_DISC: {
                    BluetoothDevice mDevice = getCsipLockRequestedDevice();
                    if (devices.contains(mDevice)) {
                        synchronized (mStateMachines) {
                            for (BluetoothDevice device : devices) {
                                AcmStateMachine sm = getOrCreateStateMachine(device);
                                if (sm == null) {
                                    //TODO:handle this case
                                    continue;
                                }
                                Message msg = sm.obtainMessage(AcmStateMachine.CSIP_LOCK_STATUS_PARTIAL_LOCK);
                                msg.obj = setId;
                                msg.arg1 = value;
                                sm.sendMessage(msg);
                            }
                        }
                    } else {
                        Log.d(TAG, "Exclusive access requested device is not present in list, release access for all devices");
                        mCsipManager.setLock(setId, devices, mCsipManager.UNLOCK);
                    }
                } break;

                case LOCK_DENIED: {
                    synchronized (mStateMachines) {
                        for (BluetoothDevice device : devices) {
                            AcmStateMachine sm = getOrCreateStateMachine(device);
                            if (sm == null) {
                                //TODO:handle this case
                                continue;
                            }
                            Message msg = sm.obtainMessage(AcmStateMachine.CSIP_LOCK_STATUS_DENIED);
                            msg.obj = setId;
                            msg.arg1 = value;
                            sm.sendMessage(msg);
                        }
                    }
                } break;

                case LOCK_RELEASED: {
                    synchronized (mStateMachines) {
                        for (BluetoothDevice device : devices) {
                            AcmStateMachine sm = getOrCreateStateMachine(device);
                            if (sm == null) {
                                //TODO:handle this case
                                continue;
                            }
                            Message msg = sm.obtainMessage(AcmStateMachine.CSIP_LOCK_STATUS_RELEASED);
                            msg.obj = setId;
                            msg.arg1 = value;
                            sm.sendMessage(msg);
                        }
                    }
                } break;

                case LOCK_RELEASED_TIMEOUT: {
                    synchronized (mStateMachines) {
                        for (BluetoothDevice device : devices) {
                            AcmStateMachine sm = getOrCreateStateMachine(device);
                            if (sm == null) {
                                //TODO:handle this case
                                continue;
                            }
                            Message msg = sm.obtainMessage(AcmStateMachine.CSIP_LOCK_STATUS_RELEASED);
                            msg.obj = setId;
                            msg.arg1 = value;
                            sm.sendMessage(msg);
                        }
                    }
                } break;

                /*case INVALID_REQUEST_PARAMS: {
                    synchronized (mStateMachines) {
                        for (BluetoothDevice device : devices) {
                            AcmStateMachine sm = getOrCreateStateMachine(device);
                            if (sm == null) {
                                //TODO:handle this case
                                continue;
                            }
                            Message msg = sm.obtainMessage(AcmStateMachine.CSIP_LOCK_STATUS_INVALID_PARAM);
                            msg.obj = setId;
                            msg.arg1 = value;
                            sm.sendMessage(msg);
                        }
                    }
                } break;*/

                /*case LOCK_RELEASE_NOT_ALLOWED: {
                    synchronized (mStateMachines) {
                        for (BluetoothDevice device : devices) {
                            AcmStateMachine sm = getOrCreateStateMachine(device);
                            if (sm == null) {
                                //TODO:handle this case
                                continue;
                            }
                            Message msg = sm.obtainMessage(AcmStateMachine.CSIP_LOCK_STATUS_RELEASE);
                            msg.obj = setId;
                            msg.arg1 = value;
                            sm.sendMessage(msg);
                        }
                    }
                } break;*/

                case INVALID_VALUE:
                    break;
            }
        }

        //public void onSetMemberFound (int setId, BluetoothDevice device) {    }

        //public void onSetDiscoveryStatusChanged (int setId, int status, int reason) {    }

        //public void onLockAvailable (int setId, BluetoothDevice device) {    }

        //public void onNewSetFound (int setId,  BluetoothDevice device, UUID uuid) {     }

        //public void onLockStatusFetched (int setId, int lockStatus) {    }
    };

    public CsipManager getCsipManager(){
        return mCsipManager;
    }

    class CsipManager {
        public int LOCK = 0;
        public int UNLOCK = 0;

        int mCsipAppid;

        CsipManager() {
            LOCK = BluetoothDeviceGroup.ACCESS_GRANTED;
            UNLOCK = BluetoothDeviceGroup.ACCESS_RELEASED;

            registerCsip();
        }

        CsipManager(BluetoothGroupCallback callbacks) {
            LOCK = BluetoothDeviceGroup.ACCESS_GRANTED;
            UNLOCK = BluetoothDeviceGroup.ACCESS_RELEASED;

            registerCsip(callbacks);
        }

        void updateAppId(int id) {
            mCsipAppid = id;
        }

        int getAppId() {
            return mCsipAppid;
        }

        void registerCsip() {
            GroupService mGroupService = GroupService.getGroupService();
            if(mGroupService != null) {
                Log.i(TAG, "mGroupService is not null, register");
                mGroupService.registerGroupClientModule(mBluetoothGroupCallback);
            }
        }

        void registerCsip(BluetoothGroupCallback callbacks) {
            GroupService mGroupService = GroupService.getGroupService();
            if(mGroupService != null) {
                Log.i(TAG, "mGroupService is not null, register " + callbacks);
                mGroupService.registerGroupClientModule(callbacks);
            }
        }

        void unregisterCsip() {
            GroupService mGroupService = GroupService.getGroupService();
            if (mGroupService != null)
                mGroupService.unregisterGroupClientModule(mCsipAppid);
        }

        void connectCsip(BluetoothDevice device) {
            GroupService mGroupService = GroupService.getGroupService();
            mGroupService.connect(mCsipAppid, device);
        }

        void disconnectCsip(BluetoothDevice device) {
            GroupService mGroupService = GroupService.getGroupService();
            mGroupService.disconnect(mCsipAppid, device);
        }

        void setLock(int setId, List<BluetoothDevice> devices, int lockVal) {
            GroupService mGroupService = GroupService.getGroupService();
            mGroupService.setLockValue(mCsipAppid, setId, devices, lockVal);
        }

        DeviceGroup getCsipSet(int setId) {
            GroupService mGroupService = GroupService.getGroupService();
            return mGroupService.getCoordinatedSet(setId);
        }

        List<BluetoothDevice> getSetMembers(int setId) {
            DeviceGroup set = getCsipSet(setId);
            if(set != null)
                return set.getDeviceGroupMembers();
            return null;
        }

        int getCsipSetId(BluetoothDevice device, ParcelUuid uuid) {
            GroupService mGroupService = GroupService.getGroupService();
            return mGroupService.getRemoteDeviceGroupId(device, uuid);
            //return -1;
        }
    }
}
