/******************************************************************************
 *
 *  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.apm;

import static android.Manifest.permission.BLUETOOTH_CONNECT;

import android.bluetooth.BluetoothDevice;
import com.android.bluetooth.hfp.HeadsetService;
import com.android.bluetooth.hfp.HeadsetA2dpSync;
import com.android.bluetooth.apm.ApmConst;
import com.android.bluetooth.apm.MediaAudio;
import com.android.bluetooth.apm.CallControl;
import android.media.AudioManager;
import com.android.bluetooth.apm.ActiveDeviceManagerService;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.btservice.AdapterService;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import com.android.bluetooth.Utils;
import android.content.Context;
import java.lang.Integer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.util.Log;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import android.content.Intent;
import android.os.UserHandle;

public class CallAudio {

    private static CallAudio mCallAudio;
    private static final String TAG = "APM: CallAudio";
    Map<String, CallDevice> mCallDevicesMap;
    private Context mContext;
    private AudioManager mAudioManager;
    private ActiveDeviceManagerService mActiveDeviceManager;
    private AdapterService mAdapterService;
    public static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
    public static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
    public static final String BLUETOOTH_PRIVILEGED =
            android.Manifest.permission.BLUETOOTH_PRIVILEGED;
    private static final int MAX_DEVICES = 200;
    public boolean mVirtualCallStarted;
    private CallControl mCallControl = null;

    private CallAudio(Context context) {
        Log.d(TAG, "Initialization");
        mContext = context;
        mCallDevicesMap = new ConcurrentHashMap<String, CallDevice>();
        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
        mActiveDeviceManager = ActiveDeviceManagerService.get();
        mAdapterService = AdapterService.getAdapterService();
        mCallControl = CallControl.get();
    }

    public static CallAudio init(Context context) {
        if(mCallAudio == null) {
            mCallAudio = new CallAudio(context);
            CallAudioIntf.init(mCallAudio);
        }
        return mCallAudio;
    }

    public static CallAudio get() {
        return mCallAudio;
    }

    public boolean connect(BluetoothDevice device) {
    Log.i(TAG, "connect: " + device);
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
        if(device == null)
            return false;
        boolean status;
        if (getConnectionPolicy(device) == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) {
            Log.e(TAG, "Cannot connect to " + device + " : CONNECTION_POLICY_FORBIDDEN");
            return false;
        }

        DeviceProfileMap dMap = DeviceProfileMap.getDeviceProfileMapInstance();
        if (dMap == null)
            return false;

        int profileID = dMap.getSupportedProfile(device, ApmConst.AudioFeatures.CALL_AUDIO);
        if (profileID == ApmConst.AudioProfiles.NONE) {
            Log.e(TAG, "Can Not connect to " + device + ". Device does not support call service.");
            return false;
        }

        CallDevice mCallDevice = mCallDevicesMap.get(device.getAddress());
        if(mCallDevice == null) {
            if(mCallDevicesMap.size() >= MAX_DEVICES)
                return false;
            mCallDevice = new CallDevice(device, profileID);
            mCallDevicesMap.put(device.getAddress(), mCallDevice);
        } else if(mCallDevice.deviceConnStatus != BluetoothProfile.STATE_DISCONNECTED) {
            Log.i(TAG, "Device already connected");
            return false;
        }

        if((ApmConst.AudioProfiles.HFP & profileID) == ApmConst.AudioProfiles.HFP) {
            HeadsetService service = HeadsetService.getHeadsetService();
            if (service == null) {
                return false;
            }
            service.connectHfp(device);
        }

        StreamAudioService mStreamService = StreamAudioService.getStreamAudioService();
        if(mStreamService != null &&
                (ApmConst.AudioProfiles.BAP_CALL & profileID) == ApmConst.AudioProfiles.BAP_CALL) {
            mStreamService.connectLeStream(device, profileID);
        }
        return true;
    }

    public boolean connect(BluetoothDevice device, Boolean allProfiles) {
        if(allProfiles) {
            DeviceProfileMap dMap = DeviceProfileMap.getDeviceProfileMapInstance();
            if (dMap == null)
                return false;

            int profileID = dMap.getSupportedProfile(device, ApmConst.AudioFeatures.CALL_AUDIO);
            if((ApmConst.AudioProfiles.HFP & profileID) == ApmConst.AudioProfiles.HFP) {
                HeadsetService service = HeadsetService.getHeadsetService();
                if (service == null) {
                    return false;
                }
                return service.connectHfp(device);
            } else {
                /*Common connect for LE Media and Call handled from StreamAudioService*/
                return true;
            }
        }

        return connect(device);
    }

    public boolean disconnect(BluetoothDevice device) {
        Log.i(TAG, " disconnect: " + device);
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
        CallDevice mCallDevice;

        if(device == null)
            return false;

        mCallDevice = mCallDevicesMap.get(device.getAddress());
        if(mCallDevice == null) {
            Log.e(TAG, "Ignore: Device " + device + " not present in list");
            return false;
        }

        if (mCallDevice.profileConnStatus[CallDevice.SCO_STREAM] != BluetoothProfile.STATE_DISCONNECTED) {
            HeadsetService service = HeadsetService.getHeadsetService();
            if(service != null) {
                service.disconnectHfp(device);
            }
        }
		
        if (mCallDevice.profileConnStatus[CallDevice.LE_STREAM] != BluetoothProfile.STATE_DISCONNECTED) {
            StreamAudioService service = StreamAudioService.getStreamAudioService();
            if(service != null) {
                service.disconnectLeStream(device, true, false);
            }
        }

        return true;
    }

    public boolean disconnect(BluetoothDevice device, Boolean allProfiles) {
        if(allProfiles) {
            CallDevice mCallDevice = mCallDevicesMap.get(device.getAddress());
            if(mCallDevice == null) {
                Log.e(TAG, "Ignore: Device " + device + " not present in list");
                return false;
            }
            if(mCallDevice.profileConnStatus[CallDevice.SCO_STREAM] != BluetoothProfile.STATE_DISCONNECTED) {
                return disconnect(device);
            } else {
                /*Common connect for LE Media and Call handled from StreamAudioService*/
                return true;
            }
        }

        return disconnect(device);
    }

    public boolean startScoUsingVirtualVoiceCall() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
        Log.d(TAG, "startScoUsingVirtualVoiceCall");
        BluetoothDevice mActivedevice = null;
        int profile;
        mActiveDeviceManager = ActiveDeviceManagerService.get();
        if(mActiveDeviceManager != null) {
            mActivedevice = mActiveDeviceManager.getActiveDevice(ApmConst.AudioFeatures.CALL_AUDIO);
            if(mActivedevice == null) {
                Log.e(TAG, "startScoUsingVirtualVoiceCall failed. Active Device is null");
                return false;
            }
        } else {
            return false;
        }

        checkA2dpState();

        profile = mActiveDeviceManager.getActiveProfile(ApmConst.AudioFeatures.CALL_AUDIO);
        switch(profile) {
            case ApmConst.AudioProfiles.HFP:
                HeadsetService headsetService = HeadsetService.getHeadsetService();
                if(headsetService != null) {
                    if(headsetService.startScoUsingVirtualVoiceCall()) {
                        mVirtualCallStarted = true;
                        return true;
                    }
                }
                break;
            case ApmConst.AudioProfiles.BAP_CALL:
            case ApmConst.AudioProfiles.TMAP_CALL:
                StreamAudioService mStreamAudioService = StreamAudioService.getStreamAudioService();
                if(mStreamAudioService != null) {
                    if(mStreamAudioService.startStream(mActivedevice)) {
                        mVirtualCallStarted = true;
                        mCallControl = CallControl.get();
                        if (mCallControl != null) {
                            mCallControl.setVirtualCallActive(true);
                        }
                        return true;
                    }
                }
                break;
            default:
                Log.e(TAG, "Unhandled profile");
                break;
        }

        Log.e(TAG, "startScoUsingVirtualVoiceCall failed. Device: " + mActivedevice);
        if(ApmConst.AudioProfiles.HFP != profile) {
            HeadsetService service = HeadsetService.getHeadsetService();
            if(service != null) {
                service.getHfpA2DPSyncInterface().releaseA2DP(null);
            }
        }
        return false;
    }

    public boolean stopScoUsingVirtualVoiceCall() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
        Log.d(TAG, "stopScoUsingVirtualVoiceCall");
        BluetoothDevice mActivedevice = null;
        int profile;
        mActiveDeviceManager = ActiveDeviceManagerService.get();
        if(mActiveDeviceManager != null) {
            mActivedevice = mActiveDeviceManager.getActiveDevice(ApmConst.AudioFeatures.CALL_AUDIO);
            if(mActivedevice == null) {
                Log.e(TAG, "stopScoUsingVirtualVoiceCall failed. Active Device is null");
                return false;
            }
        } else {
            return false;
        }

        profile = mActiveDeviceManager.getActiveProfile(ApmConst.AudioFeatures.CALL_AUDIO);
        switch(profile) {
            case ApmConst.AudioProfiles.HFP:
                HeadsetService headsetService = HeadsetService.getHeadsetService();
                if(headsetService != null) {
                    mVirtualCallStarted = false;
                    return headsetService.stopScoUsingVirtualVoiceCall();
                }
                break;
            case ApmConst.AudioProfiles.BAP_CALL:
            case ApmConst.AudioProfiles.TMAP_CALL:
                StreamAudioService mStreamAudioService = StreamAudioService.getStreamAudioService();
                if(mStreamAudioService != null) {
                    mVirtualCallStarted = false;
                    mCallControl = CallControl.get();
                    if (mCallControl != null) {
                        mCallControl.setVirtualCallActive(false);
                    }
                    return mStreamAudioService.stopStream(mActivedevice);
                }
                break;
            default:
                Log.e(TAG, "Unhandled profile");
                break;
        }

        Log.e(TAG, "stopScoUsingVirtualVoiceCall failed. Device: " + mActivedevice);
        return false;
    }

    void remoteDisconnectVirtualVoiceCall(BluetoothDevice device) {
        if(device == null)
            return;
        ActiveDeviceManagerService mActiveDeviceManager = ActiveDeviceManagerService.get();
        if(device.equals(mActiveDeviceManager.getActiveDevice(ApmConst.AudioFeatures.CALL_AUDIO)) &&
                        mActiveDeviceManager.isStableState(ApmConst.AudioFeatures.CALL_AUDIO)) {
            stopScoUsingVirtualVoiceCall();
        }
    }

    int getProfile(BluetoothDevice mDevice) {
        DeviceProfileMap dMap = DeviceProfileMap.getDeviceProfileMapInstance();
        int profileID = dMap.getProfile(mDevice, ApmConst.AudioFeatures.CALL_AUDIO);
        Log.d(TAG," getProfile for device " + mDevice + " profileID " + profileID);
        return profileID;
    }

    void checkA2dpState() {
        MediaAudio sMediaAudio = MediaAudio.get();
        BluetoothDevice sMediaActivedevice =
        mActiveDeviceManager.getActiveDevice(ApmConst.AudioFeatures.MEDIA_AUDIO);
        //if(sMediaAudio.isA2dpPlaying(sMediaActivedevice)) {
            Log.d(TAG," suspendA2DP isA2dpPlaying true " + " for device " + sMediaActivedevice);
            int profileID = mActiveDeviceManager.getActiveProfile(
                                ApmConst.AudioFeatures.CALL_AUDIO);
            if(ApmConst.AudioProfiles.HFP != profileID) {
                HeadsetService service = HeadsetService.getHeadsetService();
                if(service != null) {
                    service.getHfpA2DPSyncInterface().suspendA2DP(
                    HeadsetA2dpSync.A2DP_SUSPENDED_BY_CS_CALL, null);
                }
            }
        //}
    }

    public boolean connectAudio() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
        BluetoothDevice mActivedevice = null;
        boolean status = false;

        mActiveDeviceManager = ActiveDeviceManagerService.get();
        if(mActiveDeviceManager != null) {
                mActivedevice = mActiveDeviceManager.getActiveDevice(ApmConst.AudioFeatures.CALL_AUDIO);
        }
        Log.i(TAG, "connectAudio: device=" + mActivedevice + ", " + Utils.getUidPidString());

        int profileID = mActiveDeviceManager.getActiveProfile(ApmConst.AudioFeatures.CALL_AUDIO);
        checkA2dpState();

        if(ApmConst.AudioProfiles.HFP == profileID) {
            HeadsetService service = HeadsetService.getHeadsetService();
            if (service == null) {
                status = false;
            }
            status = service.connectAudio(mActivedevice);
        } else if(ApmConst.AudioProfiles.BAP_CALL == profileID) {
            StreamAudioService service = StreamAudioService.getStreamAudioService();
            if(service != null) {
                status = service.startStream(mActivedevice);
            }
        } else {
            Log.e(TAG, "Unhandled connect audio request for profile: " + profileID);
            status = false;
        }

        if(status == false) {
            Log.e(TAG, "failed connect audio request for device: " + mActivedevice);
            if(ApmConst.AudioProfiles.HFP != profileID) {
                HeadsetService service = HeadsetService.getHeadsetService();
                if(service != null) {
                    service.getHfpA2DPSyncInterface().releaseA2DP(null);
                }
            }
        }

        return status;
    }

    public boolean disconnectAudio() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
        BluetoothDevice mActivedevice = null;
        boolean mStatus = false;

        if(mActiveDeviceManager != null) {
                mActivedevice = mActiveDeviceManager.getActiveDevice(ApmConst.AudioFeatures.CALL_AUDIO);
        }
        Log.i(TAG, "disconnectAudio: device=" + mActivedevice + ", " + Utils.getUidPidString());

        int profileID = mActiveDeviceManager.getActiveProfile(ApmConst.AudioFeatures.CALL_AUDIO);

        if(ApmConst.AudioProfiles.HFP == profileID) {
            HeadsetService service = HeadsetService.getHeadsetService();
            if (service == null) {
                    mStatus = false;
            }
            mStatus = service.disconnectAudio();
        } else if(ApmConst.AudioProfiles.BAP_CALL == profileID) {
            StreamAudioService service = StreamAudioService.getStreamAudioService();
            if(service != null) {
                mStatus = service.stopStream(mActivedevice);
            }
        } else {
            Log.e(TAG, "Unhandled disconnectAudio request for profile: " + profileID);
            mStatus = true;
        }

        if(ApmConst.AudioProfiles.HFP != profileID) {
            HeadsetService service = HeadsetService.getHeadsetService();
            if(service != null) {
                service.getHfpA2DPSyncInterface().releaseA2DP(null);
            }
        }
        return mStatus;
    }

    public boolean setConnectionPolicy(BluetoothDevice device, Integer connectionPolicy) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
                "Need BLUETOOTH_PRIVILEGED permission");
        boolean mStatus;

        Log.d(TAG, "setConnectionPolicy: device=" + device
            + ", connectionPolicy=" + connectionPolicy + ", " + Utils.getUidPidString());

        mStatus = mAdapterService.getDatabase()
            .setProfileConnectionPolicy(device, BluetoothProfile.HEADSET, connectionPolicy);

        if (mStatus &&
                connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
            connect(device);
        } else if (mStatus &&
                connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) {
            disconnect(device);
        }
        return mStatus;
    }

    public int getConnectionPolicy(BluetoothDevice device) {
        if(mAdapterService != null) {
            int connPolicy;
            connPolicy = mAdapterService.getDatabase()
                .getProfileConnectionPolicy(device, BluetoothProfile.HEADSET);
            Log.d(TAG, "getConnectionPolicy: device=" + device
                    + ", connectionPolicy=" + connPolicy);
            return connPolicy;
        } else {
            return BluetoothProfile.CONNECTION_POLICY_UNKNOWN;

        }
    }

    public int getAudioState(BluetoothDevice device) {
        if(device == null)
            return BluetoothHeadset.STATE_AUDIO_DISCONNECTED;
        CallDevice mCallDevice;
        mCallDevice = mCallDevicesMap.get(device.getAddress());
        if (mCallDevice == null) {
            Log.w(TAG, "getAudioState: device " + device + " was never connected/connecting");
            return BluetoothHeadset.STATE_AUDIO_DISCONNECTED;
        }
        return mCallDevice.scoStatus;
    }

    private List<BluetoothDevice> getNonIdleAudioDevices() {
        if(mCallDevicesMap.size() == 0) {
            return new ArrayList<>(0);
        }

        ArrayList<BluetoothDevice> devices = new ArrayList<>();
        for (CallDevice mCallDevice : mCallDevicesMap.values()) {
            if (mCallDevice.scoStatus != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
                devices.add(mCallDevice.mDevice);
            }
        }
        return devices;
    }

    public boolean isAudioOn() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        int numConnectedAudioDevices = getNonIdleAudioDevices().size();
        Log.d(TAG," isAudioOn: The number of audio connected devices "
                      + numConnectedAudioDevices);
             return numConnectedAudioDevices > 0;
    }

    public List<BluetoothDevice> getConnectedDevices() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        Log.i(TAG, "getConnectedDevices: ");
        if(mCallDevicesMap.size() == 0) {
            Log.i(TAG, "no device is Connected:");
            return new ArrayList<>(0);
        }

        List<BluetoothDevice> connectedDevices = new ArrayList<>();
        for(CallDevice mCallDevice : mCallDevicesMap.values()) {
            if(mCallDevice.deviceConnStatus == BluetoothProfile.STATE_CONNECTED) {
                connectedDevices.add(mCallDevice.mDevice);
            }
        }
        Log.i(TAG, "ConnectedDevices: = " + connectedDevices.size());
        return connectedDevices;
    }

    public int getConnectionState(BluetoothDevice device) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if(device == null)
            return BluetoothProfile.STATE_DISCONNECTED;
        CallDevice mCallDevice;
        mCallDevice = mCallDevicesMap.get(device.getAddress());
        if(mCallDevice != null)
            return mCallDevice.deviceConnStatus;

        return BluetoothProfile.STATE_DISCONNECTED;
    }

    public boolean isVoiceOrCallActive() {
        boolean isVoiceActive = isAudioOn() || mVirtualCallStarted;
        HeadsetService mHeadsetService = HeadsetService.getHeadsetService();
        if(mHeadsetService != null) {
            isVoiceActive = isVoiceActive || mHeadsetService.isScoOrCallActive();
        }
        return isVoiceActive;
    }

    private void broadcastConnStateChange(BluetoothDevice device, int fromState, int toState) {
        Log.d(TAG,"broadcastConnectionState " + device + ": " + fromState + "->" + toState);
        HeadsetService mHeadsetService = HeadsetService.getHeadsetService();
        if(mHeadsetService == null) {
            Log.w(TAG,"broadcastConnectionState: HeadsetService not initialized. Return!");
            return;
        }

        Intent intent = new Intent(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
        intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, fromState);
        intent.putExtra(BluetoothProfile.EXTRA_STATE, toState);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
        mHeadsetService.sendBroadcastAsUser(intent, UserHandle.ALL,
                BLUETOOTH_CONNECT, Utils.getTempAllowlistBroadcastOptions());
    }

    private void broadcastAudioState(BluetoothDevice device, int fromState, int toState) {
         Log.d(TAG,"broadcastAudioState " + device + ": " + fromState + "->" + toState);
        HeadsetService mHeadsetService = HeadsetService.getHeadsetService();
        if(mHeadsetService == null) {
            Log.d(TAG,"broadcastAudioState: HeadsetService not initialized. Return!");
            return;
        }

        Intent intent = new Intent(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
        intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, fromState);
        intent.putExtra(BluetoothProfile.EXTRA_STATE, toState);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        mHeadsetService.sendBroadcastAsUser(intent, UserHandle.ALL,
                BLUETOOTH_CONNECT, Utils.getTempAllowlistBroadcastOptions());
    }

    public void onConnStateChange(BluetoothDevice device, Integer state, Integer profile) {
        int prevState;
        Log.w(TAG, "onConnStateChange: profile: " + profile + " state: "
                                                  + state + " for device " + device);
        if(device == null)
            return;
        CallDevice mCallDevice = mCallDevicesMap.get(device.getAddress());

        if(mCallDevice == null) {
            if(state == BluetoothProfile.STATE_DISCONNECTED)
                return;
            if(mCallDevicesMap.size() >= MAX_DEVICES) {
                return;
            }
            mCallDevice = new CallDevice(device, profile, state);
            mCallDevicesMap.put(device.getAddress(), mCallDevice);
            broadcastConnStateChange(device, BluetoothProfile.STATE_DISCONNECTED, state);
            return;
        }

        int profileIndex = mCallDevice.getProfileIndex(profile);
        DeviceProfileMap dMap = DeviceProfileMap.getDeviceProfileMapInstance();
        prevState = mCallDevice.deviceConnStatus;
        mCallDevice.profileConnStatus[profileIndex] = state;

        if(state == BluetoothProfile.STATE_DISCONNECTED) {
            dMap.profileConnectionUpdate(device, ApmConst.AudioFeatures.CALL_AUDIO, profile, false);
        }

        int otherProfileConnectionState = mCallDevice.profileConnStatus[(profileIndex+1)%2];
        Log.w(TAG, " otherProfileConnectionState: " + otherProfileConnectionState);

        switch(otherProfileConnectionState) {
        /*Send Broadcast based on state of other profile*/
            case BluetoothProfile.STATE_DISCONNECTED:
                broadcastConnStateChange(device, prevState, state);
                mCallDevice.deviceConnStatus = state;
                if(state == BluetoothProfile.STATE_CONNECTED) {
                    int supportedProfiles = dMap.getSupportedProfile(device, ApmConst.AudioFeatures.CALL_AUDIO);
                    if(profile == ApmConst.AudioProfiles.HFP &&
                            (supportedProfiles & ApmConst.AudioProfiles.BAP_CALL) == ApmConst.AudioProfiles.BAP_CALL) {
                        Log.w(TAG, "Connect LE Voice after HFP auto connect from remote");
                        StreamAudioService mStreamService = StreamAudioService.getStreamAudioService();
                        if(mStreamService != null) {
                            mStreamService.connectLeStream(device, ApmConst.AudioProfiles.BAP_CALL);
                        }
                    } else {
                        ActiveDeviceManagerService mActiveDeviceManager = ActiveDeviceManagerService.get();
                        mActiveDeviceManager.setActiveDevice(device, ApmConst.AudioFeatures.CALL_AUDIO);
                    }
                }
                break;
            case BluetoothProfile.STATE_CONNECTING:
                int preferredProfile = dMap.getProfile(device, ApmConst.AudioFeatures.CALL_AUDIO);
                boolean isPreferredProfile = (preferredProfile == profile);
                if(state == BluetoothProfile.STATE_CONNECTED && isPreferredProfile) {
                    broadcastConnStateChange(device, prevState, state);
                    mCallDevice.deviceConnStatus = state;
                }
                break;
            case BluetoothProfile.STATE_DISCONNECTING:
                if(state == BluetoothProfile.STATE_CONNECTING ||
                        state == BluetoothProfile.STATE_CONNECTED) {
                    broadcastConnStateChange(device, prevState, state);
                    mCallDevice.deviceConnStatus = state;
                }
                break;
            case BluetoothProfile.STATE_CONNECTED:
                if(state == BluetoothProfile.STATE_CONNECTED) {
                    if(prevState != state) {
                        broadcastConnStateChange(device, prevState, state);
                        mCallDevice.deviceConnStatus = state;
                    }
                    ActiveDeviceManagerService mActiveDeviceManager =
                                     ActiveDeviceManagerService.get();
                    mActiveDeviceManager.setActiveDevice(device, ApmConst.AudioFeatures.CALL_AUDIO);
                } else if(state == BluetoothProfile.STATE_DISCONNECTED) {
                    if(prevState != BluetoothProfile.STATE_CONNECTED) {
                        broadcastConnStateChange(device, prevState, BluetoothProfile.STATE_CONNECTED);
                        mCallDevice.deviceConnStatus = BluetoothProfile.STATE_CONNECTED;
                    } else {
                        ActiveDeviceManagerService mActiveDeviceManager =
                                     ActiveDeviceManagerService.get();
                        if(device.equals(mActiveDeviceManager.getActiveDevice(ApmConst.AudioFeatures.CALL_AUDIO))) {
                            mActiveDeviceManager.setActiveDevice(device, ApmConst.AudioFeatures.CALL_AUDIO);
                        }
                    }
                }
                break;
        }

        if(state == BluetoothProfile.STATE_CONNECTED) {
            dMap.profileConnectionUpdate(device, ApmConst.AudioFeatures.CALL_AUDIO, profile, true);
        }
    }

    public void onAudioStateChange(BluetoothDevice device, Integer state) {
        int prevStatus;
        if(device == null)
            return;
        CallDevice mCallDevice = mCallDevicesMap.get(device.getAddress());
        if(mCallDevice == null) {
            return;
        }

        if(mCallDevice.scoStatus == state)
            return;

        HeadsetService service = HeadsetService.getHeadsetService();
        int profileID = mActiveDeviceManager.getActiveProfile(
                               ApmConst.AudioFeatures.CALL_AUDIO);
        BluetoothDevice mActivedevice = mActiveDeviceManager.getActiveDevice(
                               ApmConst.AudioFeatures.CALL_AUDIO);
        if (service != null) {
            if(!(service.shouldCallAudioBeActive() || mVirtualCallStarted)) {
                if(ApmConst.AudioProfiles.BAP_CALL  == profileID) {
                    StreamAudioService mStreamAudioService =
                                StreamAudioService.getStreamAudioService();
                    if(mStreamAudioService != null) {
                        Log.w(TAG, "Call not active, disconnect stream");
                        mStreamAudioService.stopStream(mActivedevice);
                    }
                }
            }
        }

        prevStatus = mCallDevice.scoStatus;
        mCallDevice.scoStatus = state;
        VolumeManager mVolumeManager = VolumeManager.get();
        mVolumeManager.updateStreamState(device, state, ApmConst.AudioFeatures.CALL_AUDIO);
        broadcastAudioState(device, prevStatus, state);
        if(state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
            if(ApmConst.AudioProfiles.HFP != profileID) {
                if(service != null) {
                    service.getHfpA2DPSyncInterface().releaseA2DP(null);
                }
            }
          //mAudioManager.setBluetoothScoOn(false);
        } /*else {
          mAudioManager.setBluetoothScoOn(true);
        }*/
    }

    public void setAudioParam(String param) {
        mAudioManager.setParameters(param);
    }

    public void setBluetoothScoOn(boolean on) {
        mAudioManager.setBluetoothScoOn(on);
    }

    public AudioManager getAudioManager() {
        return mAudioManager;
    }

    class CallDevice {
        BluetoothDevice mDevice;
        int[] profileConnStatus = new int[2];
        int deviceConnStatus;
        int scoStatus;

        public static final int SCO_STREAM = 0;
        public static final int LE_STREAM = 1;

        CallDevice(BluetoothDevice device, int profile, int state) {
            mDevice = device;
            if(profile == ApmConst.AudioProfiles.HFP) {
                profileConnStatus[SCO_STREAM] = state;
                profileConnStatus[LE_STREAM] = BluetoothProfile.STATE_DISCONNECTED;
            } else {
                profileConnStatus[LE_STREAM] = state;
                profileConnStatus[SCO_STREAM] = BluetoothProfile.STATE_DISCONNECTED;
            }
            deviceConnStatus = state;
            scoStatus = BluetoothHeadset.STATE_AUDIO_DISCONNECTED;;
        }

        CallDevice(BluetoothDevice device, int profile) {
            this(device, profile, BluetoothProfile.STATE_DISCONNECTED);
        }

        public int getProfileIndex(int profile) {
            if(profile == ApmConst.AudioProfiles.HFP)
                return SCO_STREAM;
            else
                return LE_STREAM;
        }
    }
}

