【Android4.4蓝牙代码分析】- 蓝牙Enable过程

来源:互联网 发布:大唐软件校园招聘 编辑:程序博客网 时间:2024/06/06 01:54

【Android4.4蓝牙代码分析】- 蓝牙Enable过程

(一)基本说明

  1. 本文的代码选用的是Android4.4kitkat代码。

  2. 本文是在Windows环境下通过source insight进行代码阅读,所以大部分目录是以windows的目录结构以’\’区分层级关系。


(二)搭建代码环境

首先介绍下本文source insight所加载的代码路径,bluedroid代码结构可以参考BlueDroid概述。

  1. package/apps/Bluetooth,这个目录下是Bluetooth的app源码。
  2. hardware/libhardware/include/hardware,JNI层的一些代码。
  3. external/Bluetooth/bluedroid,bluedroid协议栈代码。
  4. frameworks\base\core\java\android\bluetooth,framework层的java代码与aidl文件。
  5. packages\apps\Settings\src\com\android\settings\bluetooth,Setting App源码中的bluetooth代码
  6. frameworks\base\services\java\com\android\server,系统核心服务的代码,系统启动后会在这注册蓝牙服务。

(三)蓝牙enable好文分享

有关于Android bluedroid的enable分析已经有很多大牛分析了,现在分享出部分好的博客,本文很多东西都是参考他们的文章。

  1. Android BlueDroid(三):BlueDroid蓝牙开启过程enable,该文给出了总体的流程图,在总体结构上对蓝牙enable过程可以有个清晰的认识。
  2. Android 4.2 Bluetooth 分析总结(二) 蓝牙enable 的整个过程,该文给出了log,并且按照代码运行流程一个个函数的进行分析,本文很多内容都参考至该文。
  3. android bluetooth 移植相关注意事项,该文将了下蓝牙移植的相关知识,在进行代码阅读之前看看该文,能够从一个总体层次上对bluedroid代码进行分析。
  4. android – 蓝牙 bluetooth (二) 打开蓝牙,该文是也很不错,作者最开始就是看的该博客。

(四)代码分析

在Android系统启动过程中,其会首先加载SystemServer.java,System Server是Android系统的核心,他在Dalvik虚拟机启动后立即开始初始化和运行。其它的系统服务在System Server进程的环境中运行。在Android系统开机过程中,蓝牙服务也会在这里注册,并运行,关于SystemServer.java详见(Android的System Server),这样蓝牙服务进程就作为一个线程运行在SystemServer进程中。最后一个else分支是我们所关心的,通过ServiceManager.addService方法向ServiceManager进程中注册了蓝牙服务,后面要使用时只需要通过getService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE)方法即可(BluetoothAdapter类在frameworks\base\core\java\android\bluetooth目录下,BLUETOOTH_MANAGER_SERVICE值为“bluetooth_manager”)。

代码位置:frameworks\base\services\java\com\android\server\SystemServer.java
    if (SystemProperties.get("ro.kernel.qemu").equals("1")) {        Slog.i(TAG, "No Bluetooh Service (emulator)");    } else if (factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {        Slog.i(TAG, "No Bluetooth Service (factory test)");    } else if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) {        Slog.i(TAG, "No Bluetooth Service (Bluetooth Hardware Not Present)");    } else if (disableBluetooth) {        Slog.i(TAG, "Bluetooth Service disabled by config");    } else {        Slog.i(TAG, "Bluetooth Manager Service");        bluetooth = new BluetoothManagerService(context);        ServiceManager.addService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, bluetooth);    }

我们先看一下BluetoothManagerService类的构造函数,代码比较多,我们主要看两个地方,loadStoredNameAndAddress()是读取蓝牙打开默认名称的地方,isBluetoothPersistedStateOn()是用来判断蓝牙是否已打开的,如果已打开,需要执行开启蓝牙的动作,前几行注册的广播其中就有这个作用。

代码位置:frameworks\base\services\java\com\android\server\BluetoothManagerService.java
    BluetoothManagerService(Context context) {        …一些变量声明初始化…        IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);        filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);        filter.addAction(Intent.ACTION_USER_SWITCHED);        registerForAirplaneMode(filter);        mContext.registerReceiver(mReceiver, filter);        loadStoredNameAndAddress();        if (isBluetoothPersistedStateOn()) {            mEnableExternal = true;        }    }

上面就完成了蓝牙的系统服务注册工作,如果没有设置蓝牙打开,系统也不会打开蓝牙,后面如果需要用到蓝牙服务只需通过systemServer的getServer方法即可。

现在回到用户真正能接触到的界面开关部分,蓝牙界面开关就是Setting界面中的蓝牙开关,其实际就是调用BluetoothEnabler.java这个类了,BluetoothEnabler类是实现
CompoundButton.OnCheckedChangeListener按键监听器,看到其onCheckedChanged方法,当按键按下时会跳入该方法,在该方法中首先判断是否开启了飞行模式,如果没则调用mLocalAdapter(LocalBluetoothAdapter)setBluetoothEnabled()方法,执行具体的开关动作。

代码位置:packages\apps\Settings\src\com\android\settings\bluetooth\BluetoothEnabler.java
    public final class BluetoothEnabler implements CompoundButton.OnCheckedChangeListener {        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {            // Show toast message if Bluetooth is not allowed in airplane mode            if (isChecked && !WirelessSettings.isRadioAllowed(mContext, Settings.Global.RADIO_BLUETOOTH)) {                Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();                // Reset switch to off                buttonView.setChecked(false);            }            if (mLocalAdapter != null) {                mLocalAdapter.setBluetoothEnabled(isChecked);            }            mSwitch.setEnabled(false);        }    }

在LocalBluetoothAdapter类的setBluetoothEnabled方法中,根据是否打开再调用mAdapter(BluetoothAdapter)的enable或disable方法。并更新蓝牙状态机。

代码位置:packages\apps\Settings\src\com\android\settings\bluetooth\LocalBluetoothAdapter.java
    public void setBluetoothEnabled(boolean enabled) {        boolean success = enabled                ? mAdapter.enable()                : mAdapter.disable();        if (success) {            setBluetoothStateInt(enabled                ? BluetoothAdapter.STATE_TURNING_ON                : BluetoothAdapter.STATE_TURNING_OFF);        } else {            if (Utils.V) {                Log.v(TAG, "setBluetoothEnabled call, manager didn't return " +"success for enabled: " + enabled);            }            syncBluetoothState();        }    }

请注意:这时候代码已经跳转到了framework层了。

在BluetoothAdapter类中可以看到一个单例模式的应用,主要提供给其它程序调用蓝牙的一些方法用的,外部程序想调用蓝牙的方法就要先用这个拿到BluetoothAdapter对象,代码也简单看下吧,里面是典型的binder应用。就是前面在SystemServer中注册的蓝牙服务。

代码位置: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;    }

此时我们更关心mAdapter.enable()的后续操作,外部其它应用到getDefaultAdapter()也是调用enable(),注意,到了BluetoothAdapter我们已经在framework层了,顺着BluetoothAdapter.java的enable()调用,其先判断蓝牙是否已经打开,如果没打开则调用mManagerService(IBluetoothManager)的enable方法。

代码位置:frameworks\base\core\java\android\bluetooth\BluetoothAdapter.java
    public boolean enable() {        if (isEnabled() == true){            if (DBG) Log.d(TAG, "enable(): BT is already enabled..!");            return true;        }        try {            return mManagerService.enable();        } catch (RemoteException e) {Log.e(TAG, "", e);}        return false;    }

IBluetoothManager类是Android进程间通信的接口,在其中定义了一堆的接口,一般这种远程服务对应的类名就是 BluetoothManagerService 类,主要用于调用在SystemServer中注册的蓝牙服务。在BluetoothAdapter类的构造函数中,将mManagerService绑定到了ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE)的蓝牙服务中。我们直接进入BluetoothManagerService类的enable()方法。

代码位置:frameworks\base\core\java\android\bluetooth\BluetoothAdapter.java
    interface IBluetoothManager {        IBluetooth registerAdapter(in IBluetoothManagerCallback callback);        void unregisterAdapter(in IBluetoothManagerCallback callback);        void registerStateChangeCallback(in IBluetoothStateChangeCallback callback);        void unregisterStateChangeCallback(in IBluetoothStateChangeCallback callback);        boolean isEnabled();        boolean enable();        boolean enableNoAutoConnect();        boolean disable(boolean persist);        IBluetoothGatt getBluetoothGatt();        String getAddress();        String getName();    }

在BluetoothManagerService类的enable()方法中,第一个if看到log那就知道如果enable正常就不会走,第二个if是打印调试信息,在后面的synchronized函数体中,实际有用的是sendEnableMsg(false)方法,跳到sendEnableMsg中。

代码位置:frameworks\base\services\java\com\android\server\BluetoothManagerService.java
    public boolean enable() {        if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&            (!checkIfCallerIsForegroundUser())) {            Log.w(TAG,"enable(): not allowed for non-active and non system user");            return false;        }        mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,                                                "Need BLUETOOTH ADMIN permission");        if (DBG) {            Log.d(TAG,"enable():  mBluetooth =" + mBluetooth +                    " mBinding = " + mBinding);        }        synchronized(mReceiver) {            mQuietEnableExternal = false;            mEnableExternal = true;            // waive WRITE_SECURE_SETTINGS permission check            long callingIdentity = Binder.clearCallingIdentity();            persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);            Binder.restoreCallingIdentity(callingIdentity);            sendEnableMsg(false);        }        return true;    }

可以看到在sendEnableMsg中向系统发送了一条MESSAGE_ENABLE消息,再跳转到mHandler(BluetoothHandler)类的handleMessage方法,可以看到在handleMessage中有对MESSAGE_ENABLE消息的处理函数,实际的话就是调用了BluetoothManagerService类的handleEnable方法。

代码位置:frameworks\base\services\java\com\android\server\BluetoothManagerService.java
    private class BluetoothHandler extends Handler {        ...        @Override        public void handleMessage(Message msg) {            if (DBG) Log.d (TAG, "Message: " + msg.what);            switch (msg.what) {                case MESSAGE_ENABLE:                    if (DBG) {                        Log.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth);                    }                    mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE);                    mEnable = true;                    handleEnable(msg.arg1 == 1);                    break;                }            }        }    }

handleEnable方法比较长,看到注释说明//Enable bluetooth,我们直接看这部分代码,实际执行的是mBluetooth.enable(),又是一个接口IBluetooth

