Loading android/app/AndroidManifest.xml +13 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED"/> <uses-permission android:name="android.permission.BLUETOOTH_MAP"/> <uses-permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE" /> <uses-permission android:name="android.permission.DUMP"/> <uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> Loading Loading @@ -424,5 +425,17 @@ <meta-data android:name="android.accounts.AccountAuthenticator" android:resource="@xml/authenticator"/> </service> <service android:name=".hfp.BluetoothInCallService" android:permission="android.permission.BIND_INCALL_SERVICE" android:process="@string/process" android:enabled="@bool/profile_supported_hfp_incallservice" android:exported="true"> <meta-data android:name="android.telecom.IN_CALL_SERVICE_RINGING" android:value="true" /> <intent-filter> <action android:name="android.telecom.InCallService"/> </intent-filter> </service> </application> </manifest> android/app/res/values/config.xml +1 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ <bool name="profile_supported_a2dp_sink">false</bool> <bool name="profile_supported_hs_hfp">true</bool> <bool name="profile_supported_hfpclient">false</bool> <bool name="profile_supported_hfp_incallservice">true</bool> <bool name="profile_supported_hid_host">true</bool> <bool name="profile_supported_opp">true</bool> <bool name="profile_supported_pan">true</bool> Loading android/app/src/com/android/bluetooth/btservice/AdapterState.java +26 −0 Original line number Diff line number Diff line Loading @@ -17,9 +17,13 @@ package com.android.bluetooth.btservice; import android.bluetooth.BluetoothAdapter; import android.content.ComponentName; import android.content.pm.PackageManager; import android.os.Message; import android.util.Log; import com.android.bluetooth.R; import com.android.bluetooth.hfp.BluetoothInCallService; import com.android.bluetooth.statemachine.State; import com.android.bluetooth.statemachine.StateMachine; Loading Loading @@ -75,6 +79,10 @@ final class AdapterState extends StateMachine { static final int BREDR_START_TIMEOUT_DELAY = 4000; static final int BREDR_STOP_TIMEOUT_DELAY = 4000; static final ComponentName BLUETOOTH_INCALLSERVICE_COMPONENT = new ComponentName(R.class.getPackage().getName(), BluetoothInCallService.class.getCanonicalName()); private AdapterService mAdapterService; private TurningOnState mTurningOnState = new TurningOnState(); private TurningBleOnState mTurningBleOnState = new TurningBleOnState(); Loading Loading @@ -222,6 +230,24 @@ final class AdapterState extends StateMachine { return BluetoothAdapter.STATE_ON; } @Override public void enter() { super.enter(); mAdapterService.getPackageManager().setComponentEnabledSetting( BLUETOOTH_INCALLSERVICE_COMPONENT, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); } @Override public void exit() { mAdapterService.getPackageManager().setComponentEnabledSetting( BLUETOOTH_INCALLSERVICE_COMPONENT, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); super.exit(); } @Override public boolean processMessage(Message msg) { switch (msg.what) { Loading android/app/src/com/android/bluetooth/hfp/BluetoothCall.java 0 → 100644 +317 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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.hfp; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.telecom.Call; import android.telecom.GatewayInfo; import android.telecom.InCallService; import android.telecom.PhoneAccountHandle; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.List; /** * A proxy class of android.telecom.Call that * 1) facilitates testing of the BluetoothInCallService class; We can't mock the final class * Call directly; * 2) Some helper functions, to let Call have same methods as com.android.server.telecom.Call * * This is necessary due to the "final" attribute of the Call class. In order to * test the correct functioning of the BluetoothInCallService class, the final class must be put * into a container that can be mocked correctly. */ @VisibleForTesting public class BluetoothCall { private Call mCall; public Call getCall() { return mCall; } public void setCall(Call call) { mCall = call; } public BluetoothCall(Call call) { mCall = call; } public String getRemainingPostDialSequence() { return mCall.getRemainingPostDialSequence(); } public void answer(int videoState) { mCall.answer(videoState); } public void deflect(Uri address) { mCall.deflect(address); } public void reject(boolean rejectWithMessage, String textMessage) { mCall.reject(rejectWithMessage, textMessage); } public void disconnect() { mCall.disconnect(); } public void hold() { mCall.hold(); } public void unhold() { mCall.unhold(); } public void enterBackgroundAudioProcessing() { mCall.enterBackgroundAudioProcessing(); } public void exitBackgroundAudioProcessing(boolean shouldRing) { mCall.exitBackgroundAudioProcessing(shouldRing); } public void playDtmfTone(char digit) { mCall.playDtmfTone(digit); } public void stopDtmfTone() { mCall.stopDtmfTone(); } public void postDialContinue(boolean proceed) { mCall.postDialContinue(proceed); } public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) { mCall.phoneAccountSelected(accountHandle, setDefault); } public void conference(BluetoothCall callToConferenceWith) { if (callToConferenceWith != null) { mCall.conference(callToConferenceWith.getCall()); } } public void splitFromConference() { mCall.splitFromConference(); } public void mergeConference() { mCall.mergeConference(); } public void swapConference() { mCall.swapConference(); } public void pullExternalCall() { mCall.pullExternalCall(); } public void sendCallEvent(String event, Bundle extras) { mCall.sendCallEvent(event, extras); } public void sendRttRequest() { mCall.sendRttRequest(); } public void respondToRttRequest(int id, boolean accept) { mCall.respondToRttRequest(id, accept); } public void handoverTo(PhoneAccountHandle toHandle, int videoState, Bundle extras) { mCall.handoverTo(toHandle, videoState, extras); } public void stopRtt() { mCall.stopRtt(); } public void putExtras(Bundle extras) { mCall.putExtras(extras); } public void putExtra(String key, boolean value) { mCall.putExtra(key, value); } public void putExtra(String key, int value) { mCall.putExtra(key, value); } public void putExtra(String key, String value) { mCall.putExtra(key, value); } public void removeExtras(List<String> keys) { mCall.removeExtras(keys); } public void removeExtras(String... keys) { mCall.removeExtras(keys); } public String getParentId() { Call parent = mCall.getParent(); if (parent != null) { return parent.getDetails().getTelecomCallId(); } return null; } public List<String> getChildrenIds() { return getIds(mCall.getChildren()); } public List<String> getConferenceableCalls() { return getIds(mCall.getConferenceableCalls()); } public int getState() { return mCall.getState(); } public List<String> getCannedTextResponses() { return mCall.getCannedTextResponses(); } public InCallService.VideoCall getVideoCall() { return mCall.getVideoCall(); } public Call.Details getDetails() { return mCall.getDetails(); } public Call.RttCall getRttCall() { return mCall.getRttCall(); } public boolean isRttActive() { return mCall.isRttActive(); } public void registerCallback(Call.Callback callback) { mCall.registerCallback(callback); } public void registerCallback(Call.Callback callback, Handler handler) { mCall.registerCallback(callback, handler); } public void unregisterCallback(Call.Callback callback) { mCall.unregisterCallback(callback); } public String toString() { String string = mCall.toString(); return string == null ? "" : string; } public void addListener(Call.Listener listener) { mCall.addListener(listener); } public void removeListener(Call.Listener listener) { mCall.removeListener(listener); } public String getGenericConferenceActiveChildCallId() { return mCall.getGenericConferenceActiveChildCall().getDetails().getTelecomCallId(); } public String getContactDisplayName() { return mCall.getDetails().getContactDisplayName(); } public PhoneAccountHandle getAccountHandle() { return mCall.getDetails().getAccountHandle(); } public int getVideoState() { return mCall.getDetails().getVideoState(); } public String getCallerDisplayName() { return mCall.getDetails().getCallerDisplayName(); } @Override public boolean equals(Object o) { if (o == null) { return getCall() == null; } return o instanceof BluetoothCall && getCall() == ((BluetoothCall) o).getCall(); } // helper functions public boolean isSilentRingingRequested() { return getDetails().getExtras().getBoolean(Call.EXTRA_SILENT_RINGING_REQUESTED); } public boolean isConference() { return getDetails().hasProperty(Call.Details.PROPERTY_CONFERENCE); } public boolean can(int capability) { return getDetails().can(capability); } public Uri getHandle() { return getDetails().getHandle(); } public GatewayInfo getGatewayInfo() { return getDetails().getGatewayInfo(); } public boolean isIncoming() { return getDetails().getCallDirection() == Call.Details.DIRECTION_INCOMING; } public boolean isExternalCall() { return getDetails().hasProperty(Call.Details.PROPERTY_IS_EXTERNAL_CALL); } public String getTelecomCallId() { return getDetails().getTelecomCallId(); } public boolean wasConferencePreviouslyMerged() { return can(Call.Details.CAPABILITY_SWAP_CONFERENCE) && !can(Call.Details.CAPABILITY_MERGE_CONFERENCE); } public static List<String> getIds(List<Call> calls) { List<String> result = new ArrayList<>(); for (Call call : calls) { if (call != null) { result.add(call.getDetails().getTelecomCallId()); } } return result; } } android/app/src/com/android/bluetooth/hfp/BluetoothHeadsetProxy.java 0 → 100644 +87 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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.hfp; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import java.util.List; /** * A proxy class that facilitates testing of the BluetoothInCallService class. * * This is necessary due to the "final" attribute of the BluetoothHeadset class. In order to * test the correct functioning of the BluetoothInCallService class, the final class must be put * into a container that can be mocked correctly. */ public class BluetoothHeadsetProxy { private BluetoothHeadset mBluetoothHeadset; public BluetoothHeadsetProxy(BluetoothHeadset headset) { mBluetoothHeadset = headset; } public void clccResponse(int index, int direction, int status, int mode, boolean mpty, String number, int type) { mBluetoothHeadset.clccResponse(index, direction, status, mode, mpty, number, type); } public void phoneStateChanged(int numActive, int numHeld, int callState, String number, int type, String name) { mBluetoothHeadset.phoneStateChanged(numActive, numHeld, callState, number, type, name); } public List<BluetoothDevice> getConnectedDevices() { return mBluetoothHeadset.getConnectedDevices(); } public int getConnectionState(BluetoothDevice device) { return mBluetoothHeadset.getConnectionState(device); } public int getAudioState(BluetoothDevice device) { return mBluetoothHeadset.getAudioState(device); } public boolean connectAudio() { return mBluetoothHeadset.connectAudio(); } public boolean setActiveDevice(BluetoothDevice device) { return mBluetoothHeadset.setActiveDevice(device); } public BluetoothDevice getActiveDevice() { return mBluetoothHeadset.getActiveDevice(); } public boolean isAudioOn() { return mBluetoothHeadset.isAudioOn(); } public boolean disconnectAudio() { return mBluetoothHeadset.disconnectAudio(); } public boolean isInbandRingingEnabled() { return mBluetoothHeadset.isInbandRingingEnabled(); } } Loading
android/app/AndroidManifest.xml +13 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED"/> <uses-permission android:name="android.permission.BLUETOOTH_MAP"/> <uses-permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE" /> <uses-permission android:name="android.permission.DUMP"/> <uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> Loading Loading @@ -424,5 +425,17 @@ <meta-data android:name="android.accounts.AccountAuthenticator" android:resource="@xml/authenticator"/> </service> <service android:name=".hfp.BluetoothInCallService" android:permission="android.permission.BIND_INCALL_SERVICE" android:process="@string/process" android:enabled="@bool/profile_supported_hfp_incallservice" android:exported="true"> <meta-data android:name="android.telecom.IN_CALL_SERVICE_RINGING" android:value="true" /> <intent-filter> <action android:name="android.telecom.InCallService"/> </intent-filter> </service> </application> </manifest>
android/app/res/values/config.xml +1 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ <bool name="profile_supported_a2dp_sink">false</bool> <bool name="profile_supported_hs_hfp">true</bool> <bool name="profile_supported_hfpclient">false</bool> <bool name="profile_supported_hfp_incallservice">true</bool> <bool name="profile_supported_hid_host">true</bool> <bool name="profile_supported_opp">true</bool> <bool name="profile_supported_pan">true</bool> Loading
android/app/src/com/android/bluetooth/btservice/AdapterState.java +26 −0 Original line number Diff line number Diff line Loading @@ -17,9 +17,13 @@ package com.android.bluetooth.btservice; import android.bluetooth.BluetoothAdapter; import android.content.ComponentName; import android.content.pm.PackageManager; import android.os.Message; import android.util.Log; import com.android.bluetooth.R; import com.android.bluetooth.hfp.BluetoothInCallService; import com.android.bluetooth.statemachine.State; import com.android.bluetooth.statemachine.StateMachine; Loading Loading @@ -75,6 +79,10 @@ final class AdapterState extends StateMachine { static final int BREDR_START_TIMEOUT_DELAY = 4000; static final int BREDR_STOP_TIMEOUT_DELAY = 4000; static final ComponentName BLUETOOTH_INCALLSERVICE_COMPONENT = new ComponentName(R.class.getPackage().getName(), BluetoothInCallService.class.getCanonicalName()); private AdapterService mAdapterService; private TurningOnState mTurningOnState = new TurningOnState(); private TurningBleOnState mTurningBleOnState = new TurningBleOnState(); Loading Loading @@ -222,6 +230,24 @@ final class AdapterState extends StateMachine { return BluetoothAdapter.STATE_ON; } @Override public void enter() { super.enter(); mAdapterService.getPackageManager().setComponentEnabledSetting( BLUETOOTH_INCALLSERVICE_COMPONENT, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); } @Override public void exit() { mAdapterService.getPackageManager().setComponentEnabledSetting( BLUETOOTH_INCALLSERVICE_COMPONENT, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); super.exit(); } @Override public boolean processMessage(Message msg) { switch (msg.what) { Loading
android/app/src/com/android/bluetooth/hfp/BluetoothCall.java 0 → 100644 +317 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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.hfp; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.telecom.Call; import android.telecom.GatewayInfo; import android.telecom.InCallService; import android.telecom.PhoneAccountHandle; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.List; /** * A proxy class of android.telecom.Call that * 1) facilitates testing of the BluetoothInCallService class; We can't mock the final class * Call directly; * 2) Some helper functions, to let Call have same methods as com.android.server.telecom.Call * * This is necessary due to the "final" attribute of the Call class. In order to * test the correct functioning of the BluetoothInCallService class, the final class must be put * into a container that can be mocked correctly. */ @VisibleForTesting public class BluetoothCall { private Call mCall; public Call getCall() { return mCall; } public void setCall(Call call) { mCall = call; } public BluetoothCall(Call call) { mCall = call; } public String getRemainingPostDialSequence() { return mCall.getRemainingPostDialSequence(); } public void answer(int videoState) { mCall.answer(videoState); } public void deflect(Uri address) { mCall.deflect(address); } public void reject(boolean rejectWithMessage, String textMessage) { mCall.reject(rejectWithMessage, textMessage); } public void disconnect() { mCall.disconnect(); } public void hold() { mCall.hold(); } public void unhold() { mCall.unhold(); } public void enterBackgroundAudioProcessing() { mCall.enterBackgroundAudioProcessing(); } public void exitBackgroundAudioProcessing(boolean shouldRing) { mCall.exitBackgroundAudioProcessing(shouldRing); } public void playDtmfTone(char digit) { mCall.playDtmfTone(digit); } public void stopDtmfTone() { mCall.stopDtmfTone(); } public void postDialContinue(boolean proceed) { mCall.postDialContinue(proceed); } public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) { mCall.phoneAccountSelected(accountHandle, setDefault); } public void conference(BluetoothCall callToConferenceWith) { if (callToConferenceWith != null) { mCall.conference(callToConferenceWith.getCall()); } } public void splitFromConference() { mCall.splitFromConference(); } public void mergeConference() { mCall.mergeConference(); } public void swapConference() { mCall.swapConference(); } public void pullExternalCall() { mCall.pullExternalCall(); } public void sendCallEvent(String event, Bundle extras) { mCall.sendCallEvent(event, extras); } public void sendRttRequest() { mCall.sendRttRequest(); } public void respondToRttRequest(int id, boolean accept) { mCall.respondToRttRequest(id, accept); } public void handoverTo(PhoneAccountHandle toHandle, int videoState, Bundle extras) { mCall.handoverTo(toHandle, videoState, extras); } public void stopRtt() { mCall.stopRtt(); } public void putExtras(Bundle extras) { mCall.putExtras(extras); } public void putExtra(String key, boolean value) { mCall.putExtra(key, value); } public void putExtra(String key, int value) { mCall.putExtra(key, value); } public void putExtra(String key, String value) { mCall.putExtra(key, value); } public void removeExtras(List<String> keys) { mCall.removeExtras(keys); } public void removeExtras(String... keys) { mCall.removeExtras(keys); } public String getParentId() { Call parent = mCall.getParent(); if (parent != null) { return parent.getDetails().getTelecomCallId(); } return null; } public List<String> getChildrenIds() { return getIds(mCall.getChildren()); } public List<String> getConferenceableCalls() { return getIds(mCall.getConferenceableCalls()); } public int getState() { return mCall.getState(); } public List<String> getCannedTextResponses() { return mCall.getCannedTextResponses(); } public InCallService.VideoCall getVideoCall() { return mCall.getVideoCall(); } public Call.Details getDetails() { return mCall.getDetails(); } public Call.RttCall getRttCall() { return mCall.getRttCall(); } public boolean isRttActive() { return mCall.isRttActive(); } public void registerCallback(Call.Callback callback) { mCall.registerCallback(callback); } public void registerCallback(Call.Callback callback, Handler handler) { mCall.registerCallback(callback, handler); } public void unregisterCallback(Call.Callback callback) { mCall.unregisterCallback(callback); } public String toString() { String string = mCall.toString(); return string == null ? "" : string; } public void addListener(Call.Listener listener) { mCall.addListener(listener); } public void removeListener(Call.Listener listener) { mCall.removeListener(listener); } public String getGenericConferenceActiveChildCallId() { return mCall.getGenericConferenceActiveChildCall().getDetails().getTelecomCallId(); } public String getContactDisplayName() { return mCall.getDetails().getContactDisplayName(); } public PhoneAccountHandle getAccountHandle() { return mCall.getDetails().getAccountHandle(); } public int getVideoState() { return mCall.getDetails().getVideoState(); } public String getCallerDisplayName() { return mCall.getDetails().getCallerDisplayName(); } @Override public boolean equals(Object o) { if (o == null) { return getCall() == null; } return o instanceof BluetoothCall && getCall() == ((BluetoothCall) o).getCall(); } // helper functions public boolean isSilentRingingRequested() { return getDetails().getExtras().getBoolean(Call.EXTRA_SILENT_RINGING_REQUESTED); } public boolean isConference() { return getDetails().hasProperty(Call.Details.PROPERTY_CONFERENCE); } public boolean can(int capability) { return getDetails().can(capability); } public Uri getHandle() { return getDetails().getHandle(); } public GatewayInfo getGatewayInfo() { return getDetails().getGatewayInfo(); } public boolean isIncoming() { return getDetails().getCallDirection() == Call.Details.DIRECTION_INCOMING; } public boolean isExternalCall() { return getDetails().hasProperty(Call.Details.PROPERTY_IS_EXTERNAL_CALL); } public String getTelecomCallId() { return getDetails().getTelecomCallId(); } public boolean wasConferencePreviouslyMerged() { return can(Call.Details.CAPABILITY_SWAP_CONFERENCE) && !can(Call.Details.CAPABILITY_MERGE_CONFERENCE); } public static List<String> getIds(List<Call> calls) { List<String> result = new ArrayList<>(); for (Call call : calls) { if (call != null) { result.add(call.getDetails().getTelecomCallId()); } } return result; } }
android/app/src/com/android/bluetooth/hfp/BluetoothHeadsetProxy.java 0 → 100644 +87 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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.hfp; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import java.util.List; /** * A proxy class that facilitates testing of the BluetoothInCallService class. * * This is necessary due to the "final" attribute of the BluetoothHeadset class. In order to * test the correct functioning of the BluetoothInCallService class, the final class must be put * into a container that can be mocked correctly. */ public class BluetoothHeadsetProxy { private BluetoothHeadset mBluetoothHeadset; public BluetoothHeadsetProxy(BluetoothHeadset headset) { mBluetoothHeadset = headset; } public void clccResponse(int index, int direction, int status, int mode, boolean mpty, String number, int type) { mBluetoothHeadset.clccResponse(index, direction, status, mode, mpty, number, type); } public void phoneStateChanged(int numActive, int numHeld, int callState, String number, int type, String name) { mBluetoothHeadset.phoneStateChanged(numActive, numHeld, callState, number, type, name); } public List<BluetoothDevice> getConnectedDevices() { return mBluetoothHeadset.getConnectedDevices(); } public int getConnectionState(BluetoothDevice device) { return mBluetoothHeadset.getConnectionState(device); } public int getAudioState(BluetoothDevice device) { return mBluetoothHeadset.getAudioState(device); } public boolean connectAudio() { return mBluetoothHeadset.connectAudio(); } public boolean setActiveDevice(BluetoothDevice device) { return mBluetoothHeadset.setActiveDevice(device); } public BluetoothDevice getActiveDevice() { return mBluetoothHeadset.getActiveDevice(); } public boolean isAudioOn() { return mBluetoothHeadset.isAudioOn(); } public boolean disconnectAudio() { return mBluetoothHeadset.disconnectAudio(); } public boolean isInbandRingingEnabled() { return mBluetoothHeadset.isInbandRingingEnabled(); } }