Skip to content

Commit d5b58f6

Browse files
Bhakthavatsala RaghavendraMocaRafee
authored andcommitted
Bluetooth: Add BC profile entry
Add BC profile entry and override constructor for CachedBluetoothDevice CRs-fixed: 2853618 Change-Id: I750139a482280ce3409989582ffad50aed20e081
1 parent 251e249 commit d5b58f6

6 files changed

Lines changed: 260 additions & 3 deletions

File tree

core/java/android/bluetooth/BluetoothAdapter.java

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@
6666
import java.util.concurrent.Executor;
6767
import java.util.concurrent.TimeoutException;
6868
import java.util.concurrent.locks.ReentrantReadWriteLock;
69+
import java.lang.reflect.Method;
70+
import java.lang.reflect.Constructor;
71+
import java.lang.reflect.InvocationTargetException;
6972

7073
/**
7174
* Represents the local device Bluetooth adapter. The {@link BluetoothAdapter}
@@ -2780,6 +2783,92 @@ public Pair<byte[], byte[]> readOutOfBandData() {
27802783
return null;
27812784
}
27822785

2786+
private void closeBCProfile(BluetoothProfile proxy) {
2787+
Class<?> bshClass = null;
2788+
Method bshClose = null;
2789+
try {
2790+
bshClass = Class.forName("android.bluetooth.BluetoothSyncHelper");
2791+
} catch (ClassNotFoundException ex) {
2792+
Log.e(TAG, "no BSH: exists");
2793+
bshClass = null;
2794+
}
2795+
if (bshClass != null) {
2796+
Log.d(TAG, "Able to get BSH class handle");
2797+
try {
2798+
bshClose = bshClass.getDeclaredMethod("close", null);
2799+
} catch (NoSuchMethodException e) {
2800+
Log.e(TAG, "no BSH:isSupported method exists");
2801+
}
2802+
if (bshClose != null) {
2803+
try {
2804+
bshClose.invoke(proxy, null);
2805+
} catch(IllegalAccessException e) {
2806+
Log.e(TAG, "bshClose IllegalAccessException");
2807+
} catch (InvocationTargetException e) {
2808+
Log.e(TAG, "bshClose InvocationTargetException");
2809+
}
2810+
}
2811+
}
2812+
Log.d(TAG, "CloseBCProfile returns");
2813+
}
2814+
2815+
private boolean getBCProfile(Context context, BluetoothProfile.ServiceListener sl) {
2816+
boolean ret = true;
2817+
boolean isProfileSupported = false;
2818+
Class<?> bshClass = null;
2819+
Method bshSupported = null;
2820+
Constructor bshCons = null;
2821+
Object bshObj = null;
2822+
try {
2823+
bshClass = Class.forName("android.bluetooth.BluetoothSyncHelper");
2824+
} catch (ClassNotFoundException ex) {
2825+
Log.e(TAG, "no BSH: exists");
2826+
bshClass = null;
2827+
}
2828+
if (bshClass != null) {
2829+
Log.d(TAG, "Able to get BSH class handle");
2830+
try {
2831+
bshSupported = bshClass.getDeclaredMethod("isSupported", null);
2832+
} catch (NoSuchMethodException e) {
2833+
Log.e(TAG, "no BSH:isSupported method exists: gdm");
2834+
}
2835+
try {
2836+
bshCons =
2837+
bshClass.getDeclaredConstructor(
2838+
new Class[]{Context.class,
2839+
BluetoothProfile.ServiceListener.class});
2840+
} catch (NoSuchMethodException ex) {
2841+
Log.e(TAG, "bshCons: NoSuchMethodException: gdm" + ex);
2842+
}
2843+
}
2844+
if (bshClass != null && bshSupported != null && bshCons != null) {
2845+
try {
2846+
isProfileSupported = (boolean)bshSupported.invoke(null, null);
2847+
} catch(IllegalAccessException e) {
2848+
Log.e(TAG, "BSH:isSupported IllegalAccessException");
2849+
} catch (InvocationTargetException e) {
2850+
Log.e(TAG, "BSH:isSupported InvocationTargetException");
2851+
}
2852+
if (isProfileSupported) {
2853+
try {
2854+
bshObj = bshCons.newInstance(
2855+
context, sl);
2856+
} catch (InstantiationException ex) {
2857+
Log.e(TAG, "bshCons InstantiationException:" + ex);
2858+
} catch (IllegalAccessException ex) {
2859+
Log.e(TAG, "bshCons InstantiationException:" + ex);
2860+
} catch (InvocationTargetException ex) {
2861+
Log.e(TAG, "bshCons InvocationTargetException:" + ex);
2862+
}
2863+
}
2864+
}
2865+
if (bshObj == null) {
2866+
ret = false;
2867+
}
2868+
Log.d(TAG, "getBCService returns" + ret);
2869+
return ret;
2870+
}
2871+
27832872
/**
27842873
* Get the profile proxy object associated with the profile.
27852874
*
@@ -2844,6 +2933,8 @@ public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener
28442933
} else if (profile == BluetoothProfile.HID_DEVICE) {
28452934
BluetoothHidDevice hidDevice = new BluetoothHidDevice(context, listener);
28462935
return true;
2936+
} else if (profile == BluetoothProfile.BC_PROFILE) {
2937+
return getBCProfile(context, listener);
28472938
} else if (profile == BluetoothProfile.HEARING_AID) {
28482939
if (isHearingAidProfileSupported()) {
28492940
BluetoothHearingAid hearingAid = new BluetoothHearingAid(context, listener);
@@ -2931,6 +3022,9 @@ public void closeProfileProxy(int profile, BluetoothProfile proxy) {
29313022
BluetoothHidDevice hidDevice = (BluetoothHidDevice) proxy;
29323023
hidDevice.close();
29333024
break;
3025+
case BluetoothProfile.BC_PROFILE:
3026+
closeBCProfile(proxy);
3027+
break;
29343028
case BluetoothProfile.HEARING_AID:
29353029
BluetoothHearingAid hearingAid = (BluetoothHearingAid) proxy;
29363030
hearingAid.close();

core/java/android/bluetooth/BluetoothProfile.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,13 +205,31 @@ public interface BluetoothProfile {
205205
*/
206206
int HEARING_AID = 21;
207207

