您的位置:首页 > 编程语言

代码流程分析二:Settings-蓝牙分析-搜索设备原理

2015-08-12 19:24 429 查看
蓝牙搜索功能http://blog.csdn.net/haozitt/article/details/42971847

(一)设置界面packages\Settings

A:搜索调用的地方:

目录:android\packages\apps\Settings\src\com\android\settings\bluetooth

(1):菜单按钮点击搜索设备,前提条件是bluetoothAdapter.STAT_ON会走startScanning()

public boolean onOptionsItemSelected(MenuItem item) {

switch (item.getItemId()) {

case MENU_ID_SCAN:

if (mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_ON) {

startScanning();

}

return true;

(2):一进onResume延迟一会发送消息查询,是后来加的代码,原生的代码直接在onResume中执行startScanning();

mHandler.sendEmptyMessageDelayed(0, 500);延迟时间

private Handler mHandler = new Handler() {

@Override

public void handleMessage(Message msg) {

if (mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_ON) {

startScanning();

}

}

};

(3):在onResume中updateContent,如果前提bluetoothAdapter.STAT_ON会看没有配对设备,如果没有就会进来startScanning();

如果有就不查询。

if (numberOfPairedDevices == 0) {

preferenceScreen.removePreference(mPairedDevicesCategory);

if (scanState == true) {

mActivityStarted = false;

startScanning();

} else {

if (!mAvailableDevicesCategoryIsPresent) {

getPreferenceScreen().addPreference(mAvailableDevicesCategory);

}

}

}

B:startScanning()方法:

private void startScanning() {

if (isRestrictedAndNotPinProtected()) return;

if (!mAvailableDevicesCategoryIsPresent) {

getPreferenceScreen().addPreference(mAvailableDevicesCategory);

}

mLocalAdapter.startScanning(true);

}

C:localAdapter.startScanning()方法:

目录:android\packages\apps\Settings\src\com\android\settings\bluetooth\localBluetoothAdapter.java

void startScanning(boolean force) {

..........................

if (mAdapter.startDiscovery()) {

mLastScan = System.currentTimeMillis();

}

}

}

(二)走到frameworks

D:madapter.startDiscovery()方法:

目录:android\frameworks\base\core\java\android\bluetooth\BluetoothAdapter.java

public boolean startDiscovery() {

if (getState() != STATE_ON) return false;

try {

synchronized(mManagerCallback) {

if (mService != null) return mService.startDiscovery();

}

} catch (RemoteException e) {Log.e(TAG, "", e);}

return false;

}

E:mservice.startDiscovery()方法:这分析有问题--------?????

private IBluetooth mService;知道了是在IBluetooth.aidl文件中写的 boolean startDiscovery()属于跨进程调用的写法不需要研究;所以直接搜索startDiscovery()看在上层哪实现的这个方法。

(三)跨进程调到packages\Bluetooth

F:mService.startDiscovery()方法:

目录:android\packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterService.java

(1):公共

public boolean startDiscovery() {

...................

AdapterService service = getService();

if (service == null) return false;

return service.startDiscovery();

}

(2):走

boolean startDiscovery() {

enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,

"Need BLUETOOTH ADMIN permission");

注册权限

return startDiscoveryNative();

}

(3):调到native,这是个标志,有native声明就会调用,系统会自动识别出来,因为有个native的大表。所以会调用到对应的.cpp文件结尾的jini层的函数,属于java调C,所以要直接搜索startDiscoveryNative

private native boolean startDiscoveryNative();

(四)packages\Bluetooth的java层调到jini层的cpp文件

G:nativeCpp.startDiscoveryNative方法:

目录:android\packages\apps\Bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp

static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) {

...........................................

int ret = sBluetoothInterface->start_discovery();

result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;

return result;

}

(1):初始化

jint JNI_OnLoad(JavaVM *jvm, void *reserved)

{

......................................

if ((status = android::register_com_android_bluetooth_btservice_AdapterService(e)) < 0) {

ALOGE("jni adapter service registration failure, status: %d", status);

return JNI_ERR;

}

(2):注册

int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env)

{

return jniRegisterNativeMethods(env, "com/android/bluetooth/btservice/AdapterService",包名

sMethods, NELEM(sMethods));

}

(3):对应的函数

