蓝牙搜索功能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

更多相关文章

  1. Android之TextSwitcher详解
  2. RK3288 android7.1.2 插 UVCCamera 摄像头, android studio 调试9
  3. Android中Intent的几种使用方法
  4. Android新版NDK环境配置(免Cygwin)
  5. android初中高开发工程师必需要装的一个APP
  6. Android(安卓)Studio logcat 设置 缓存大小 ,增加logcat条数
  7. android 按两次返回键退出程序
  8. javascript 与 webview 交互
  9. android MediaPlayer+Stagefright架构(音频)图解

随机推荐

  1. Android基础练习
  2. android studio编译错误但是不提示哪里错
  3. Android(安卓)动画学习笔记
  4. android 跳转 activity 出现错误 you do
  5. Android判断是Wifi还是4G网络代码
  6. Android加载动画库
  7. Android(安卓)JNI和NDK学习(2)--编程入门
  8. Appium自动化测试-Android启动实例(2)
  9. Android(安卓)部分系统广播
  10. android context调用startActivity时报错