208+
/**
209+
* BC_PROFILE
210+
* @hide
211+
*/
212+
public static final int BC_PROFILE = 24;
213+
214+
/**
215+
* PC_PROFILE
216+
* @hide
217+
*/
218+
public static final int PC_PROFILE = 25;
219+
220+
/**
221+
* CC_SERVER
222+
* @hide
223+
*/
224+
public static final int CC_SERVER = 26;
225+
208226
/**
209227
* Max profile ID. This value should be updated whenever a new profile is added to match
210228
* the largest value assigned to a profile.
211229
*
212230
* @hide
213231
*/
214-
int MAX_PROFILE_ID = 21;
232+
int MAX_PROFILE_ID = 26;
215233

216234
/**
217235
* Default priority for devices that we try to auto-connect to and
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
Copyright (c) 2020, The Linux Foundation. All rights reserved.
4+
5+
Redistribution and use in source and binary forms, with or without
6+
modification, are permitted provided that the following conditions are
7+
met:
8+
* Redistributions of source code must retain the above copyright
9+
notice, this list of conditions and the following disclaimer.
10+
* Redistributions in binary form must reproduce the above
11+
copyright notice, this list of conditions and the following
12+
disclaimer in the documentation and/or other materials provided
13+
with the distribution.
14+
* Neither the name of The Linux Foundation nor the names of its
15+
contributors may be used to endorse or promote products derived
16+
from this software without specific prior written permission.
17+
18+
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
19+
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
21+
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22+
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23+
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24+
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25+
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26+
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27+
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
28+
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
-->
30+
31+
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
32+
<!-- Bluetooth settings. The user-visible string that is used whenever
33+
referring to BC profile. -->
34+
<string name="bluetooth_profile_bc">BC Profile</string>
35+
<!-- Bluetooth settings. Connection options screen.
36+
The summary for the profile checkbox preference when BC is connected. -->
37+
<string name="bluetooth_bc_profile_summary_connected">Connected to BA server
38+
</string>
39+
<!-- Bluetooth settings. Connection options screen.
40+
The summary for the BC checkbox preference that describes how checking it
41+
will set the BC profile as preferred. -->
42+
<string name="bluetooth_bc_profile_summary_use_for">Use for BA</string>
43+
</resources>

packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
import java.util.Objects;
4545
import java.util.Set;
4646
import java.util.concurrent.CopyOnWriteArrayList;
47+
import java.lang.reflect.Constructor;
48+
import java.lang.reflect.InvocationTargetException;
4749

4850
/**
4951
* BluetoothEventManager receives broadcasts and callbacks from the Bluetooth
@@ -63,6 +65,8 @@ public class BluetoothEventManager {
6365
private final android.os.Handler mReceiverHandler;
6466
private final UserHandle mUserHandle;
6567
private final Context mContext;
68+
private final String ACT_BROADCAST_SOURCE_INFO =
69+
"android.bluetooth.BroadcastAudioSAManager.action.BROADCAST_SOURCE_INFO";
6670

6771
interface Handler {
6872
void onReceive(Context context, Intent intent, BluetoothDevice device);
@@ -130,6 +134,23 @@ interface Handler {
130134
addHandler(BluetoothDevice.ACTION_ACL_CONNECTED, new AclStateChangedHandler());
131135
addHandler(BluetoothDevice.ACTION_ACL_DISCONNECTED, new AclStateChangedHandler());
132136
addHandler(BluetoothA2dp.ACTION_CODEC_CONFIG_CHANGED, new A2dpCodecConfigChangedHandler());
137+
Object sourceInfoHandler = null;
138+
try {
139+
Class<?> classSourceInfoHandler =
140+
Class.forName("com.android.settingslib.bluetooth.BroadcastSourceInfoHandler");
141+
Constructor ctor;
142+
ctor = classSourceInfoHandler.getDeclaredConstructor(
143+
new Class[] {CachedBluetoothDeviceManager.class});
144+
sourceInfoHandler = ctor.newInstance(mDeviceManager);
145+
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException
146+
| InstantiationException | InvocationTargetException e) {
147+
e.printStackTrace();
148+
}
149+
if (sourceInfoHandler != null) {
150+
Log.d(TAG, "adding SourceInfo Handler");
151+
addHandler(ACT_BROADCAST_SOURCE_INFO,
152+
(Handler)sourceInfoHandler);
153+
}
133154

134155
registerAdapterIntentReceiver();
135156

packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@
4343
import java.util.Collection;
4444
import java.util.List;
4545
import java.util.concurrent.CopyOnWriteArrayList;
46+
import java.lang.reflect.Constructor;
47+
import java.lang.reflect.Method;
48+
import java.lang.reflect.InvocationTargetException;
4649

4750
/**
4851
* CachedBluetoothDevice represents a remote Bluetooth device. It contains
@@ -138,6 +141,17 @@ public void handleMessage(Message msg) {
138141
mTwspBatteryLevel = -1;
139142
}
140143

144+
CachedBluetoothDevice(CachedBluetoothDevice cachedDevice) {
145+
mContext = cachedDevice.mContext;
146+
mLocalAdapter = BluetoothAdapter.getDefaultAdapter();
147+
mProfileManager = cachedDevice.mProfileManager;
148+
mDevice = cachedDevice.mDevice;
149+
fillData();
150+
mHiSyncId = BluetoothHearingAid.HI_SYNC_ID_INVALID;
151+
mTwspBatteryState = -1;
152+
mTwspBatteryLevel = -1;
153+
}
154+
141155
/* Gets Device for seondary TWS device
142156
* @param mDevice Primary TWS device to get secondary
143157
* @return Description of the device
@@ -774,13 +788,49 @@ public List<LocalBluetoothProfile> getProfiles() {
774788
return new ArrayList<>(mProfiles);
775789
}
776790

791+
public boolean isBASeeker() {
792+
if (mDevice == null) {
793+
Log.e(TAG, "isBASeeker: mDevice is null");
794+
return false;
795+
}
796+
boolean ret = false;
797+
Class<?> bCProfileClass = null;
798+
String BC_PROFILE_CLASS = "com.android.settingslib.bluetooth.BCProfile";
799+
Method baSeeker;
800+
try {
801+
bCProfileClass = Class.forName(BC_PROFILE_CLASS);
802+
baSeeker = bCProfileClass.getDeclaredMethod("isBASeeker", BluetoothDevice.class);
803+
ret = (boolean)baSeeker.invoke(null, mDevice);
804+
} catch (ClassNotFoundException | NoSuchMethodException
805+
| IllegalAccessException | InvocationTargetException e) {
806+
e.printStackTrace();
807+
}
808+
return ret;
809+
}
810+
777811
public List<LocalBluetoothProfile> getConnectableProfiles() {
778812
List<LocalBluetoothProfile> connectableProfiles =
779813
new ArrayList<LocalBluetoothProfile>();
814+
Class<?> bCProfileClass = null;
815+
String BC_PROFILE_CLASS = "com.android.settingslib.bluetooth.BCProfile";
816+
try {
817+
bCProfileClass = Class.forName(BC_PROFILE_CLASS);
818+
} catch (ClassNotFoundException ex) {
819+
Log.e(TAG, "no BCProfileClass: exists");
820+
bCProfileClass = null;
821+
}
780822
synchronized (mProfileLock) {
781823
for (LocalBluetoothProfile profile : mProfiles) {
782-
if (profile.accessProfileEnabled()) {
783-
connectableProfiles.add(profile);
824+
if (bCProfileClass != null && bCProfileClass.isInstance(profile)) {
825+
if (isBASeeker()) {
826+
connectableProfiles.add(profile);
827+
} else {
828+
Log.d(TAG, "BC profile is not enabled for" + mDevice);
829+
}
830+
} else {
831+
if (profile.accessProfileEnabled()) {
832+
connectableProfiles.add(profile);
833+
}
784834
}
785835
}
786836
}

packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
import java.util.List;
5050
import java.util.Map;
5151
import java.util.concurrent.CopyOnWriteArrayList;
52+
import java.lang.reflect.Constructor;
53+
import java.lang.reflect.InvocationTargetException;
5254

5355

5456
/**
@@ -94,6 +96,7 @@ public interface ServiceListener {
9496
private MapProfile mMapProfile;
9597
private MapClientProfile mMapClientProfile;
9698
private HidProfile mHidProfile;
99+
private LocalBluetoothProfile mBCProfile;
97100
private HidDeviceProfile mHidDeviceProfile;
98101
private OppProfile mOppProfile;
99102
private PanProfile mPanProfile;
@@ -102,6 +105,8 @@ public interface ServiceListener {
102105
private HearingAidProfile mHearingAidProfile;
103106
private SapProfile mSapProfile;
104107

108+
private static final String BC_CONNECTION_STATE_CHANGED =
109+
"android.bluetooth.bc.profile.action.CONNECTION_STATE_CHANGED";
105110
/**
106111
* Mapping from profile name, e.g. "HEADSET" to profile object.
107112
*/
@@ -213,6 +218,23 @@ void updateLocalProfiles() {
213218
addProfile(mPbapClientProfile, PbapClientProfile.NAME,
214219
BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED);
215220
}
221+
if (mBCProfile == null && supportedList.contains(BluetoothProfile.BC_PROFILE)) {
222+
if (DEBUG) Log.d(TAG, "Adding local BC profile");
223+
try {
224+
Class<?> classBCProfile =
225+
Class.forName("com.android.settingslib.bluetooth.BCProfile");
226+
Constructor ctor;
227+
ctor = classBCProfile.getDeclaredConstructor(new Class[] {Context.class,
228+
CachedBluetoothDeviceManager.class,
229+
LocalBluetoothProfileManager.class});
230+
mBCProfile = (LocalBluetoothProfile)ctor.newInstance(mContext, mDeviceManager, this);
231+
addProfile(mBCProfile, "BCProfile",
232+
BC_CONNECTION_STATE_CHANGED);
233+
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException
234+
| InstantiationException | InvocationTargetException e) {
235+
e.printStackTrace();
236+
}
237+
}
216238
if (mSapProfile == null && supportedList.contains(BluetoothProfile.SAP)) {
217239
if (DEBUG) {
218240
Log.d(TAG, "Adding local SAP profile");
@@ -446,6 +468,10 @@ public HearingAidProfile getHearingAidProfile() {
446468
return mHearingAidProfile;
447469
}
448470

471+
public LocalBluetoothProfile getBCProfile() {
472+
Log.d(TAG, "getBCProfile returning: " + mBCProfile);
473+
return mBCProfile;
474+
}
449475
@VisibleForTesting
450476
HidProfile getHidProfile() {
451477
return mHidProfile;
@@ -570,6 +596,11 @@ synchronized void updateProfiles(ParcelUuid[] uuids, ParcelUuid[] localUuids,
570596
removedProfiles.remove(mSapProfile);
571597
}
572598

599+
if (mBCProfile != null) {
600+
profiles.add(mBCProfile);
601+
removedProfiles.remove(mBCProfile);
602+
if(DEBUG) Log.d(TAG, "BC profile removed");
603+
}
573604
if (DEBUG) {
574605
Log.d(TAG,"New Profiles" + profiles.toString());
575606
}

0 commit comments

Comments
 (0)