返回
顶部

修改密码

[Android源码分析]蓝牙打开分析--苦尽甘来之再次回到jni之上

+1

-1

收藏

+1

-1

点赞0

评论0

第三章,苦尽甘来之再次回到jni之上 经过了上面两章的分析,我们基本已经对一次的“下乡活动”了解清楚了,下面我们就要详细分析再次回到jni之上的一些操作了。再这之前,我们先来看看这次下乡活动从乡下都带来了什么? 其实很少蛮清晰的,就是带回来了几…
第三章,苦尽甘来之再次回到jni之上
 
         经过了上面两章的分析,我们基本已经对一次的“下乡活动”了解清楚了,下面我们就要详细分析再次回到jni之上的一些操作了。再这之前,我们先来看看这次下乡活动从乡下都带来了什么?
 
         其实很少蛮清晰的,就是带回来了几个property change的event,他们分别是UUIDs,pairable=false,powered=false,class, discoverable=false。我们来看一下,他们对上层都有哪些影响。
 
         eventloop中对property change的处理函数是:
 
/*package*/ void onPropertyChanged(String[] propValues) {
 
         所以,我们要分析各个propertychange的影响分析这个函数就可以了。下面,我们来具体分析这些property change的影响:
 
1、UUIDs的处理
 
[cpp]  
} else if (name.equals("Devices") || name.equals("UUIDs")) {  
          String value = null;  
          int len = Integer.valueOf(propValues[1]);  
          if (len > 0) {  
              StringBuilder str = new StringBuilder();  
              for (int i = 2; i < propValues.length; i++) {  
                  str.append(propValues[i]);  
                  str.append(",");  
              }  
              value = str.toString();  
          }  
//加入到property中,把UUIDs和对应的value保存  
          adapterProperties.setProperty(name, value);  
          if (name.equals("UUIDs")) {  
        //若是uuid,这个函数是很重要的  
              mBluetoothService.updateBluetoothState(value);  
          }  
 
 
 
1.2 mBluetoothService.updateBluetoothState(value)函数分析
 
[cpp]  
 /*package*/ synchronized void updateBluetoothState(String uuids) {  
        ParcelUuid[] adapterUuids = convertStringToParcelUuid(uuids);  
      
//当uuid都被注册成功之后,就可以发送SERVICE_RECORD_LOADED的msg了  
        if (mAdapterUuids != null &&  
            BluetoothUuid.containsAllUuids(adapterUuids, mAdapterUuids)) {  
            mBluetoothState.sendMessage(BluetoothAdapterStateMachine.SERVICE_RECORD_LOADED);  
        }  
}  
 
 
 
          所以,UUIDs的property change的最终目的就是发送SERVICE_RECORD_LOADED的msg,这个msg是从warmup到hotoff的关键条件,这个我们在蓝牙的状态机里面有详细分析,不过,我们不妨在这里也再次分析一下:
 
[cpp] 
switch(message.what) {  
               case SERVICE_RECORD_LOADED:  
                   removeMessages(PREPARE_BLUETOOTH_TIMEOUT);  
        //转换到hotoff的状态  
                   transitionTo(mHotOff);  
                   break;  
到了hotoff状态之后,我们需要继续处理在poweroff状态中传入的turnon continue的msg:  
               case TURN_ON_CONTINUE:  
            //这个就是设置powered为true  
                   mBluetoothService.switchConnectable(true);  
                   transitionTo(mSwitching);  
                   break;  
//从注释来看,这里是用来设置connectable和pairable的,又要到jni层之下,不过我们直接去看吧,就没有必要再分开分析了。  
 /*package*/ synchronized void switchConnectable(boolean on) {  
       setAdapterPropertyBooleanNative("Powered", on ? 1 : 0);  
 
 
 
1.3 bluez中set property的powered的处理
 
这个函数是处理很多property的不同的,所以,这里我们直接分析powered的处理。
 
[cpp]  
    } else if (g_str_equal("Powered", property)) {  
        gboolean powered;  
    //得到参数,这里就是1了  
        if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)  
            return btd_error_invalid_args(msg);  
  
        dbus_message_iter_get_basic(&sub, &powered);  
//调用这个函数  
        return set_powered(conn, msg, powered, data);  
}  
  
下面就来看一下set_powered都做了些什么:  
static DBusMessage *set_powered(DBusConnection *conn, DBusMessage *msg,  
                gboolean powered, void *data)  
{  
    struct btd_adapter *adapter = data;  
    uint8_t mode;  
    int err;  
    //就是先这个了  
    if (powered) {  
        //mode是off  
        mode = get_mode(&adapter->bdaddr, "on");  
//所以,这个地方是传入的false  
        return set_discoverable(conn, msg, mode == MODE_DISCOVERABLE,  
                                    data);  
    }  
……  
  
    return NULL;  
}  
static DBusMessage *set_discoverable(DBusConnection *conn, DBusMessage *msg,  
                gboolean discoverable, void *data)  
{  
    struct btd_adapter *adapter = data;  
    uint8_t mode;  
    int err;  
    //这里discoverable是0,所以mode connectable  
    mode = discoverable ? MODE_DISCOVERABLE : MODE_CONNECTABLE;  
    //adapter的mode是off  
    if (mode == adapter->mode) {  
        adapter->global_mode = mode;  
        return dbus_message_new_method_return(msg);  
    }  
//这里adapter的mode是off,mode是iteconnectable  
    err = set_mode(adapter, mode, msg);  
    /* when called by discov_timeout_handler(), msg may be NULL, and cause dbus error */  
    if (err < 0 && msg != NULL)  
        return btd_error_failed(msg, strerror(-err));  
  
    return NULL;  
}  
继续看  
static int set_mode(struct btd_adapter *adapter, uint8_t new_mode,  
            DBusMessage *msg)  
{  
    int err;  
    const char *modestr;  
  
    if (adapter->pending_mode != NULL)  
        return -EALREADY;  
    //我们是肯定up了,new mode为connectable  
    if (!adapter->up && new_mode != MODE_OFF) {  
        err = adapter_ops->set_powered(adapter->dev_id, TRUE);  
        if (err < 0)  
            return err;  
  
        goto done;  
    }  
  
    if (adapter->up && new_mode == MODE_OFF) {  
        err = adapter_ops->set_powered(adapter->dev_id, FALSE);  
        if (err < 0)  
            return err;  
  
        adapter->off_requested = TRUE;  
  
        goto done;  
    }  
  
    if (new_mode == adapter->mode)  
        return 0;  
    //new mode 是connectable,就是hciops中的set discoverable,同时因为discoverable是false,所以,就是page scan  
    err = adapter_set_mode(adapter, new_mode);  
done:  
    //新的mode 是connectable  
    modestr = mode2str(new_mode);  
    //把它写入到config文件on mode中  
    write_device_mode(&adapter->bdaddr, modestr);  
  
    DBG("%s", modestr);  
  
    if (msg != NULL) {  
        struct session_req *req;  
    //用来看是否需要回给jni层内容,这里必然有一个  
        req = find_session_by_msg(adapter->mode_sessions, msg);  
        if (req) {  
            adapter->pending_mode = req;  
            session_ref(req);  
        } else  
            /* Wait for mode change to reply */  
            adapter->pending_mode = create_session(adapter,  
                    connection, msg, new_mode, NULL);  
    } else  
        /* Nothing to reply just write the new mode */  
        adapter->mode = new_mode;  
  
    return 0;  
}  
 
 
 
所以,这里其实说白了就是发送了一个write scan enable的cmd,这个cmd的event我们在前文中都分析过了,会去read scan enable,然后通知上层pairable的property change。这个我们在2中进行分析。
 
2. 对pairable的property change的处理
 
同样的,property change的处理还是在eventloop中。
 
[cpp] 
} else if (name.equals("Pairable") || name.equals("Discoverable")) {  
        //设置property的值  
         adapterProperties.setProperty(name, propValues[1]);  
  
         if (name.equals("Discoverable")) {  
             mBluetoothState.sendMessage(BluetoothAdapterStateMachine.SCAN_MODE_CHANGED);  
         }  
//得到对应的值  
         String pairable = name.equals("Pairable") ? propValues[1] :  
             adapterProperties.getProperty("Pairable");  
         String discoverable = name.equals("Discoverable") ? propValues[1] :  
             adapterProperties.getProperty("Discoverable");  
  
         // This shouldn't happen, unless Adapter Properties are null.  
         if (pairable == null || discoverable == null)  
             return;  
//这里开始的时候discoverable是false,pairable是true  
           int mode = BluetoothService.bluezStringToScanMode(  
                 pairable.equals("true"),  
                 discoverable.equals("true"));  
         if (mode >= 0) {  
发送ACTION_SCAN_MODE_CHANGED的action  
             Intent intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);  
             intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, mode);  
             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);  
             mContext.sendBroadcast(intent, BLUETOOTH_PERM);  
         }  
 
 
 