static JNINativeMethod sMethods[] = {

......................

{"startDiscoveryNative", "()Z", (void*) startDiscoveryNative},

static const bt_interface_t *sBluetoothInterface = NULL;

(五)packages\Bluetooth的java层调到jini层的cpp文件--------------->在调到Hal层的.h文件中bt_interface_t ->start_discovery()的一个接口;

H:sBluetoothInterface->start_discovery()方法:

目录:android\hardware\libhardware\include\hardware\bluetooth.h

/** Start Discovery */
    int (*start_discovery)(void);

I:会调到extenel层

兄弟!不能在往下分析了,后续要分析的话参考http://blog.csdn.net/wendell_gong/article/details/16864467

----------------------------------------------------------------------------------------------------------------------------------------------------

点scan传上来的流程,一会搜索,如何调的这个cpp文件

A:上层BluetoothEventManager收到的Log流程

点搜索先走第一条广播:

01-07 18:00:45.129: V/lwn(2786): ScanningStateChangedHandler intent=Intent { act=android.bluetooth.adapter.action.DISCOVERY_STARTED flg=0x10 } BluetoothDevice=null

搜出来就走下面的:

01-07 18:00:47.279: V/lwn(2786): NameChangedHandler intent=Intent { act=android.bluetooth.device.action.NAME_CHANGED flg=0x4000010 (has extras) } BluetoothDevice=CC:AF:78:E5:34:EF

01-07 18:00:47.279: V/lwn(2786): ClassChangedHandler intent=Intent { act=android.bluetooth.device.action.CLASS_CHANGED flg=0x4000010 (has extras) } BluetoothDevice=CC:AF:78:E5:34:EF

01-07 18:00:47.289: V/lwn(2786): DeviceFoundHandler intent=Intent { act=android.bluetooth.device.action.FOUND flg=0x10 (has extras) } BluetoothDevice=CC:AF:78:E5:34:EF

最后还要走一下第一条:

01-07 18:00:57.949: V/lwn(2786): ScanningStateChangedHandler intent=Intent { act=android.bluetooth.adapter.action.DISCOVERY_FINISHED flg=0x10 } BluetoothDevice=null

搜索对应的Log得出以下的分析:是2种广播,一种是bluetoothAdapter的还有一种是bluetoothDevice的。

......................经过下层的调用,参考:http://blog.csdn.net/wendell_gong/article/details/16864467

(一)packages\Bluetooth的jini层的cpp文件

B:

目录:android\packages\apps\Bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp

这个cpp的流程前面已经分析过。

(1):初始化

jint JNI_OnLoad(JavaVM *jvm, void *reserved)

{

......................................

if ((status = android::register_com_android_bluetooth_btservice_AdapterService(e)) < 0) { 只有中间这个有用

ALOGE("jni adapter service registration failure, status: %d", status);

return JNI_ERR;

}

....................................

(2):注册

int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env)

{

return jniRegisterNativeMethods(env, "com/android/bluetooth/btservice/AdapterService",包名

sMethods, NELEM(sMethods));

}

(3):对应的函数后来才知道原来这里面写的全是向上层发的广播。

static JNINativeMethod sMethods[] = {



{"classInitNative", "()V", (void *) classInitNative},这个对应是第一个类型的广播

{"initNative", "()Z", (void *) initNative},对应是第二个类型的广播

...............................前面是C调java,下面是java调C
{"startDiscoveryNative", "()Z", (void*) startDiscoveryNative},

.................................
}

-----------------------------------------------------------------------------------------------------------------------------------------------这前面只是注册函数的流程
classInitNative方法注册下面:

(1):

static void classInitNative(JNIEnv* env, jclass clazz) {



..................................................

method_discoveryStateChangeCallback = env->GetMethodID(jniCallbackClass,

"discoveryStateChangeCallback", "(I)V");

......................................................

method_devicePropertyChangedCallback = env->GetMethodID(jniCallbackClass,

"devicePropertyChangedCallback",

"([B[I[[B)V");

method_deviceFoundCallback = env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V");

.........................................................

-------------------------------------------

jniCallbackClass参数一:意思是直接找“”里面的这个类下的后面引号里面的方法

jclass jniCallbackClass =

env->FindClass("com/android/bluetooth/btservice/JniCallbacks");

(2):

InitNative方法注册下面:

(1):

static bool initNative(JNIEnv* env, jobject 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 \n");

sBluetoothInterface = NULL;

return JNI_FALSE;

}

(2):sBluetoothCallbacks

bt_callbacks_t sBluetoothCallbacks = {

sizeof(sBluetoothCallbacks),

adapter_state_change_callback,

adapter_properties_callback,

remote_device_properties_callback,---------对应的是namechangge和classchange

device_found_callback,-------------founddevice

discovery_state_changed_callback,------------状态变了就走

wake_state_changed_callback,

pin_request_callback,

ssp_request_callback,

bond_state_changed_callback,

acl_state_changed_callback,

..................................

};

(3):

a:discovery_state_changed_callback

static void discovery_state_changed_callback(bt_discovery_state_t state) {



callbackEnv->CallVoidMethod(sJniCallbacksObj, method_discoveryStateChangeCallback,

(jint)state);

}

b:remote_device_properties_callback,

callbackEnv->CallVoidMethod(sJniCallbacksObj, method_devicePropertyChangedCallback, addr,

types, props);

c:device_found_callback,

callbackEnv->CallVoidMethod(sJniCallbacksObj, method_deviceFoundCallback, addr);

----------------------------------------------------------------又指向了上面classInitNative,再看sJniCallbacksObj也能看出来用的是classInitNative,总之会调用到下面。

(二)jini调java

C:jniCallbacks.discoveryStateChangeCallback()方法:
目录:android\packages\apps\Bluetooth\src\com\android\bluetooth\btservice\jniCallbacks.java
private AdapterProperties mAdapterProperties;

void discoveryStateChangeCallback(int state) {

mAdapterProperties.discoveryStateChangeCallback(state);

}

void devicePropertyChangedCallback(byte[] address, int[] types, byte[][] val) {

mRemoteDevices.devicePropertyChangedCallback(address, types, val);

}

void deviceFoundCallback(byte[] address) {

mRemoteDevices.deviceFoundCallback(address);

}

D:AdapterProperties .discoveryStateChangeCallback()方法:

目录:android\packages\apps\Bluetooth\src\com\android\bluetooth\adapterProperties.java

void discoveryStateChangeCallback(int state) {



if (state == AbstractionLayer.BT_DISCOVERY_STOPPED) {

mDiscovering = false;

intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);

mService.sendBroadcast(intent, mService.BLUETOOTH_PERM);

} else if ((state == AbstractionLayer.BT_DISCOVERY_STARTED) && !mDiscovering) {

mDiscovering = true;

intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_STARTED);

mService.sendBroadcast(intent, mService.BLUETOOTH_PERM);

}

}

}

