RK3288 + Android 7.1
本文用于跟踪android获取蓝牙MAC接口实现的代码流程.
Android 提供了标准的接口用来访问蓝牙的MAC地址信息
BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
String addr = bt.getAddress();
String name = bt.getName();//00:11:22:33:44:55
注意权限的申请
SDK接口的BluetoothAdapter源码如下:
|-- frameworks/base/core/java/android/bluetooth/BluetoothAdapter.java
public static synchronized BluetoothAdapter getDefaultAdapter() {
if (sAdapter == null) {
IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
if (b != null) {
IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
sAdapter = new BluetoothAdapter(managerService);
} else {
Log.e(TAG, "Bluetooth binder is null");
}
}
return sAdapter;
}
BluetoothAdapter(IBluetoothManager managerService) {
if (managerService == null) {
throw new IllegalArgumentException("bluetooth manager service is null");
}
try {
mServiceLock.writeLock().lock();
mService = managerService.registerAdapter(mManagerCallback);
} catch (RemoteException e) {
Log.e(TAG, "", e);
} finally {
mServiceLock.writeLock().unlock();
}
mManagerService = managerService;
mLeScanClients = new HashMap<LeScanCallback, ScanCallback>();
mToken = new Binder();
}
public String getAddress() {
try {
return mManagerService.getAddress();
} catch (RemoteException e) {Log.e(TAG, "", e);}
return null;
}
mManagerService服务接口, 由BluetoothService注册到系统服务中
|-- frameworks/base/services/core/java/com/android/server/BluetoothService.java
@Override
public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
publishBinderService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE,
mBluetoothManagerService);
} else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
mBluetoothManagerService.handleOnBootPhase();
}
}
|-- frameworks/base/services/core/java/com/android/server/BluetoothManagerService.java
public String getAddress() {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
"Need BLUETOOTH permission");
if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
(!checkIfCallerIsForegroundUser())) {
Slog.w(TAG,"getAddress(): not allowed for non-active and non system user");
return null;
}
if (mContext.checkCallingOrSelfPermission(Manifest.permission.LOCAL_MAC_ADDRESS)
!= PackageManager.PERMISSION_GRANTED) {
return BluetoothAdapter.DEFAULT_MAC_ADDRESS;
}
try {
mBluetoothLock.readLock().lock();
if (mBluetooth != null) return mBluetooth.getAddress();
} catch (RemoteException e) {
Slog.e(TAG, "getAddress(): Unable to retrieve address remotely. Returning cached address", e);
} finally {
mBluetoothLock.readLock().unlock();
}
// mAddress is accessed from outside.
// It is alright without a lock. Here, bluetooth is off, no other thread is
// changing mAddress
return mAddress;
}
private class BluetoothServiceConnection implements ServiceConnection {
public void onServiceConnected(ComponentName componentName, IBinder service) {
String name = componentName.getClassName();
if (DBG) Slog.d(TAG, "BluetoothServiceConnection: " + name);
Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
msg.arg1 = SERVICE_IBLUETOOTH;
} else if (name.equals("com.android.bluetooth.gatt.GattService")) {
msg.arg1 = SERVICE_IBLUETOOTHGATT;
} else {
Slog.e(TAG, "Unknown service connected: " + name);
return;
}
msg.obj = service;
mHandler.sendMessage(msg);
}
public void onServiceDisconnected(ComponentName componentName) {
// Called if we unexpectedly disconnect.
String name = componentName.getClassName();
if (DBG) Slog.d(TAG, "BluetoothServiceConnection, disconnected: " + name);
Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
if (name.equals("com.android.bluetooth.btservice.AdapterService")) {
msg.arg1 = SERVICE_IBLUETOOTH;
} else if (name.equals("com.android.bluetooth.gatt.GattService")) {
msg.arg1 = SERVICE_IBLUETOOTHGATT;
} else {
Slog.e(TAG, "Unknown service disconnected: " + name);
return;
}
mHandler.sendMessage(msg);
}
}
private class BluetoothHandler extends Handler {
boolean mGetNameAddressOnly = false;
public BluetoothHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_GET_NAME_AND_ADDRESS:
if (DBG) Slog.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS");
try {
mBluetoothLock.writeLock().lock();
if ((mBluetooth == null) && (!mBinding)) {
if (DBG) Slog.d(TAG, "Binding to service to get name and address");
mGetNameAddressOnly = true;
Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS);
Intent i = new Intent(IBluetooth.class.getName());
if (!doBind(i, mConnection,
Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
UserHandle.CURRENT)) {
mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
} else {
mBinding = true;
}
} else if (mBluetooth != null) {
try {
storeNameAndAddress(mBluetooth.getName(),
mBluetooth.getAddress());
} catch (RemoteException re) {
Slog.e(TAG, "Unable to grab names", re);
}
if (mGetNameAddressOnly && !mEnable) {
unbindAndFinish();
}
mGetNameAddressOnly = false;
}
} finally {
mBluetoothLock.writeLock().unlock();
}
break;
//...
case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
{
if (DBG) Slog.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);
IBinder service = (IBinder) msg.obj;
try {
mBluetoothLock.writeLock().lock();
if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service);
onBluetoothGattServiceUp();
break;
} // else must be SERVICE_IBLUETOOTH
//Remove timeout
mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
mBinding = false;
mBluetoothBinder = service;
mBluetooth = IBluetooth.Stub.asInterface(service);
if (!isNameAndAddressSet()) {
Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
mHandler.sendMessage(getMsg);
if (mGetNameAddressOnly) return;
}
try {
boolean enableHciSnoopLog = (Settings.Secure.getInt(mContentResolver,
Settings.Secure.BLUETOOTH_HCI_LOG, 0) == 1);
if (!mBluetooth.configHciSnoopLog(enableHciSnoopLog)) {
Slog.e(TAG,"IBluetooth.configHciSnoopLog return false");
}
} catch (RemoteException e) {
Slog.e(TAG,"Unable to call configHciSnoopLog", e);
}
//Register callback object
try {
mBluetooth.registerCallback(mBluetoothCallback);
} catch (RemoteException re) {
Slog.e(TAG, "Unable to register BluetoothCallback",re);
}
//Inform BluetoothAdapter instances that service is up
sendBluetoothServiceUpCallback();
//Do enable request
try {
if (mQuietEnable == false) {
if (!mBluetooth.enable()) {
Slog.e(TAG,"IBluetooth.enable() returned false");
}
} else {
if (!mBluetooth.enableNoAutoConnect()) {
Slog.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
}
}
} catch (RemoteException e) {
Slog.e(TAG,"Unable to call enable()",e);
}
} finally {
mBluetoothLock.writeLock().unlock();
}
if (!mEnable) {
waitForOnOff(true, false);
handleDisable();
waitForOnOff(false, false);
}
break;
}
与HAL层的通讯实现放在蓝牙的APP中, 由蓝牙APP提供BIND服务:
|-- packages/apps/Bluetooth/AndroidManifest.xml
<intent-filter>
<action android:name="android.bluetooth.IBluetooth" />
intent-filter>
service>
|-- packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java
private static class AdapterServiceBinder extends IBluetooth.Stub {
//...
public String getAddress() {
if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
(!Utils.checkCallerAllowManagedProfiles(mService))) {
Log.w(TAG, "getAddress() - Not allowed for non-active user and non system user");
return null;
}
AdapterService service = getService();
if (service == null) return null;
return service.getAddress();
}
//...
}
String getAddress() {
enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
String addrString = null;
byte[] address = mAdapterProperties.getAddress();
return Utils.getAddressStringFromByte(address);
}
|-- packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterProperties.java
/**
* @return the mAddress
*/
byte[] getAddress() {
return mAddress;
}
void adapterPropertyChangedCallback(int[] types, byte[][] values) {
Intent intent;
int type;
byte[] val;
for (int i = 0; i < types.length; i++) {
val = values[i];
type = types[i];
infoLog("adapterPropertyChangedCallback with type:" + type + " len:" + val.length);
synchronized (mObject) {
switch (type) {
case AbstractionLayer.BT_PROPERTY_BDNAME:
mName = new String(val);
intent = new Intent(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
intent.putExtra(BluetoothAdapter.EXTRA_LOCAL_NAME, mName);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mService.sendBroadcastAsUser(intent, UserHandle.ALL,
mService.BLUETOOTH_PERM);
debugLog("Name is: " + mName);
break;
case AbstractionLayer.BT_PROPERTY_BDADDR:
mAddress = val;
debugLog("Address is:" + Utils.getAddressStringFromByte(mAddress));
break;
}
|-- packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp
static bt_callbacks_t sBluetoothCallbacks = {
sizeof(sBluetoothCallbacks),
adapter_state_change_callback,
adapter_properties_callback,
remote_device_properties_callback,
device_found_callback,
discovery_state_changed_callback,
pin_request_callback,
ssp_request_callback,
bond_state_changed_callback,
acl_state_changed_callback,
callback_thread_event,
dut_mode_recv_callback,
le_test_mode_recv_callback,
energy_info_recv_callback
};
static bool initNative(JNIEnv* env, jobject obj) {
ALOGV("%s:",__FUNCTION__);
android_bluetooth_UidTraffic.clazz = (jclass) env->NewGlobalRef(
env->FindClass("android/bluetooth/UidTraffic"));
sJniAdapterServiceObj = env->NewGlobalRef(obj);
sJniCallbacksObj = env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField));
if (sBluetoothInterface) {
int ret = sBluetoothInterface->init(&sBluetoothCallbacks);
if (ret != BT_STATUS_SUCCESS) {
ALOGE("Error while setting the callbacks: %d\n", ret);
sBluetoothInterface = NULL;
return JNI_FALSE;
}
ret = sBluetoothInterface->set_os_callouts(&sBluetoothOsCallouts);
if (ret != BT_STATUS_SUCCESS) {
ALOGE("Error while setting Bluetooth callouts: %d\n", ret);
sBluetoothInterface->cleanup();
sBluetoothInterface = NULL;
return JNI_FALSE;
}
if ( (sBluetoothSocketInterface = (btsock_interface_t *)
sBluetoothInterface->get_profile_interface(BT_PROFILE_SOCKETS_ID)) == NULL) {
ALOGE("Error getting socket interface");
}
return JNI_TRUE;
}
return JNI_FALSE;
}
static void adapter_properties_callback(bt_status_t status, int num_properties,
bt_property_t *properties) {
jobjectArray props;
jintArray types;
jbyteArray val;
jclass mclass;
if (!checkCallbackThread()) {
ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
return;
}
ALOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties);
if (status != BT_STATUS_SUCCESS) {
ALOGE("%s: Status %d is incorrect", __FUNCTION__, status);
return;
}
val = (jbyteArray) callbackEnv->NewByteArray(num_properties);
if (val == NULL) {
ALOGE("%s: Error allocating byteArray", __FUNCTION__);
return;
}
mclass = callbackEnv->GetObjectClass(val);
/* (BT) Initialize the jobjectArray and jintArray here itself and send the
initialized array pointers alone to get_properties */
props = callbackEnv->NewObjectArray(num_properties, mclass,
NULL);
if (props == NULL) {
ALOGE("%s: Error allocating object Array for properties", __FUNCTION__);
return;
}
types = (jintArray)callbackEnv->NewIntArray(num_properties);
if (types == NULL) {
ALOGE("%s: Error allocating int Array for values", __FUNCTION__);
return;
}
// Delete the reference to val and mclass
callbackEnv->DeleteLocalRef(mclass);
callbackEnv->DeleteLocalRef(val);
if (get_properties(num_properties, properties, &types, &props) < 0) {
if (props) callbackEnv->DeleteLocalRef(props);
if (types) callbackEnv->DeleteLocalRef(types);
return;
}
callbackEnv->CallVoidMethod(sJniCallbacksObj, method_adapterPropertyChangedCallback, types,
props);
checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
callbackEnv->DeleteLocalRef(props);
callbackEnv->DeleteLocalRef(types);
return;
}
在系统中存在两个hardware 的lib库:
rk3288:/ # ll /system/lib/hw/bluetooth*
-rw-r--r-- 1 root root 1272568 2019-11-25 15:47 /system/lib/hw/bluetooth.default.so
-rw-r--r-- 1 root root 1334308 2020-05-07 15:45 /system/lib/hw/bluetooth_rtk.default.so
主板使用的是8723的模块, 所以对应使用的是:bluetooth_rtk.default.so
|-- hardware/realtek/rtkbt/code/bt/btif/src/bluetooth.c
static int init(bt_callbacks_t *callbacks) {
LOG_INFO(LOG_TAG, "%s", __func__);
if (interface_ready())
return BT_STATUS_DONE;
#ifdef BLUEDROID_DEBUG
allocation_tracker_init();
#endif
bt_hal_cbacks = callbacks;
stack_manager_get_interface()->init_stack();
btif_debug_init();
#ifdef BLUETOOTH_RTK_API
uipc_inited = FALSE;
#endif
return BT_STATUS_SUCCESS;
}
|-- hardware/realtek/rtkbt/code/bt/btif/src/btif_core.c
bt_status_t btif_init_bluetooth() {
LOG_DEBUG(LOG_TAG, "%s", __func__);
bte_main_boot_entry();
/* As part of the init, fetch the local BD ADDR */
memset(&btif_local_bd_addr, 0, sizeof(bt_bdaddr_t));
btif_fetch_local_bdaddr(&btif_local_bd_addr);
bt_jni_workqueue_thread = thread_new(BT_JNI_WORKQUEUE_NAME);
if (bt_jni_workqueue_thread == NULL) {
LOG_ERROR(LOG_TAG, "%s Unable to create thread %s", __func__, BT_JNI_WORKQUEUE_NAME);
goto error_exit;
}
// Associate this workqueue thread with jni.
btif_transfer_context(btif_jni_associate, 0, NULL, 0, NULL);
return BT_STATUS_SUCCESS;
error_exit:;
thread_free(bt_jni_workqueue_thread);
bt_jni_workqueue_thread = NULL;
return BT_STATUS_FAIL;
}
static void btif_fetch_local_bdaddr(bt_bdaddr_t *local_addr)
{
char val[PROPERTY_VALUE_MAX] = {0};
uint8_t valid_bda = FALSE;
int val_size = 0;
int vflash_fd;
const uint8_t null_bdaddr[BD_ADDR_LEN] = {0,0,0,0,0,0};
if ((vflash_fd = open("/dev/vflash", O_RDONLY)) != -1)
{
char bd_addr[6] = {0};
BTIF_TRACE_ERROR("Get local bdaddr from vflash");
#define VFLASH_READ_BDA 0x01
if(ioctl(vflash_fd, VFLASH_READ_BDA, (unsigned long)bd_addr) >= 0
&& memcmp(bd_addr, null_bdaddr, BD_ADDR_LEN) != 0)
{
local_addr->address[0] = bd_addr[5];
local_addr->address[1] = bd_addr[4];
local_addr->address[2] = bd_addr[3];
local_addr->address[3] = bd_addr[2];
local_addr->address[4] = bd_addr[1];
local_addr->address[5] = bd_addr[0];
//local_addr->address[0] = local_addr->address[0] << 1;
valid_bda = TRUE;
BTIF_TRACE_DEBUG("Got Factory BDA %02X:%02X:%02X:%02X:%02X:%02X",
local_addr->address[0], local_addr->address[1], local_addr->address[2],
local_addr->address[3], local_addr->address[4], local_addr->address[5]);
}
close(vflash_fd);
}
//...
}
读取MAC的优先级如下: