| /* |
| * Copyright (c) 2014 The Android Open Source Project |
| * Copyright (C) 2012 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.hfpclient; |
| |
| import android.bluetooth.BluetoothDevice; |
| import android.bluetooth.BluetoothProfile; |
| import android.bluetooth.BluetoothHeadsetClient; |
| import android.bluetooth.BluetoothHeadsetClientCall; |
| import android.bluetooth.IBluetoothHeadsetClient; |
| import android.content.BroadcastReceiver; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.IntentFilter; |
| import android.media.AudioManager; |
| import android.os.Bundle; |
| import android.os.Message; |
| import android.provider.Settings; |
| import android.util.Log; |
| import com.android.bluetooth.btservice.ProfileService; |
| import com.android.bluetooth.Utils; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| /** |
| * Provides Bluetooth Headset Client (HF Role) profile, as a service in the |
| * Bluetooth application. |
| * |
| * @hide |
| */ |
| public class HeadsetClientService extends ProfileService { |
| private static final boolean DBG = false; |
| private static final String TAG = "HeadsetClientService"; |
| |
| private HeadsetClientStateMachine mStateMachine; |
| private static HeadsetClientService sHeadsetClientService; |
| |
| @Override |
| protected String getName() { |
| return TAG; |
| } |
| |
| @Override |
| public IProfileServiceBinder initBinder() { |
| return new BluetoothHeadsetClientBinder(this); |
| } |
| |
| @Override |
| protected boolean start() { |
| mStateMachine = HeadsetClientStateMachine.make(this); |
| IntentFilter filter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION); |
| filter.addAction(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY); |
| try { |
| registerReceiver(mBroadcastReceiver, filter); |
| } catch (Exception e) { |
| Log.w(TAG, "Unable to register broadcat receiver", e); |
| } |
| setHeadsetClientService(this); |
| return true; |
| } |
| |
| @Override |
| protected boolean stop() { |
| try { |
| unregisterReceiver(mBroadcastReceiver); |
| } catch (Exception e) { |
| Log.w(TAG, "Unable to unregister broadcast receiver", e); |
| } |
| mStateMachine.doQuit(); |
| return true; |
| } |
| |
| @Override |
| protected boolean cleanup() { |
| if (mStateMachine != null) { |
| mStateMachine.cleanup(); |
| } |
| clearHeadsetClientService(); |
| return true; |
| } |
| |
| private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { |
| @Override |
| public void onReceive(Context context, Intent intent) { |
| String action = intent.getAction(); |
| |
| if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) { |
| int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1); |
| if (streamType == AudioManager.STREAM_BLUETOOTH_SCO) { |
| int streamValue = intent |
| .getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1); |
| int streamPrevValue = intent.getIntExtra( |
| AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, -1); |
| |
| if (streamValue != -1 && streamValue != streamPrevValue) { |
| mStateMachine.sendMessage(mStateMachine.obtainMessage( |
| HeadsetClientStateMachine.SET_SPEAKER_VOLUME, streamValue, 0)); |
| } |
| } |
| } |
| } |
| }; |
| |
| /** |
| * Handlers for incoming service calls |
| */ |
| private static class BluetoothHeadsetClientBinder extends IBluetoothHeadsetClient.Stub |
| implements IProfileServiceBinder { |
| private HeadsetClientService mService; |
| |
| public BluetoothHeadsetClientBinder(HeadsetClientService svc) { |
| mService = svc; |
| } |
| |
| @Override |
| public boolean cleanup() { |
| mService = null; |
| return true; |
| } |
| |
| private HeadsetClientService getService() { |
| if (!Utils.checkCaller()) { |
| Log.w(TAG, "HeadsetClient call not allowed for non-active user"); |
| return null; |
| } |
| |
| if (mService != null && mService.isAvailable()) { |
| return mService; |
| } |
| return null; |
| } |
| |
| @Override |
| public boolean connect(BluetoothDevice device) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return false; |
| } |
| return service.connect(device); |
| } |
| |
| @Override |
| public boolean disconnect(BluetoothDevice device) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return false; |
| } |
| return service.disconnect(device); |
| } |
| |
| @Override |
| public List<BluetoothDevice> getConnectedDevices() { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return new ArrayList<BluetoothDevice>(0); |
| } |
| return service.getConnectedDevices(); |
| } |
| |
| @Override |
| public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return new ArrayList<BluetoothDevice>(0); |
| } |
| return service.getDevicesMatchingConnectionStates(states); |
| } |
| |
| @Override |
| public int getConnectionState(BluetoothDevice device) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return BluetoothProfile.STATE_DISCONNECTED; |
| } |
| return service.getConnectionState(device); |
| } |
| |
| @Override |
| public boolean setPriority(BluetoothDevice device, int priority) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return false; |
| } |
| return service.setPriority(device, priority); |
| } |
| |
| @Override |
| public int getPriority(BluetoothDevice device) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return BluetoothProfile.PRIORITY_UNDEFINED; |
| } |
| return service.getPriority(device); |
| } |
| |
| @Override |
| public boolean startVoiceRecognition(BluetoothDevice device) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return false; |
| } |
| return service.startVoiceRecognition(device); |
| } |
| |
| @Override |
| public boolean stopVoiceRecognition(BluetoothDevice device) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return false; |
| } |
| return service.stopVoiceRecognition(device); |
| } |
| |
| @Override |
| public boolean acceptIncomingConnect(BluetoothDevice device) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return false; |
| } |
| return service.acceptIncomingConnect(device); |
| } |
| |
| @Override |
| public boolean rejectIncomingConnect(BluetoothDevice device) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return false; |
| } |
| return service.rejectIncomingConnect(device); |
| } |
| |
| @Override |
| public int getAudioState(BluetoothDevice device) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED; |
| } |
| return service.getAudioState(device); |
| } |
| |
| @Override |
| public boolean connectAudio() { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return false; |
| } |
| return service.connectAudio(); |
| } |
| |
| @Override |
| public boolean disconnectAudio() { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return false; |
| } |
| return service.disconnectAudio(); |
| } |
| |
| @Override |
| public boolean acceptCall(BluetoothDevice device, int flag) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return false; |
| } |
| return service.acceptCall(device, flag); |
| } |
| |
| @Override |
| public boolean rejectCall(BluetoothDevice device) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return false; |
| } |
| return service.rejectCall(device); |
| } |
| |
| @Override |
| public boolean holdCall(BluetoothDevice device) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return false; |
| } |
| return service.holdCall(device); |
| } |
| |
| @Override |
| public boolean terminateCall(BluetoothDevice device, int index) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return false; |
| } |
| return service.terminateCall(device, index); |
| } |
| |
| @Override |
| public boolean explicitCallTransfer(BluetoothDevice device) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return false; |
| } |
| return service.explicitCallTransfer(device); |
| } |
| |
| @Override |
| public boolean enterPrivateMode(BluetoothDevice device, int index) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return false; |
| } |
| return service.enterPrivateMode(device, index); |
| } |
| |
| @Override |
| public boolean redial(BluetoothDevice device) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return false; |
| } |
| return service.redial(device); |
| } |
| |
| @Override |
| public boolean dial(BluetoothDevice device, String number) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return false; |
| } |
| return service.dial(device, number); |
| } |
| |
| @Override |
| public boolean dialMemory(BluetoothDevice device, int location) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return false; |
| } |
| return service.dialMemory(device, location); |
| } |
| |
| @Override |
| public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return null; |
| } |
| return service.getCurrentCalls(device); |
| } |
| |
| @Override |
| public boolean sendDTMF(BluetoothDevice device, byte code) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return false; |
| } |
| return service.sendDTMF(device, code); |
| } |
| |
| @Override |
| public boolean getLastVoiceTagNumber(BluetoothDevice device) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return false; |
| } |
| return service.getLastVoiceTagNumber(device); |
| } |
| |
| @Override |
| public Bundle getCurrentAgEvents(BluetoothDevice device) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return null; |
| } |
| return service.getCurrentAgEvents(device); |
| } |
| |
| @Override |
| public Bundle getCurrentAgFeatures(BluetoothDevice device) { |
| HeadsetClientService service = getService(); |
| if (service == null) { |
| return null; |
| } |
| return service.getCurrentAgFeatures(device); |
| } |
| }; |
| |
| // API methods |
| public static synchronized HeadsetClientService getHeadsetClientService() { |
| if (sHeadsetClientService != null && sHeadsetClientService.isAvailable()) { |
| if (DBG) { |
| Log.d(TAG, "getHeadsetClientService(): returning " + sHeadsetClientService); |
| } |
| return sHeadsetClientService; |
| } |
| if (DBG) { |
| if (sHeadsetClientService == null) { |
| Log.d(TAG, "getHeadsetClientService(): service is NULL"); |
| } else if (!(sHeadsetClientService.isAvailable())) { |
| Log.d(TAG, "getHeadsetClientService(): service is not available"); |
| } |
| } |
| return null; |
| } |
| |
| private static synchronized void setHeadsetClientService(HeadsetClientService instance) { |
| if (instance != null && instance.isAvailable()) { |
| if (DBG) { |
| Log.d(TAG, "setHeadsetClientService(): set to: " + sHeadsetClientService); |
| } |
| sHeadsetClientService = instance; |
| } else { |
| if (DBG) { |
| if (sHeadsetClientService == null) { |
| Log.d(TAG, "setHeadsetClientService(): service not available"); |
| } else if (!sHeadsetClientService.isAvailable()) { |
| Log.d(TAG, "setHeadsetClientService(): service is cleaning up"); |
| } |
| } |
| } |
| } |
| |
| private static synchronized void clearHeadsetClientService() { |
| sHeadsetClientService = null; |
| } |
| |
| public boolean connect(BluetoothDevice device) { |
| enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, |
| "Need BLUETOOTH ADMIN permission"); |
| |
| if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) { |
| return false; |
| } |
| |
| int connectionState = mStateMachine.getConnectionState(device); |
| if (connectionState == BluetoothProfile.STATE_CONNECTED || |
| connectionState == BluetoothProfile.STATE_CONNECTING) { |
| return false; |
| } |
| |
| mStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT, device); |
| return true; |
| } |
| |
| boolean disconnect(BluetoothDevice device) { |
| enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, |
| "Need BLUETOOTH ADMIN permission"); |
| int connectionState = mStateMachine.getConnectionState(device); |
| if (connectionState != BluetoothProfile.STATE_CONNECTED && |
| connectionState != BluetoothProfile.STATE_CONNECTING) { |
| return false; |
| } |
| |
| mStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT, device); |
| return true; |
| } |
| |
| public List<BluetoothDevice> getConnectedDevices() { |
| enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); |
| return mStateMachine.getConnectedDevices(); |
| } |
| |
| private List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { |
| enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); |
| return mStateMachine.getDevicesMatchingConnectionStates(states); |
| } |
| |
| int getConnectionState(BluetoothDevice device) { |
| enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); |
| return mStateMachine.getConnectionState(device); |
| } |
| |
| // TODO Should new setting for HeadsetClient priority be created? |
| public boolean setPriority(BluetoothDevice device, int priority) { |
| enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, |
| "Need BLUETOOTH_ADMIN permission"); |
| Settings.Global.putInt(getContentResolver(), |
| Settings.Global.getBluetoothHeadsetPriorityKey(device.getAddress()), |
| priority); |
| if (DBG) { |
| Log.d(TAG, "Saved priority " + device + " = " + priority); |
| } |
| return true; |
| } |
| |
| public int getPriority(BluetoothDevice device) { |
| enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, |
| "Need BLUETOOTH_ADMIN permission"); |
| int priority = Settings.Global.getInt(getContentResolver(), |
| Settings.Global.getBluetoothHeadsetPriorityKey(device.getAddress()), |
| BluetoothProfile.PRIORITY_UNDEFINED); |
| return priority; |
| } |
| |
| boolean startVoiceRecognition(BluetoothDevice device) { |
| enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); |
| int connectionState = mStateMachine.getConnectionState(device); |
| if (connectionState != BluetoothProfile.STATE_CONNECTED && |
| connectionState != BluetoothProfile.STATE_CONNECTING) { |
| return false; |
| } |
| mStateMachine.sendMessage(HeadsetClientStateMachine.VOICE_RECOGNITION_START); |
| return true; |
| } |
| |
| boolean stopVoiceRecognition(BluetoothDevice device) { |
| enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); |
| // It seem that we really need to check the AudioOn state. |
| // But since we allow startVoiceRecognition in STATE_CONNECTED and |
| // STATE_CONNECTING state, we do these 2 in this method |
| int connectionState = mStateMachine.getConnectionState(device); |
| if (connectionState != BluetoothProfile.STATE_CONNECTED && |
| connectionState != BluetoothProfile.STATE_CONNECTING) { |
| return false; |
| } |
| mStateMachine.sendMessage(HeadsetClientStateMachine.VOICE_RECOGNITION_STOP); |
| return true; |
| } |
| |
| boolean acceptIncomingConnect(BluetoothDevice device) { |
| // TODO(BT) remove it if stack does access control |
| return false; |
| } |
| |
| boolean rejectIncomingConnect(BluetoothDevice device) { |
| // TODO(BT) remove it if stack does access control |
| return false; |
| } |
| |
| int getAudioState(BluetoothDevice device) { |
| return mStateMachine.getAudioState(device); |
| } |
| |
| boolean connectAudio() { |
| enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); |
| if (!mStateMachine.isConnected()) { |
| return false; |
| } |
| if (mStateMachine.isAudioOn()) { |
| return false; |
| } |
| mStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT_AUDIO); |
| return true; |
| } |
| |
| boolean disconnectAudio() { |
| enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); |
| if (!mStateMachine.isAudioOn()) { |
| return false; |
| } |
| mStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT_AUDIO); |
| return true; |
| } |
| |
| boolean holdCall(BluetoothDevice device) { |
| enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); |
| int connectionState = mStateMachine.getConnectionState(device); |
| if (connectionState != BluetoothProfile.STATE_CONNECTED && |
| connectionState != BluetoothProfile.STATE_CONNECTING) { |
| return false; |
| } |
| Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.HOLD_CALL); |
| mStateMachine.sendMessage(msg); |
| return true; |
| } |
| |
| boolean acceptCall(BluetoothDevice device, int flag) { |
| enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); |
| int connectionState = mStateMachine.getConnectionState(device); |
| if (connectionState != BluetoothProfile.STATE_CONNECTED && |
| connectionState != BluetoothProfile.STATE_CONNECTING) { |
| return false; |
| } |
| Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.ACCEPT_CALL); |
| msg.arg1 = flag; |
| mStateMachine.sendMessage(msg); |
| return true; |
| } |
| |
| boolean rejectCall(BluetoothDevice device) { |
| enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); |
| int connectionState = mStateMachine.getConnectionState(device); |
| if (connectionState != BluetoothProfile.STATE_CONNECTED && |
| connectionState != BluetoothProfile.STATE_CONNECTING) { |
| return false; |
| } |
| |
| Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.REJECT_CALL); |
| mStateMachine.sendMessage(msg); |
| return true; |
| } |
| |
| boolean terminateCall(BluetoothDevice device, int index) { |
| enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); |
| int connectionState = mStateMachine.getConnectionState(device); |
| if (connectionState != BluetoothProfile.STATE_CONNECTED && |
| connectionState != BluetoothProfile.STATE_CONNECTING) { |
| return false; |
| } |
| |
| Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.TERMINATE_CALL); |
| msg.arg1 = index; |
| mStateMachine.sendMessage(msg); |
| return true; |
| } |
| |
| boolean enterPrivateMode(BluetoothDevice device, int index) { |
| enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); |
| int connectionState = mStateMachine.getConnectionState(device); |
| if (connectionState != BluetoothProfile.STATE_CONNECTED && |
| connectionState != BluetoothProfile.STATE_CONNECTING) { |
| return false; |
| } |
| |
| Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.ENTER_PRIVATE_MODE); |
| msg.arg1 = index; |
| mStateMachine.sendMessage(msg); |
| return true; |
| } |
| |
| boolean redial(BluetoothDevice device) { |
| enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); |
| int connectionState = mStateMachine.getConnectionState(device); |
| if (connectionState != BluetoothProfile.STATE_CONNECTED && |
| connectionState != BluetoothProfile.STATE_CONNECTING) { |
| return false; |
| } |
| |
| Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.REDIAL); |
| mStateMachine.sendMessage(msg); |
| return true; |
| } |
| |
| boolean dial(BluetoothDevice device, String number) { |
| enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); |
| int connectionState = mStateMachine.getConnectionState(device); |
| if (connectionState != BluetoothProfile.STATE_CONNECTED && |
| connectionState != BluetoothProfile.STATE_CONNECTING) { |
| return false; |
| } |
| |
| Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.DIAL_NUMBER); |
| msg.obj = number; |
| mStateMachine.sendMessage(msg); |
| return true; |
| } |
| |
| boolean dialMemory(BluetoothDevice device, int location) { |
| enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); |
| int connectionState = mStateMachine.getConnectionState(device); |
| if (connectionState != BluetoothProfile.STATE_CONNECTED && |
| connectionState != BluetoothProfile.STATE_CONNECTING) { |
| return false; |
| } |
| Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.DIAL_MEMORY); |
| msg.arg1 = location; |
| mStateMachine.sendMessage(msg); |
| return true; |
| } |
| |
| public boolean sendDTMF(BluetoothDevice device, byte code) { |
| enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); |
| int connectionState = mStateMachine.getConnectionState(device); |
| if (connectionState != BluetoothProfile.STATE_CONNECTED && |
| connectionState != BluetoothProfile.STATE_CONNECTING) { |
| return false; |
| } |
| Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.SEND_DTMF); |
| msg.arg1 = code; |
| mStateMachine.sendMessage(msg); |
| return true; |
| } |
| |
| public boolean getLastVoiceTagNumber(BluetoothDevice device) { |
| enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); |
| int connectionState = mStateMachine.getConnectionState(device); |
| if (connectionState != BluetoothProfile.STATE_CONNECTED && |
| connectionState != BluetoothProfile.STATE_CONNECTING) { |
| return false; |
| } |
| Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.LAST_VTAG_NUMBER); |
| mStateMachine.sendMessage(msg); |
| return true; |
| } |
| |
| public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) { |
| enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); |
| int connectionState = mStateMachine.getConnectionState(device); |
| if (connectionState != BluetoothProfile.STATE_CONNECTED) { |
| return null; |
| } |
| return mStateMachine.getCurrentCalls(); |
| } |
| |
| public boolean explicitCallTransfer(BluetoothDevice device) { |
| enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); |
| int connectionState = mStateMachine.getConnectionState(device); |
| if (connectionState != BluetoothProfile.STATE_CONNECTED && |
| connectionState != BluetoothProfile.STATE_CONNECTING) { |
| return false; |
| } |
| Message msg = mStateMachine |
| .obtainMessage(HeadsetClientStateMachine.EXPLICIT_CALL_TRANSFER); |
| mStateMachine.sendMessage(msg); |
| return true; |
| } |
| |
| public Bundle getCurrentAgEvents(BluetoothDevice device) { |
| enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); |
| int connectionState = mStateMachine.getConnectionState(device); |
| if (connectionState != BluetoothProfile.STATE_CONNECTED) { |
| return null; |
| } |
| return mStateMachine.getCurrentAgEvents(); |
| } |
| |
| public Bundle getCurrentAgFeatures(BluetoothDevice device) { |
| enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); |
| int connectionState = mStateMachine.getConnectionState(device); |
| if (connectionState != BluetoothProfile.STATE_CONNECTED) { |
| return null; |
| } |
| return mStateMachine.getCurrentAgFeatures(); |
| } |
| |
| @Override |
| public void dump(StringBuilder sb) { |
| super.dump(sb); |
| if (mStateMachine != null) { |
| mStateMachine.dump(sb); |
| } |
| } |
| } |