所以,对pairable这一property change的反应就是发送了ACTION_SCAN_MODE_CHANGED的action。那么我们就来分析一下究竟有多少地方注册了这个action的receiver。
 
2.1 ACTION_SCAN_MODE_CHANGED的receiver分析
 
         注册了这个action receiver的地方有:BluetoothDiscoverableEnabler。
 
2.1.1 BluetoothDiscoverableEnabler中receiver的分析  
 
[cpp]  
public void onReceive(Context context, Intent intent) {  
            if (BluetoothAdapter.ACTION_SCAN_MODE_CHANGED.equals(intent.getAction())) {  
                int mode = intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE,  
                        BluetoothAdapter.ERROR);  
//只要不是error,就需要handle mode的changed  
                if (mode != BluetoothAdapter.ERROR) {  
                    handleModeChanged(mode);  
                }  
            }  
//mode changed的处理  
    void handleModeChanged(int mode) {  
    //打开的情况下,不会走到这,只有在后期设置可发现的时候,才会走到。UI上会显示一个可发现的倒计时吧。到了那时再具体分析,其实蛮简单的  
        if (mode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {  
            mDiscoverable = true;  
            updateCountdownSummary();  
        } else {  
            //这里的话,这里是false,这里就是显示两句话:  
//1)假如没有配对设备,那么就是显示不让其他蓝牙设备检测到  
//2)假如已经配对了设备,那么就是显示只让已配对的设备检测到  
            mDiscoverable = false;  
            setSummaryNotDiscoverable();  
        }  
 
 
 
3 powered的property change的处理
 
         同样的,对powered的property change的处理:
 
   } else if (name.equals("Powered")) {
 
//就是发送POWER_STATE_CHANGED的msg。一看就知道是个state machine的msg,我们去看看吧            mBluetoothState.sendMessage(BluetoothAdapterStateMachine.POWER_STATE_CHANGED,
 
                propValues[1].equals("true") ? new Boolean(true) : new Boolean(false));
 
 
 
此时,statemachine处于swtiching的状态:
 
 
 
[cpp]  
case POWER_STATE_CHANGED:  
  
     removeMessages(POWER_DOWN_TIMEOUT);  
  
             //这个if是false,我们是true,进else,我们在turnning on的状态,所以,没有什么好说的。  
  
     if (!((Boolean) message.obj)) {  
  
         if (mPublicState == BluetoothAdapter.STATE_TURNING_OFF) {  
  
             transitionTo(mHotOff);  
  
             finishSwitchingOff();  
  
             if (!mContext.getResources().getBoolean  
  
             (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {  
  
                 deferMessage(obtainMessage(TURN_COLD));  
  
             }  
  
         }  
  
     } else {  
  
         if (mPublicState != BluetoothAdapter.STATE_TURNING_ON) {  
  
             if (mContext.getResources().getBoolean  
  
             (com.android.internal.R.bool.config_bluetooth_adapter_quick_switch)) {  
  
                 recoverStateMachine(TURN_HOT, null);  
  
             } else {  
  
                 recoverStateMachine(TURN_COLD, null);  
  
             }  
  
         }  
  
     }  
  
     break;  
 
所以,在这里,整个powered的change并没有什么特别的处理。
 
 
 
4、 discoverable的property change的处理
 
这里discoveable是false,和上面pairable的处理时一个函数,只是多进入了一下这个函数:
 
[cpp] 
 if (name.equals("Discoverable")) {  
                mBluetoothState.sendMessage(BluetoothAdapterStateMachine.SCAN_MODE_CHANGED);  
            }  
至于上层ui的改变,因为discoverable是false,所以,还是不会做什么改变。所以就不去分析了,我们仍然只分析BluetoothAdapterStateMachine.SCAN_MODE_CHANGED这个action的处理。  
    同样的,他仍然是一个adatperstatemachine的action,我们去swtiching的状态看看他的处理。  
                case SCAN_MODE_CHANGED:  
                    // This event matches mBluetoothService.switchConnectable action  
                    if (mPublicState == BluetoothAdapter.STATE_TURNING_ON) {  
                        // set pairable if it's not  
                //假如pairable不是true,就去设置pairable,因为我们已经设置了,所以这就不会有什么了。  
                        mBluetoothService.setPairable();  
            //这个函数在蓝牙的状态机装换中已经分析过,不再详细分析。  
                        mBluetoothService.initBluetoothAfterTurningOn();  
            //转变到buetoothon的状态  
                        transitionTo(mBluetoothOn);  
        //广播BluetoothAdapter.ACTION_STATE_CHANGED,这次的值是STATE_ON,所以,我们还是有必要再次分析一下的。  
                        broadcastState(BluetoothAdapter.STATE_ON);  
                        // run bluetooth now that it's turned on  
                        // Note runBluetooth should be called only in adapter STATE_ON  
                //主要就是自动连接。其它也没有做什么特别的,见下面的简单分析  
                        mBluetoothService.runBluetooth();  
                    }  
                    break;  
  
    /*package*/ void runBluetooth() {  
    //若是有可连接的设备,这里去进行自动连接。这个这里就不分析了  
        autoConnect();  
  
        // Log bluetooth on to battery stats.  
        //告诉电池管理那边,蓝牙打开了  
        long ident = Binder.clearCallingIdentity();  
        try {  
            mBatteryStats.noteBluetoothOn();  
        } catch (RemoteException e) {  
            Log.e(TAG, "", e);  
        } finally {  
            Binder.restoreCallingIdentity(ident);  
        }  
}  
 
我们在2.1.1中已经对BluetoothAdapter.ACTION_STATE_CHANGED这个action进行了详细的分析。它主要就是把ui上的按钮高亮了,其它还有一写profile会随着这个进行初始化,比如opp之类的,这里等到具体分析到的时候我们再详细的解释吧。
 
 

扫一扫在手机打开

评论
已有0条评论
0/150
提交
热门评论
相关推荐
Android蓝牙开发
  • 近场通信
  • 2022-05-20 18:30
  • 5 0 0
+1
android 蓝牙分析
  • 近场通信
  • 2022-05-20 18:30
  • 10 0 0
+1
android4.0蓝牙使能的详细解析
  • 近场通信
  • 2022-05-20 18:30
  • 2 0 0
+1
Android 蓝牙API 之 BluetoothAdapter 类
  • 近场通信
  • 2022-05-20 18:30
  • 1 0 0
+1
android蓝牙源码分析
  • 近场通信
  • 2022-05-20 18:30
  • 5 0 0
+1
今日要闻
换一批
热点排行