代码位置:frameworks\base\services\java\com\android\server\BluetoothManagerService.java
    private void handleEnable(boolean quietMode) {        mQuietEnable = quietMode;        synchronized(mConnection) {            if ((mBluetooth == null) && (!mBinding)) {                //Start bind timeout and bind                Message timeoutMsg=mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);                mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);                mConnection.setGetNameAddressOnly(false);                Intent i = new Intent(IBluetooth.class.getName());                if (!doBind(i, mConnection,Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) {                    mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);                } else {                    mBinding = true;                }            } else if (mBluetooth != null) {                if (mConnection.isGetNameAddressOnly()) {                    // if GetNameAddressOnly is set, we can clear this flag,                    // so the service won't be unbind                    // after name and address are saved                    mConnection.setGetNameAddressOnly(false);                    //Register callback object                    try {                        mBluetooth.registerCallback(mBluetoothCallback);                    } catch (RemoteException re) {                        Log.e(TAG, "Unable to register BluetoothCallback",re);                    }                    //Inform BluetoothAdapter instances that service is up                    sendBluetoothServiceUpCallback();                }                //Enable bluetooth                try {                    if (!mQuietEnable) {                        if(!mBluetooth.enable()) {                            Log.e(TAG,"IBluetooth.enable() returned false");                        }                    }                    else {                        if(!mBluetooth.enableNoAutoConnect()) {                            Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");                        }                    }                } catch (RemoteException e) {                    Log.e(TAG,"Unable to call enable()",e);                }            }        }    }

mBluetooth(IBluetooth)这个接口到底是对应哪个远程服务呢?在同一个目录下搜索,先搜索mBluetooth在哪里赋值了,搜索完BluetoothManagerService.java只在handleMessage中找到了mBluetooth = IBluetooth.Stub.asInterface(service),而IBinder service = (IBinder) msg.obj。也就是远程服务是发送“MESSAGE_BLUETOOTH_SERVICE_CONNECTED”消息对象。继续在BluetoothManagerService类中搜索是谁发送这条消息。

代码位置:frameworks\base\services\java\com\android\server\BluetoothManagerService.java
    private class BluetoothHandler extends Handler {        ...        @Override        public void handleMessage(Message msg) {            if (DBG) Log.d (TAG, "Message: " + msg.what);            switch (msg.what) {                case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:                {                    if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);                    IBinder service = (IBinder) msg.obj;                    synchronized(mConnection) {                        if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {                            mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service);                            break;                        } // else must be SERVICE_IBLUETOOTH                        //Remove timeout                        mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);                        mBinding = false;                        mBluetooth = IBluetooth.Stub.asInterface(service);                        ...                    break;                }            }        }    }

BluetoothManagerService.java中发现在onServiceConnected方法中构建了该消息,并将调用该方法的service赋值给msg.obj,到底谁调用了这个函数呢,尝试搜索了下“onServiceConnected”并没有得到想要的结果,再回到onServiceConnected方法中,可以看到有个log,"BluetoothServiceConnection: " + className.getClassName(),就是说将BluetoothServiceConnection连接到一个服务上,在看到下面的if判断,最有可能的是连接到了AdapterService服务中。在Android 4.2 Bluetooth 分析总结(二) 蓝牙enable 的整个过程中作者从实际打印的log中也指出了在这一步系统会跳转到AdapterService。
D/BluetoothManagerService( 1646): BluetoothServiceConnection: connected to AdapterService

代码位置:frameworks\base\services\java\com\android\server\BluetoothManagerService.java
        public void onServiceConnected(ComponentName className, IBinder service) {            if (DBG) Log.d(TAG, "BluetoothServiceConnection: " + className.getClassName());            Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);            // TBD if (className.getClassName().equals(IBluetooth.class.getName())) {            if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) {                msg.arg1 = SERVICE_IBLUETOOTH;                // } else if (className.getClassName().equals(IBluetoothGatt.class.getName())) {            } else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) {                msg.arg1 = SERVICE_IBLUETOOTHGATT;            } else {                Log.e(TAG, "Unknown service connected: " + className.getClassName());                return;            }            msg.obj = service;            mHandler.sendMessage(msg);        }

这时代码从framework层跳到了APP层,符合了android代码架构图中的定义。

我们看到AdapterService的enable方法,可以发现在AdapterService类中有三个enable函数,从framework层到这到底调用了哪个enable函数呢,根据代码注释和实际情况,应该是调用了在AdapterServiceBinder类中的enable方法,在该方法中调用了service.enable(),而service是通过getService()方法获取的,看到该方法,实际是返回了mService(AdapterService),也就是调用了boolean enable()方法,最终调用了public synchronized boolean enable(boolean quietMode)方法。在这个方法中主要是构建了一个AdapterState.USER_TURN_ON消息,并发送给状态机mAdapterStateMachine去处理。

代码位置:packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterService.java
    public class AdapterService extends Service {        ...        private static class AdapterServiceBinder extends IBluetooth.Stub {            private AdapterService mService;            public AdapterServiceBinder(AdapterService svc) {                mService = svc;            }        ...            public boolean enable() {                if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&                    (!Utils.checkCaller())) {                    Log.w(TAG,"enable(): not allowed for non-active user and non system user");                    return false;                }                AdapterService service = getService();                if (service == null) return false;                return service.enable();            }        ...            public AdapterService getService() {                if (mService  != null && mService.isAvailable()) {                    return mService;                }                return null;            }        }        ...        //----API Methods--------        ...        boolean enable() {            return enable (false);        }           ...        public synchronized boolean enable(boolean quietMode) {            enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,                                            "Need BLUETOOTH ADMIN permission");            if (DBG)debugLog("Enable called with quiet mode status =  " + mQuietmode);            mQuietmode  = quietMode;            Message m =                     mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON);            mAdapterStateMachine.sendMessage(m);            return true;        }    }

这里用到了状态机的概念,在网上查了下有关Android蓝牙状态机的资料,没有找到合适的,大多是Android4.2之前的状态机分析,通过查看源码,在AdapterState状态机的注释中可以发现如下说明,说明该状态机有三个状态,分别是OnState、OffState以及PendingCommandState,再根据注释,在初始状态下,蓝牙应该处于OffState,中间态是PendingCommandState,正在打开是OnState。具体没有深入去分析代码,可能有错误,暂时按照这个流程继续进行蓝牙enable分析。

代码位置:packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterState.java
    /**     * This state machine handles Bluetooth Adapter State.     * States:     *      {@link OnState} : Bluetooth is on at this state     *      {@link OffState}: Bluetooth is off at this state. This is the initial     *      state.     *      {@link PendingCommandState} : An enable / disable operation is pending.     * TODO(BT): Add per process on state.     */

我们重点看状态机的消息处理部分,由于这时候进行的是蓝牙开启操作,状态机处于OffState状态下,在OffState的processMessage中找到对USER_TURN_ON的处理函数,前面的几个是进行状态机的状态更新,最后调用了adapterService.processStart(),我们跳进去看。

代码位置:packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterState.java
    final class AdapterState extends StateMachine {        ...        private class OffState extends State {            ...            @Override            public boolean processMessage(Message msg) {                AdapterService adapterService = mAdapterService;                if (adapterService == null) {                    Log.e(TAG,"receive message at OffState after cleanup:" +                              msg.what);                    return false;                }                switch(msg.what) {                   case USER_TURN_ON:                       if (DBG) Log.d(TAG,"CURRENT_STATE=OFF, MESSAGE = USER_TURN_ON");                       notifyAdapterStateChange(BluetoothAdapter.STATE_TURNING_ON);                       mPendingCommandState.setTurningOn(true);                       transitionTo(mPendingCommandState);                       sendMessageDelayed(START_TIMEOUT, START_TIMEOUT_DELAY);                       adapterService.processStart();                       break;                ...                }                return true;            }        }        ...    }

又回到了AdapterService,通过看给出的log提示以及函数名称,大概是进行了所有profile的状态机状态开启设置,在最后一个else中的log中也是显示processStart(): Profile Services alreay started,最后又调用状态机执行AdapterState.STARTED消息,执行mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED))

代码位置:packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterService.java
   void processStart() {        if (DBG) debugLog("processStart()");        Class[] supportedProfileServices = Config.getSupportedProfiles();        //Initialize data objects        for (int i=0; i < supportedProfileServices.length;i++) {            mProfileServicesState.put(supportedProfileServices[i].getName(),BluetoothAdapter.STATE_OFF);        }        mRemoteDevices = new RemoteDevices(this);        mAdapterProperties.init(mRemoteDevices);        if (DBG) {debugLog("processStart(): Make Bond State Machine");}        mBondStateMachine = BondStateMachine.make(this, mAdapterProperties, mRemoteDevices);        mJniCallbacks.init(mBondStateMachine,mRemoteDevices);        //FIXME: Set static instance here???        setAdapterService(this);        //Start profile services        if (!mProfilesStarted && supportedProfileServices.length >0) {            //Startup all profile services            setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);        }else {            if (DBG) {debugLog("processStart(): Profile Services alreay started");}            mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED));        }    }

再次回到AdapterState类,由于这时候状态机处于pending状态下,所以在PendingCommandState中对该消息进行处理,实际是调用了adapterService.enableNative()方法,也就是终于通过JNI开始向下层调用底层操作方法进行蓝牙Enable操作。

代码位置:packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterState.java
    final class AdapterState extends StateMachine {        ...        private class PendingCommandState extends State {            private boolean mIsTurningOn;            private boolean mIsTurningOff;            ...            @Override            public boolean processMessage(Message msg) {                ...                switch(msg.what) {                    case STARTED:                           if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = STARTED, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);                        //Remove start timeout                        removeMessages(START_TIMEOUT);                        //Enable                        boolean ret = adapterService.enableNative();                        if (!ret) {                            Log.e(TAG, "Error while turning Bluetooth On");                            notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);                            transitionTo(mOffState);                        } else {                            sendMessageDelayed(ENABLE_TIMEOUT, ENABLE_TIMEOUT_DELAY);                        }                        break;                ...                }                return true;            }        }        ...    }

这里已经通过JNI从APP framework层进入了bluedroid协议栈了。

根据Android JNI层的命名规则,找到了com_android_bluetooth_btservice_AdapterService.cpp,看到其中的enableNative()方法。实际是调用了sBluetoothInterface(bt_interface_t)的enable方法。sBluetoothInterface这个又是一个接口,在网上看别人写的博客说不能跳转,但是我这边可以直接跳转到bt_interface_t的定义,如果不能跳转依然可以到这个文章中看如何跳转Android 4.2 Bluetooth 分析总结(二) 蓝牙enable 的整个过程。

代码位置:packages\apps\Bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp
    static jboolean enableNative(JNIEnv* env, jobject obj) {        ALOGV("%s:",__FUNCTION__);        jboolean result = JNI_FALSE;        if (!sBluetoothInterface) return result;        int ret = sBluetoothInterface->enable();        result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;        return result;    }

可以看出,在这个结构体中包含了大量的接口,有bluetooth.h自然有bluetooth.c文件,我们跳转到bluetooth.c中看下接口的具体实现。

代码位置:hardware\libhardware\include\hardware\bluetooth.h
    /** Represents the standard Bluetooth DM interface. */    typedef struct {        /** set to sizeof(bt_interface_t) */        size_t size;        /**         * Opens the interface and provides the callback routines         * to the implemenation of this interface.         */        int (*init)(bt_callbacks_t* callbacks );        /** Enable Bluetooth. */        int (*enable)(void);        /** Disable Bluetooth. */        int (*disable)(void);        ...    } bt_interface_t;

终于开始了最喜欢的c代码了,c代码看起来就轻松多了。

在这里可以看到bluetooth.c实例化了一个bt_interface_t对象,bluetoothInterface。跳转到enable函数中,在打印了一个log信息后,先会对接口进行检查,如果接口ready就调用btif_enable_bluetooth()方法。

代码位置:external\bluetooth\bluedroid\btif\src\bluetooth.c
    static int enable( void )    {        ALOGI("enable");        /* sanity check */        if (interface_ready() == FALSE)            return BT_STATUS_NOT_READY;        return btif_enable_bluetooth();    }    ...    static const bt_interface_t bluetoothInterface = {        sizeof(bluetoothInterface),        init,        enable,        disable,        cleanup,        get_adapter_properties,        get_adapter_property,        set_adapter_property,        get_remote_device_properties,        get_remote_device_property,        set_remote_device_property,        get_remote_service_record,        get_remote_services,        start_discovery,        cancel_discovery,        create_bond,        remove_bond,        cancel_bond,        pin_reply,        ssp_reply,        get_profile_interface,        dut_mode_configure,        dut_mode_send,    #if BLE_INCLUDED == TRUE        le_test_mode,    #else        NULL,    #endif        config_hci_snoop_log    };

到了这一步基本上已经完成了上层的一堆蓝牙Enable代码分析,后面的都是bluedroid的代码了,具体到蓝牙的实际开关又涉及到各个厂商Vendor的设计。下面简要写一些后续的蓝牙Enable过程。

一下就跳转到了btif_core.c中了,前面是一堆的判断以及状态机的设置,我们直接看到后面,又调用了bte_main_enable(),跳进去继续看。

代码位置:external\bluetooth\bluedroid\btif\src\btif_core.c
    bt_status_t btif_enable_bluetooth(void)    {        BTIF_TRACE_DEBUG0("BTIF ENABLE BLUETOOTH");        if (btif_core_state != BTIF_CORE_STATE_DISABLED)        {            ALOGD("not disabled\n");            return BT_STATUS_DONE;        }        btif_core_state = BTIF_CORE_STATE_ENABLING;        /* Create the GKI tasks and run them */        bte_main_enable();        return BT_STATUS_SUCCESS;    }

认真看下这个函数,首先初始化了BTE的控制块,是什么呢,大概看了下,主要是一些参数设置。主要看到bte_hci_enable(),这个函数比较长,首先启动了一个preload定时器,主要用于重新打开蓝牙的操作,以防蓝牙长时间没有打开,先不管,继续往下看,bt_hc_if(bt_hc_interface_t)是什么东西呢,我们跳进去看看,bte_hci_enable()的分析后面继续开展,先看看bt_hc_if(bt_hc_interface_t)是什么东西,后面很多地方都有调用。

代码位置:external\bluetooth\bluedroid\main\bte_main.c
    void bte_main_enable()    {        APPL_TRACE_DEBUG1("%s", __FUNCTION__);        /* Initialize BTE control block */        BTE_Init();        lpm_enabled = FALSE;        bte_hci_enable();        GKI_create_task((TASKPTR)btu_task, BTU_TASK, BTE_BTU_TASK_STR,                        (UINT16 *) ((UINT8 *)bte_btu_stack + BTE_BTU_STACK_SIZE),                        sizeof(bte_btu_stack));        GKI_run(0);    }    ...    static void bte_hci_enable(void)    {        APPL_TRACE_DEBUG1("%s", __FUNCTION__);        preload_start_wait_timer();        if (bt_hc_if)        {            int result = bt_hc_if->init(&hc_callbacks, btif_local_bd_addr.address);            APPL_TRACE_EVENT1("libbt-hci init returns %d", result);            assert(result == BT_HC_STATUS_SUCCESS);            if (hci_logging_enabled == TRUE || hci_logging_config == TRUE)                bt_hc_if->logging(BT_HC_LOGGING_ON, hci_logfile);    #if (defined (BT_CLEAN_TURN_ON_DISABLED) && BT_CLEAN_TURN_ON_DISABLED == TRUE)            APPL_TRACE_DEBUG1("%s  Not Turninig Off the BT before Turninig ON", __FUNCTION__);            /* Do not power off the chip before powering on  if BT_CLEAN_TURN_ON_DISABLED flag             is defined and set to TRUE to avoid below mentioned issue.             Wingray kernel driver maintains a combined  counter to keep track of             BT-Wifi state. Invoking  set_power(BT_HC_CHIP_PWR_OFF) when the BT is already             in OFF state causes this counter to be incorrectly decremented and results in undesired             behavior of the chip.             This is only a workaround and when the issue is fixed in the kernel this work around             should be removed. */    #else            /* toggle chip power to ensure we will reset chip in case               a previous stack shutdown wasn't completed gracefully */            bt_hc_if->set_power(BT_HC_CHIP_PWR_OFF);    #endif            bt_hc_if->set_power(BT_HC_CHIP_PWR_ON);            bt_hc_if->preload(NULL);        }    }

bt_hc_interface_t和前面的bt_interface_t接口一样,根据其说明文件,其是Bluetooth Host/Controller Interface。这个接口的实现在哪呢,看到目录,我们在src目录找找,也可以对整个project进行检索,很快我们发现了对该接口的实现。

代码位置:external\bluetooth\bluedroid\hci\include\bt_hci_lib.h
    /*     * Bluetooth Host/Controller Interface     */    typedef struct {        /** Set to sizeof(bt_hc_interface_t) */        size_t          size;        /**         * Opens the interface and provides the callback routines         * to the implemenation of this interface.         */        int   (*init)(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr);        /** Chip power control */        void (*set_power)(bt_hc_chip_power_state_t state);        /** Set low power mode wake */        int   (*lpm)(bt_hc_low_power_event_t event);        /** Called prior to stack initialization */        void (*preload)(TRANSAC transac);        /** Called post stack initialization */        void (*postload)(TRANSAC transac);        /** Transmit buffer */        int (*transmit_buf)(TRANSAC transac, char *p_buf, int len);        /** Controls receive flow */        int (*set_rxflow)(bt_rx_flow_state_t state);        /** Controls HCI logging on/off */        int (*logging)(bt_hc_logging_state_t state, char *p_path);        /** Closes the interface */        void  (*cleanup)( void );    } bt_hc_interface_t;

bt_hc_interface_t接口在bt_hci_bdroid.c中有具体实现,现在再次回到bte_hci_enable()

代码位置:external\bluetooth\bluedroid\hci\src\bt_hci_bdroid.c
    static const bt_hc_interface_t bluetoothHCLibInterface = {        sizeof(bt_hc_interface_t),        init,        set_power,        lpm,        preload,        postload,        transmit_buf,        set_rxflow,        logging,        cleanup    };

首先调用了bt_hc_if的init函数,根据注释,init函数主要用来打开interface并且提供回调机制,我们跳进去看下。

代码位置:external\bluetooth\bluedroid\main\bte_main.c
    static void bte_hci_enable(void)    {        APPL_TRACE_DEBUG1("%s", __FUNCTION__);        preload_start_wait_timer();        if (bt_hc_if)        {            int result = bt_hc_if->init(&hc_callbacks, btif_local_bd_addr.address);            APPL_TRACE_EVENT1("libbt-hci init returns %d", result);            assert(result == BT_HC_STATUS_SUCCESS);            if (hci_logging_enabled == TRUE || hci_logging_config == TRUE)                bt_hc_if->logging(BT_HC_LOGGING_ON, hci_logfile);    #if (defined (BT_CLEAN_TURN_ON_DISABLED) && BT_CLEAN_TURN_ON_DISABLED == TRUE)            APPL_TRACE_DEBUG1("%s  Not Turninig Off the BT before Turninig ON", __FUNCTION__);            /* Do not power off the chip before powering on  if BT_CLEAN_TURN_ON_DISABLED flag             is defined and set to TRUE to avoid below mentioned issue.             Wingray kernel driver maintains a combined  counter to keep track of             BT-Wifi state. Invoking  set_power(BT_HC_CHIP_PWR_OFF) when the BT is already             in OFF state causes this counter to be incorrectly decremented and results in undesired             behavior of the chip.             This is only a workaround and when the issue is fixed in the kernel this work around             should be removed. */    #else            /* toggle chip power to ensure we will reset chip in case               a previous stack shutdown wasn't completed gracefully */            bt_hc_if->set_power(BT_HC_CHIP_PWR_OFF);    #endif            bt_hc_if->set_power(BT_HC_CHIP_PWR_ON);            bt_hc_if->preload(NULL);        }    }

我们都知道,蓝牙的话分为HostController,两者通过HCI层进行数据交互。Host的话是Android操作系统,这部分是通用的,由google公司提供;Controller的话是一个个芯片厂商提供的,这部分各个厂商都有其独立设计。在Android4.2后的bluedroid中将所有厂商的设计文件放在vendor目录中,而为了实现上层对芯片的操作,bluedroid提供了专门的接口,下面我们通过代码分析来了解bluedroid是怎么完成这些操作的。

这个init函数非常的长,首先看到第一个重要跳转就是init_vnd_if(local_bdaddr),从函数的字面理解就是调用厂商vender的init函数,在函数的注释中了解到这个函数主要完成vendor lib interface的初始化操作。

代码位置:external\bluetooth\bluedroid\hci\src\bt_hci_bdroid.c
    static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr)    {        ...        /* store reference to user callbacks */        bt_hc_cbacks = (bt_hc_callbacks_t *) p_cb;        init_vnd_if(local_bdaddr);        ...    }

在这里完成了厂商定制功能与Android系统的绑定,系统后面都可以通过bt_vnd_if调用厂商的定制功能。在这里我们不深入分析厂商具体做了什么。

首先利用dlopen方法打开了libbt-vendor.so厂商的配置文件,并将动态库的句柄赋给dlhandle,再通过dlsym方法将"BLUETOOTH_VENDOR_LIB_INTERFACE"句柄返回给bt_vnd_if,关于libbt-vendor.so的介绍说明可以看android bluetooth 移植相关注意事项。在这里主要就是要厂商实现bt_vendor_interface_t这一通用接口,并且将接口赋值给bt_vnd_if,后面就可以通过bt_vnd_if实现对厂商定制功能的调用。最后再利用厂商实现的init方法实现蓝牙芯片的init操作(厂商具体决定init过程的具体操作)。

代码位置:external\bluetooth\bluedroid\hci\src\bt_hw.c
    void init_vnd_if(unsigned char *local_bdaddr)    {        void *dlhandle;        dlhandle = dlopen("libbt-vendor.so", RTLD_NOW);        if (!dlhandle)        {            ALOGE("!!! Failed to load libbt-vendor.so !!!");            return;        }        bt_vnd_if = (bt_vendor_interface_t *) dlsym(dlhandle, "BLUETOOTH_VENDOR_LIB_INTERFACE");        if (!bt_vnd_if)        {            ALOGE("!!! Failed to get bt vendor interface !!!");            return;        }        bt_vnd_if->init(&vnd_callbacks, local_bdaddr);    }

bt_vendor_lib.h的定义如下,可以看到dlsym方法返回的bt_vnd_if就是指向了bt_vendor_interface_t结构体。

代码位置:external\bluetooth\bluedroid\hci\include\bt_vendor_lib.h
    /*     * Bluetooth Host/Controller VENDOR Interface     */    typedef struct {        /** Set to sizeof(bt_vndor_interface_t) */        size_t          size;        /*         * Functions need to be implemented in Vendor libray (libbt-vendor.so).         */        /**         * Caller will open the interface and pass in the callback routines         * to the implemenation of this interface.         */        int   (*init)(const bt_vendor_callbacks_t* p_cb, unsigned char *local_bdaddr);        /**  Vendor specific operations */        int (*op)(bt_vendor_opcode_t opcode, void *param);        /** Closes the interface */        void  (*cleanup)(void);    } bt_vendor_interface_t;    /*     * External shared lib functions/data     */    /* Entry point of DLib --     *      Vendor library needs to implement the body of bt_vendor_interface_t     *      structure and uses the below name as the variable name. HCI library     *      will use this symbol name to get address of the object through the     *      dlsym call.     */    extern const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE;

回到bt_hci_bdroid.c函数,在init_vnd_if方法中注册了厂商的hci接口,utils_init()初始化了一个互斥锁,暂不去管他,后面用到了#ifdef…#else…#endif的宏if语句,默认情况下,Android bluedroid是采用h4也就是uart传输方式,也就是其声明了一个hci_h4_func_table函数体,并将p_hci_if指向了该函数体,随后调用了hci_h4_func_table中的init函数。

代码位置:external\bluetooth\bluedroid\hci\src\bt_hci_bdroid.c
    static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr)    {        ...        init_vnd_if(local_bdaddr);        utils_init();    #ifdef HCI_USE_MCT        extern tHCI_IF hci_mct_func_table;        p_hci_if = &hci_mct_func_table;    #else        extern tHCI_IF hci_h4_func_table;        p_hci_if = &hci_h4_func_table;    #endif        p_hci_if->init();        ...    }

我们跳到hci_h4_func_table函数体重看看其具体干了什么,可以看到其定义了一个h4的服务接口,在hci_h4_init函数中奇首先初始化了一个队列h4_cb.acl_rx_q用于接收acl数据。然后设置了一些参数,最后init了btsnoop,也就是初始化了抓取蓝牙hci log的btsnoop,实际就是初始化了一个thread,具体就不跳进去了,代码在external\bluetooth\bluedroid\hci\src\btsnoop.c

代码位置:external\bluetooth\bluedroid\hci\src\hci_h4.c
    void hci_h4_init(void)    {        HCIDBG("hci_h4_init");        memset(&h4_cb, 0, sizeof(tHCI_H4_CB));        utils_queue_init(&(h4_cb.acl_rx_q));        /* Per HCI spec., always starts with 1 */        num_hci_cmd_pkts = 1;        /* Give an initial values of Host Controller's ACL data packet length         * Will update with an internal HCI(_LE)_Read_Buffer_Size request         */        h4_cb.hc_acl_data_size = 1021;        h4_cb.hc_ble_acl_data_size = 27;        btsnoop_init();    }    /******************************************************************************    **  HCI H4 Services interface table    ******************************************************************************/    const tHCI_IF hci_h4_func_table =    {        hci_h4_init,        hci_h4_cleanup,        hci_h4_send_msg,        hci_h4_send_int_cmd,        hci_h4_get_acl_data_length,        hci_h4_receive_msg    };

bt_hc_worker_thread线程里面有很多重要的事件处理,可以具体看看。

再次回到bt_hci_bdroid.c函数,在初始化hci后,其继续初始化了userial,也就是初始化了串口,这里需要根据前面的#ifdef来决定跳转到那个userial.c文件,文件位置在external\bluetooth\bluedroid\hci\src\userial.c。随后对lpm进行了初始化,在lpm_init函数中调用了芯片厂商中BT_VND_OP_GET_LPM_IDLE_TIMEOUT所对应的函数,然后赋值给bt_lpm_cb.timeout_ms,文件位置在external\bluetooth\bluedroid\hci\src\lmp.c。在utils_queue_init初始化了一个发送队列。在init函数最后创建了一个bt_hc_worker_thread蓝牙工作主线程,用于发送和接收命令。

代码位置:external\bluetooth\bluedroid\hci\src\bt_hci_bdroid.c
    static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr)    {        ...        p_hci_if->init();        userial_init();        lpm_init();        utils_queue_init(&tx_q);        ...        pthread_mutex_init(&hc_cb.mutex, NULL);        pthread_cond_init(&hc_cb.cond, NULL);        pthread_attr_init(&thread_attr);        if (pthread_create(&hc_cb.worker_thread, &thread_attr, \                           bt_hc_worker_thread, NULL) != 0)        {            ...        }        ...        return BT_HC_STATUS_SUCCESS;    }

回到最初的bte_hci_enable()函数,上面就完成了bt_hc_if->init函数,然后根据是否需要打开hci log来打开hci log,后面的宏if语句用于判断是否已经打开蓝牙,如果没有则先关闭chip power bt_hc_if->set_power(BT_HC_CHIP_PWR_OFF)然后再打开chip power bt_hc_if->set_power(BT_HC_CHIP_PWR_ON)。最后调用了bt_hc_if->preload(NULL)函数,主要进行一些芯片的预操作,具体分析见后文。

代码位置:external\bluetooth\bluedroid\main\bte_main.c
    static void bte_hci_enable(void)    {        APPL_TRACE_DEBUG1("%s", __FUNCTION__);        preload_start_wait_timer();        if (bt_hc_if)        {            int result = bt_hc_if->init(&hc_callbacks, btif_local_bd_addr.address);            ...            if (hci_logging_enabled == TRUE || hci_logging_config == TRUE)                bt_hc_if->logging(BT_HC_LOGGING_ON, hci_logfile);    #if (defined (BT_CLEAN_TURN_ON_DISABLED) && BT_CLEAN_TURN_ON_DISABLED == TRUE)            APPL_TRACE_DEBUG1("%s  Not Turninig Off the BT before Turninig ON", __FUNCTION__);            /* Do not power off the chip before powering on  if BT_CLEAN_TURN_ON_DISABLED flag             is defined and set to TRUE to avoid below mentioned issue.             Wingray kernel driver maintains a combined  counter to keep track of             BT-Wifi state. Invoking  set_power(BT_HC_CHIP_PWR_OFF) when the BT is already             in OFF state causes this counter to be incorrectly decremented and results in undesired             behavior of the chip.             This is only a workaround and when the issue is fixed in the kernel this work around             should be removed. */    #else            /* toggle chip power to ensure we will reset chip in case               a previous stack shutdown wasn't completed gracefully */            bt_hc_if->set_power(BT_HC_CHIP_PWR_OFF);    #endif            bt_hc_if->set_power(BT_HC_CHIP_PWR_ON);            bt_hc_if->preload(NULL);        }    }

找到bt_hc_interface_t接口在bt_hci_bdroid.cset_power()的具体实现,首先设置了power的状态,然后调用厂商接口bt_vnd_if中的BT_VND_OP_POWER_CTRL所对应的函数,执行芯片的上电操作。

代码位置:external\bluetooth\bluedroid\hci\src\bt_hci_bdroid.c
    /** Chip power control */    static void set_power(bt_hc_chip_power_state_t state)    {        int pwr_state;        BTHCDBG("set_power %d", state);        /* Calling vendor-specific part */        pwr_state = (state == BT_HC_CHIP_PWR_ON) ? BT_VND_PWR_ON : BT_VND_PWR_OFF;        if (bt_vnd_if)            bt_vnd_if->op(BT_VND_OP_POWER_CTRL, &pwr_state);        else            ALOGE("vendor lib is missing!");    }

找到bt_hc_interface_t接口在bt_hci_bdroid.cpreload()的具体实现,其就是发送了一个事件,也就是向我们前面在bt_hci_bdroid.c创建的线程bt_hc_worker_thread发送了HC_EVENT_PRELOAD消息,我们跳到线程里对该消息的处理函数中,可以看到,其首先打开了串口userial_open(USERIAL_PORT_1),然后调用了vendor定义的BT_VND_OP_FW_CFG所对应的函数进行芯片framework的config操作。

代码位置:external\bluetooth\bluedroid\hci\src\bt_hci_bdroid.c
    /** Called prio to stack initialization */    static void preload(TRANSAC transac)    {        BTHCDBG("preload");        bthc_signal_event(HC_EVENT_PRELOAD);    }    ...    static void *bt_hc_worker_thread(void *arg)    {        ...        while (lib_running)        {            pthread_mutex_lock(&hc_cb.mutex);            while (ready_events == 0)            {                pthread_cond_wait(&hc_cb.cond, &hc_cb.mutex);            }            events = ready_events;            ready_events = 0;            pthread_mutex_unlock(&hc_cb.mutex);            ...            if (events & HC_EVENT_PRELOAD)            {                userial_open(USERIAL_PORT_1);                /* Calling vendor-specific part */                if (bt_vnd_if)                {                    bt_vnd_if->op(BT_VND_OP_FW_CFG, NULL);                }                else                {                    if (bt_hc_cbacks)                        bt_hc_cbacks->preload_cb(NULL, BT_HC_PRELOAD_FAIL);                }            }            ...        }        ALOGI("bt_hc_worker_thread exiting");        lib_running = 0;        pthread_exit(NULL);        return NULL;    // compiler friendly    }

userial_open中主要调用vendor定义的BT_VND_OP_USERIAL_OPEN所对应的函数进行userial的打开操作,然后再创建了一个串口读取线程userial_read_thread

代码位置:external\bluetooth\bluedroid\hci\src\userial.c
    uint8_t userial_open(uint8_t port)    {        ...        if (userial_running)        {            /* Userial is open; close it first */            userial_close();            utils_delay(50);        }        ...        /* Calling vendor-specific part */        if (bt_vnd_if)        {            result = bt_vnd_if->op(BT_VND_OP_USERIAL_OPEN, &fd_array);            ...        }        else        {            ALOGE("userial_open: missing vendor lib interface !!!");            ALOGE("userial_open: unable to open UART port");            return FALSE;        }        ...        if (pthread_create(&(userial_cb.read_thread), &thread_attr, \                           userial_read_thread, NULL) != 0 )        {            ALOGE("pthread_create failed!");            return FALSE;        }        ...        return TRUE;    }

到现在已经完成了bte_hci_enable的全部操作,回忆下,其首先绑定了蓝牙芯片厂商定制功能函数,首先调用了vendor芯片的init函数;然后根据实际需要,通过宏if语句绑定了hci函数体hci_h4_func_table,并调用其init函数进行hci的初始化;然后调用了userial和lpm的初始化,并创建了了用于蓝牙hc工作的主线程;接着进行了蓝牙的上电操作;最后进行了蓝牙的preload操作,包括打开userial,创建userial read线程,并执行蓝牙芯片的framework config操作。

再次回到bte_main.c中的bte_main_enable()函数,其最后create了一个GKI任务,并启动了该任务。

代码位置:external\bluetooth\bluedroid\main\bte_main.c
    void bte_main_enable()    {        APPL_TRACE_DEBUG1("%s", __FUNCTION__);        /* Initialize BTE control block */        BTE_Init();        lpm_enabled = FALSE;        bte_hci_enable();        GKI_create_task((TASKPTR)btu_task, BTU_TASK, BTE_BTU_TASK_STR,                        (UINT16 *) ((UINT8 *)bte_btu_stack + BTE_BTU_STACK_SIZE),                        sizeof(bte_btu_stack));        GKI_run(0);    }

至此,蓝牙的enable操作的就全部结束了,文章中存在很多问题,欢迎大家的指正。

0 0
原创粉丝点击