这2个广播就是adapter发出来的

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------这只是Log中的第一条和最后一条,中间的那三个下面分析

D1:mRemoteDevices.devicePropertyChangedCallback(address, types, val);方法.deviceFoundCallback(address);方法

目录:android\packages\apps\Bluetooth\src\com\android\bluetooth\remoteDevices.java

(1):Log中第2条

void devicePropertyChangedCallback{

case AbstractionLayer.BT_PROPERTY_BDNAME:

device.mName = new String(val);

intent = new Intent(BluetoothDevice.ACTION_NAME_CHANGED);

............................

break;

(2):Log中第3条

case AbstractionLayer.BT_PROPERTY_CLASS_OF_DEVICE:

device.mBluetoothClass = Utils.byteArrayToInt(val);

intent = new Intent(BluetoothDevice.ACTION_CLASS_CHANGED);

..............................

break;

}

(3):Log中第4条

void deviceFoundCallback(byte[] address) {

Intent intent = new Intent(BluetoothDevice.ACTION_FOUND);

}

接收广播:BluetoothEventManager.java

目录:android\packages\apps\Settings\src\com\android\settings\bluetooth\BluetoothEventManager.java

addHandler(BluetoothAdapter.ACTION_DISCOVERY_STARTED, new ScanningStateChangedHandler(true));------开始搜索

addHandler(BluetoothDevice.ACTION_NAME_CHANGED, new NameChangedHandler());-----------远程设备第一次或者最后一次的名字

addHandler(BluetoothDevice.ACTION_CLASS_CHANGED, new ClassChangedHandler());----------远程设备的class

addHandler(BluetoothDevice.ACTION_FOUND,
new DeviceFoundHandler());-------------------------找到了远程设备

addHandler(BluetoothAdapter.ACTION_DISCOVERY_FINISHED, new ScanningStateChangedHandler(false));------搜索完毕



其实应该有十几个广播,我接收到的只是其中的几个而已。。。。别的广播可能是有别的用处。。。

a2dp:是蓝牙立体声耳机
gatt:低功耗蓝牙
HFP(Hands-free Profile),让蓝牙设备可以控制电话,如接听、挂断、拒接、语音拨号等,拒接、语音拨号要视蓝牙耳机及电话是否支持。

跳到android\packages\apps\Bluetooth\src\com\android\bluetooth\hfp连接耳机配对过程。

因为我们的用的是hfp协议。

BluetoothDevicePreference:



第一个:是如果连接点击,弹出对话框断开连接。

第三个:没发现设备。。。

第二个:发现了点击就会走如果没配对先配对,配了直接连。




这就是开始配对

连接:执行那个方法反正最后都是调到



调到这个接口:



经过查找筛选出来hfp协议对应的是这个类:HeadsetProfile implements LocalBluetoothProfile



android\frameworks\base\core\java\android\bluetooth\BluetoothHeadset.java

BluetoothHeadset implements BluetoothProfile.java



private IBluetoothHeadset mService;又是aidl文件。

直接搜索:IBluetoothHeadset

android\packages\apps\Bluetooth\src\com\android\bluetooth\hfp\headsetService.java





...............会一直调到frameworks\base\core\java\android\os\MessageQueue.java



同样看到了native函数



直接搜---

android\frameworks\base\core\jni\android_os_MessageQueue.cpp



注册:android/os/MessageQueue



发送广播的地方:

packages\apps\Bluetooth\src\com\android\bluetooth\btservice\BondStateMachine.java



发送的方式是用service服务来发的。也就是服务一直开着。

packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterService.java中但是没有sendBroadcastAsuser()方法,但是它继承了service

frameworks\base\core\java\android\app\service.java也没有,它也是继承了ContextWrapper

frameworks\base\core\java\android\content\ContextWrapper.java继承了context



frameworks\base\core\java\android\content\Context.java是个接口。

一:声音修改

先画UI发送广播一起的。AudioService



二:VolumePanel


调本身

handleMessage





一:将packages和framework全加,不要只加个Setings,或者只加Settings和Bluetooth
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: