开发一个网站的步骤流程,网站建设合同怎么交印花税,酒店宾馆型网站开发,php快速建站系统转自#xff1a;http://blog.csdn.net/baimy1985/article/details/8922508 4.2的蓝牙打开流程这一部分还是有些变化的#xff0c;从界面上看蓝牙开关就是设置settings里那个switch开关#xff0c;widget开关当然也可以#xff0c;起点不同而已#xff0c;后续的流程是一样…转自http://blog.csdn.net/baimy1985/article/details/8922508 4.2的蓝牙打开流程这一部分还是有些变化的从界面上看蓝牙开关就是设置settings里那个switch开关widget开关当然也可以起点不同而已后续的流程是一样的。先来看systemServer.java的代码蓝牙服务开启的地方最后一个else分支是我们关心的前两个是模拟器的一个测试模式的。 [java] view plain copy print ? 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 { Slog.i(TAG, Bluetooth Manager Service); bluetooth new BluetoothManagerService(context); ServiceManager.addService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, bluetooth); } 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 {
Slog.i(TAG, Bluetooth Manager Service);
bluetooth new BluetoothManagerService(context);
ServiceManager.addService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, bluetooth);
} 暂且看下bluetoothManagerService的构造方法代码有点多我们只看两个地方 loadStoredNameAndAddress()是读取蓝牙打开默认名称的地方isBluetoothPersistedStateOn()是判断是否已打开蓝牙的如果已打开后续操作要执行开启蓝牙的动作前面那几行注册广播其中就有这个作用。 [java] view plain copy print ? 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; } } 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;
}
} 回到界面开关那个看得着的地方界面上开关就是BluetoothEnabler.java这个类了而setBluetoothEnabled()则是具体开关动作。看下代码 [java] view plain copy print ? 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); } 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);
}
这里在判断是飞行模式不知道为什么没有return如果是飞行模式会有提示toast弹出既然这样源码为什么还要执行下面打开流程呢也许是个bug不细究这个了继续看setBluetoothEnabled()方法做什么了很明显mLocalAdapter(LocalBluetoothAdapter )只是个过渡里面的 mAdapter(BluetoothAdapter)才是真正的主角代码如下 [java] view plain copy print ? 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 { ......... } } 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 {
.........
}
} 在BluetoothAdapter.java里可以看到一个单例模式的应用主要提供给其它程序调用蓝牙的一些方法用的外部程序想调用蓝牙的方法就要先用这个
拿到BluetoothAdapter对象代码也简单看下吧里面是典型的binder应用。 [java] view plain copy print ? 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; 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()调用先回到BluetoothManagerService.java的enable()再进一步来到BluetoothManagerService.java中的handleEnable()
方法后面要跳转到新类了贴出来一起看下这部分好像不同版本还有些出入不过核心的启动service是一样的不影响理解。 [java] view plain copy print ? private void handleEnable(boolean persist, boolean quietMode) { synchronized(mConnection) { if ((mBluetooth null) (!mBinding)) { //Start bind timeout and bind Message timeoutMsgmHandler.obtainMessage(MESSAGE_TIMEOUT_BIND); mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS); mConnection.setGetNameAddressOnly(false); Intent i new Intent(IBluetooth.class.getName()); if (!mContext.bindService(i, mConnection,Context.BIND_AUTO_CREATE, UserHandle.USER_CURRENT)) { mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); Log.e(TAG, Fail to bind to: IBluetooth.class.getName()); } else { mBinding true; } } private void handleEnable(boolean persist, boolean quietMode) {
synchronized(mConnection) {
if ((mBluetooth null) (!mBinding)) {
//Start bind timeout and bind
Message timeoutMsgmHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);
mHandler.sendMessageDelayed(timeoutMsg,TIMEOUT_BIND_MS);
mConnection.setGetNameAddressOnly(false);
Intent i new Intent(IBluetooth.class.getName());
if (!mContext.bindService(i, mConnection,Context.BIND_AUTO_CREATE,
UserHandle.USER_CURRENT)) {
mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
Log.e(TAG, Fail to bind to: IBluetooth.class.getName());
} else {
mBinding true;
}
} 下面跑到哪个service里去了呢在log信息里可以看到ActivityManager: Start proc com.android.bluetooth for service com.android.bluetooth/.btservice.AdapterService: 这样的信息那就是去AdapterService里看看里面一共有三个enable()跳转关系不复杂我们直接看最后一个关键的。 [java] view plain copy print ? 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; } 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;
} 状态机来了状态转换图从一个状态接受命令跳到另一个状态因为我们是在开启蓝牙所以先去的AdapterState.java内部类offstate.java里面找在这个分支USER_TURN_ON看到mAdapterService.processStart()在这里面可以看到蓝牙遍历下所支持的profile最后又发出个带AdapterState.STARTED标识的消息
处理在同文件下面的代码里 [java] view plain copy print ? case STARTED: { if (DBG) Log.d(TAG,CURRENT_STATEPENDING, MESSAGE STARTED, isTurningOn isTurningOn , isTurningOff isTurningOff); //Remove start timeout removeMessages(START_TIMEOUT); //Enable boolean ret mAdapterService.enableNative(); if (!ret) { Log.e(TAG, Error while turning Bluetooth On); notifyAdapterStateChange(BluetoothAdapter.STATE_OFF); transitionTo(mOffState); } else { sendMessageDelayed(ENABLE_TIMEOUT, ENABLE_TIMEOUT_DELAY); } case STARTED: {
if (DBG) Log.d(TAG,CURRENT_STATEPENDING, MESSAGE STARTED, isTurningOn isTurningOn , isTurningOff isTurningOff);
//Remove start timeout
removeMessages(START_TIMEOUT);
//Enable
boolean ret mAdapterService.enableNative();
if (!ret) {
Log.e(TAG, Error while turning Bluetooth On);
notifyAdapterStateChange(BluetoothAdapter.STATE_OFF);
transitionTo(mOffState);
} else {
sendMessageDelayed(ENABLE_TIMEOUT, ENABLE_TIMEOUT_DELAY);
} 看到那个enableNative()函数调用了吧又要用到JNI了稍微回头看下前面的代码我们先从应用界面开关BluetoothEnabler走到framework的BluetoothAdapter又回到package的adapterService现在又要去JNI的C代码了往常一般是packages --framework--下面一层这次顺序有些颠倒了不过这不能影响我们跟踪代码最后 还是要到下面去的。一起往下看吧。 根据android JNI的函数命名惯例很容易找到enableNative对应的C函数在packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp里面 [java] view plain copy print ? 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; } 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;
} 代码瞬间简洁了不少看来更多的故事还在下面sBluetoothInterface这是什么直接关系到下一步去哪的问题看下变量声明原来是
Const bt_interface_t *sBluetoothInterface NULL; 再去找在哪初始化搜索external目录可以找到/external/bluetooth/bluedroid/btif/src/bluetooth.c [cpp] view plain copy print ? static const bt_interface_t bluetoothInterface { sizeof(bt_interface_t), init, enable, disable, ............. start_discovery, cancel_discovery, create_bond, remove_bond, cancel_bond, ............... }; static const bt_interface_t bluetoothInterface {
sizeof(bt_interface_t),
init,
enable,
disable,
.............
start_discovery,
cancel_discovery,
create_bond,
remove_bond,
cancel_bond,
...............
};
原来在这里说下怎么找到直接跳转是不成了看这个文件夹下的mk文件那里面有libhardware目录是编译的时候要用到这个多半在hardware目录里在这里面很快可以看到bluetooth.h那里面有最我们要找的结构体定义头文件找到了再找同名C文件就快了好了继续吧看下enable()里是怎么实现的 [cpp] view plain copy print ? static int enable( void ) { ALOGI(enable); /* sanity check */ if (interface_ready() FALSE) return BT_STATUS_NOT_READY; return btif_enable_bluetooth(); } static int enable( void )
{
ALOGI(enable);
/* sanity check */
if (interface_ready() FALSE)
return BT_STATUS_NOT_READY;
return btif_enable_bluetooth();
}
又是一个新函数直接跳转比起刚才的寻觅这太幸福了 [cpp] view plain copy print ? 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(btif_local_bd_addr.address); return BT_STATUS_SUCCESS; } 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(btif_local_bd_addr.address);
return BT_STATUS_SUCCESS;
}
忘了写路径了 好在可以直接跳转下面是/external/bluetooth/bluedroid/main/bte_main.c有点长暂时只关心set_power那部分就好了 [cpp] view plain copy print ? void bte_main_enable(uint8_t *local_addr) { APPL_TRACE_DEBUG1(%s, __FUNCTION__); ........................ #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__); #else /* toggle chip power to ensure we will reset chip in case a previous stack shutdown wasnt 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); } ............................. } void bte_main_enable(uint8_t *local_addr)
{
APPL_TRACE_DEBUG1(%s, __FUNCTION__);
........................
#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__);
#else
/* toggle chip power to ensure we will reset chip in case
a previous stack shutdown wasnt 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);
}
.............................
} 路径在这里/external/bluetooth/bluedroid/hci/src/bt_hci_bdroid.c看看set_power里面有什么快到头了 [cpp] view plain copy print ? 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!); } 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_vnd_if这个是什么bt_vendor_interface_t *bt_vnd_ifNULL;和刚才的bt_interface_t 一样我们希望可以找到它的初始化那样就可以继续跟踪了不过看到下面的代码和注释在源码中我们要绝望了。路径/external/bluetooth/bluedroid/hci/include/bt_vendor_lib.h [cpp] view plain copy print ? /* 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_vendor_interface_t *bt_vnd_ifNULL; /* 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_vendor_interface_t *bt_vnd_ifNULL; google定义好了接口具体实现要看vendor厂商来做了这后面怎么实现就看各家芯片商怎么写了肯定各有不同而且这一部分代码一般是不会公开当然授权购买后除外了。所以在4.2的源码中我们只跟到这里了那后面会做什么呢加载驱动和上电这两项肯定要有了打开蓝牙没这两步怎么行类似下面的字符串 [cpp] view plain copy print ? static const char* BT_DRIVER_MODULE_PATH /system/lib/modules/mbt8xxx.ko; static const char* BT_DRIVER_MODULE_NAME bt8xxx; static const char* BT_DRIVER_MODULE_INIT_ARG init_cfg; static const char* BT_DRIVER_MODULE_INIT_CFG_PATH bt_init_cfg.conf; static const char* BT_DRIVER_MODULE_PATH /system/lib/modules/mbt8xxx.ko;
static const char* BT_DRIVER_MODULE_NAME bt8xxx;
static const char* BT_DRIVER_MODULE_INIT_ARG init_cfg;
static const char* BT_DRIVER_MODULE_INIT_CFG_PATH bt_init_cfg.conf;
在有类似下面的动作insmod加载驱动rfkill控制上下电具体厂商具体做法也不同。 [cpp] view plain copy print ? ret insmod(BT_DRIVER_MODULE_PATH, arg_buf); ret system(/system/bin/rfkill block all); ret insmod(BT_DRIVER_MODULE_PATH, arg_buf);
ret system(/system/bin/rfkill block all); 写到这关于4.2源码的蓝牙打开流程就算结束了比起4.1之前的代码感觉没有以前的直观对于vendor那部分的代码大家只能看各自厂商的代码了一般蓝牙开启后才会上电这样也比较符合逻辑和节省电量是否上电可以连上手机用adb shell看sys/class/rfkill目录下的state状态值有些厂商会把蓝牙和wifi的上电算在一起这个也是要注意的小心误判。最后呢这次文章写得有点仓促写错的或遗漏地方希望朋友指出来非常感谢。