代码流程分析二:Settings-蓝牙分析-搜索设备原理
蓝牙搜索功能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},对应是第二个类型的广播
................................. }
-----------------------------------------------------------------------------------------------------------------------------------------------这前面只是注册函数的流程 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
更多相关文章
- Android之TextSwitcher详解
- RK3288 android7.1.2 插 UVCCamera 摄像头, android studio 调试9
- Android中Intent的几种使用方法
- Android新版NDK环境配置(免Cygwin)
- android初中高开发工程师必需要装的一个APP
- Android(安卓)Studio logcat 设置 缓存大小 ,增加logcat条数
- android 按两次返回键退出程序
- javascript 与 webview 交互
- android MediaPlayer+Stagefright架构(音频)图解