Android6.0蓝牙探索旅程
来源:互联网 发布:网络缓存级别 影音先锋 编辑:程序博客网 时间:2024/06/05 19:33
废话不说,直接撸代码。
模块一:模拟手机设置界面打开蓝牙操作逐步分析。
Step1
对应文件packages/apps/Settings/SettingsActivity.java
private static final String[] ENTRY_FRAGMENTS = { ...... BluetoothSettings.class.getName(), ...... }```
蓝牙作为众多设置的一个,也被添加到数组中了。
Step2
蓝牙设置界面
对应文件ackages/apps/Settings/bluetooth/BluetoothSettings.java
public class BluetoothSettings extends DeviceListPreferenceFragment implements Indexable {
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
……….
final SettingsActivity activity = (SettingsActivity) getActivity();
mSwitchBar = activity.getSwitchBar();
mBluetoothEnabler = new BluetoothEnabler(activity, mSwitchBar);
mBluetoothEnabler.setupSwitchBar();
}
}
继承自fragment,添加了一个switchBar。嗯,接下来分析BluetoothEnabler这个文件时如何来控制蓝牙的开关的。
Step3
文件目录:packages/apps/Settings/bluetooth/BluetoothEnabler.java
`public void onSwitchChanged(Switch switchView, boolean isChecked) {
if (isChecked && !WirelessUtils.isRadioAllowed(mContext, Settings.Global.RADIO_BLUETOOTH)) { Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show(); // Reset switch to off switchView.setChecked(false); } MetricsLogger.action(mContext, MetricsLogger.ACTION_BLUETOOTH_TOGGLE, isChecked); Log.d(TAG, "mUpdateStatusOnly is " + mUpdateStatusOnly); /// M: if receive bt status changed broadcast, do not need enable/disable bt. if (mLocalAdapter != null && !mUpdateStatusOnly) { mLocalAdapter.setBluetoothEnabled(isChecked); } mSwitch.setEnabled(false);}`
Step4
调用bluetoothAdapter的setBluetoothEnabled(isChecked)方法,
boolean success = enabled ? mAdapter.enable() : mAdapter.disable()
终于到核心类BluetoothAdapter了。
目录来了一个大的改变从packages目录到了frameworks目录。
frameworks/base/core/java/android/bluetooth/bluetoothAdapter.java
@SystemApi public boolean enableBLE() { if (!isBleScanAlwaysAvailable()) return false; if (isLeEnabled() == true) { if (DBG) Log.d(TAG, "enableBLE(): BT is already enabled..!"); try { mManagerService.updateBleAppCount(mToken, true); } catch (RemoteException e) { Log.e(TAG, "", e); } return true; } try { if (DBG) Log.d(TAG, "Calling enableBLE"); mManagerService.updateBleAppCount(mToken, true); return mManagerService.enable(); } catch (RemoteException e) { Log.e(TAG, "", e); } return false; }
Step5
重点关注 return mManagerService.enable(); mManagerService的创建时在BluetoothAdapter中完成的
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; } /** * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance. */ BluetoothAdapter(IBluetoothManager managerService) { if (managerService == null) { throw new IllegalArgumentException("bluetooth manager service is null"); } try { mService = managerService.registerAdapter(mManagerCallback); } catch (RemoteException e) {Log.e(TAG, "", e);} mManagerService = managerService; mLeScanClients = new HashMap<LeScanCallback, ScanCallback>(); mToken = new Binder(); }
我们可以看到,getDefaultAdapter方法和构造方法配合着使用。当获取实例时,mManagerService也实例化了。首先通过ServiceManager的getService返回一个binder类型的对象,然后获取到远程对象的接口managerService ,来进行远程调用。这样我们直接查看frameworks/base/core/java/android/bluetooth/BluetoothManagerService 的enable方法。
Step5
在这里前面最终还是调用了, sendEnableMsg(false);发送了MESSAGE_ENABLE消息,我们看看,哪个handler接收了这个消息。
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); } /// M: MoMS permission check @{ if (MobileManagerUtils.isSupported()) { checkEnablePermission(); return true; } /// @} synchronized(mReceiver) { mQuietEnableExternal = false; mEnableExternal = true; // waive WRITE_SECURE_SETTINGS permission check sendEnableMsg(false); } if (DBG) Log.d(TAG, "enable returning"); return true; } private void sendEnableMsg(boolean quietMode) { mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0)); }
Step6
BluetoothManagerService有个内部类BluetoothHandler.java,继续发消息,里面有个doBind方法,发现最终拉起一个Service,看看ServiceConnection的onServiceConected方法,发现又是发消息MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED,里面会根据AdapterService和GattService的差异区别发送,最终传一个binder对象到message中,继续看看这个消息发送的目的地,他在BluetoothHandler中,这里也是把之前的binder对象转化成调用远程服务的接口,所以最终我们要看在
AdapterService和GattService是如何处理的。
public void handleMessage(Message msg) { ... case MESSAGE_ENABLE: mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); mEnable = true; handleEnable(msg.arg1 == 1); break; case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: { 。。。。 IBinder service = (IBinder) msg.obj; synchronized(mConnection) { if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service); onBluetoothGattServiceUp(); break; } // else must be SERVICE_IBLUETOOTH //Remove timeout mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); mBinding = false; mBluetooth = IBluetooth.Stub.asInterface(service); try { boolean enableHciSnoopLog = (Settings.Secure.getInt(mContentResolver, Settings.Secure.BLUETOOTH_HCI_LOG, 0) == 1); if (!mBluetooth.configHciSnoopLog(enableHciSnoopLog)) { Log.e(TAG,"IBluetooth.configHciSnoopLog return false"); } } catch (RemoteException e) { Log.e(TAG,"Unable to call configHciSnoopLog", e); }..... break; } case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: { Log.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: " + msg.arg1); synchronized(mConnection) { if (msg.arg1 == SERVICE_IBLUETOOTH) { // if service is unbinded already, do nothing and return if (mBluetooth == null) break; mBluetooth = null; } else if (msg.arg1 == SERVICE_IBLUETOOTHGATT) { mBluetoothGatt = null; break; } else { Log.e(TAG, "Bad msg.arg1: " + msg.arg1); break; } } ... } private void handleEnable(boolean quietMode) { synchronized(mConnection) { if ((mBluetooth == null) && (!mBinding)) { 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 | Context.BIND_IMPORTANT, UserHandle.CURRENT)) { } } boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) { ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) { Log.e(TAG, "Fail to bind to: " + intent); return false; } return true; } private class BluetoothServiceConnection implements ServiceConnection {。。。。。 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); } 。。。。 }
Step7
上面已经说到,要找AdapterService和GattService里继续追踪。接下来重点考虑AdapterService,他的路径在Packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService,所以又从framework层调到了app层。从何处入手了,Step6中说了拉起服务的事,其实后面拉起服务后还会有一段代码,启动蓝牙,我们看看AdapterService的enable方法。
//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); }public class AdapterService extends Service {...public synchronized boolean enable(boolean quietMode) { enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); debugLog("enable() - Enable called with quiet mode status = " + mQuietmode); mQuietmode = quietMode; Message m = mAdapterStateMachine.obtainMessage(AdapterState.BLE_TURN_ON); mAdapterStateMachine.sendMessage(m); return true; } ... }
Step8
嗯,继续发消息,AdapterState.BLE_TURN_ON
Packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterState.java,里面有很多stateMachine,也有对消息的监听这里,我也有点蒙圈,不按照套路出牌,最终要调用adapterService.enableNative()的native方法,进行jni通信。
case BLE_TURN_ON: if (isTurningOff || isBleTurningOff) { infoLog("Deferring BLE_TURN_ON request..."); deferMessage(msg); } break; case BLE_STARTED: //Remove start timeout removeMessages(BLE_START_TIMEOUT); //Enable if (!adapterService.enableNative()) { errorLog("Error while turning Bluetooth on"); notifyAdapterStateChange(BluetoothAdapter.STATE_OFF); transitionTo(mOffState); } else { sendMessageDelayed(ENABLE_TIMEOUT, ENABLE_TIMEOUT_DELAY); } break;
Step9
从应用层调到了蓝牙协议栈了,我们看看它的c++层是如何操作的。
Packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp,蓝牙驱动对象sBluetoothInterface的enable方法。好吧我再也分析不下去了。
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; }
总的来说博通写的蓝牙模块的内容涉及了好多message信息的处理。下面一篇我会对蓝牙文件传输进行分析。
- Android6.0蓝牙探索旅程
- Android6.0-蓝牙权限问题
- Android6.0蓝牙搜索设备
- android6.0 ble scan android6.0蓝牙扫描
- Android6.0源码分析之蓝牙
- android6.0蓝牙配对加入提示音
- Android6.0 蓝牙搜索不到设备原因
- android6.0获取蓝牙mac地址
- Android6.0蓝牙协议之OPP
- Android6.0蓝牙搜索出错问题
- android6.0以上版本蓝牙4.0开发
- Android6.0的蓝牙权限问题
- Android6.0源码分析之蓝牙
- Android6.0蓝牙权限申请及开启蓝牙
- android6.0手机蓝牙与ble蓝牙模块通信
- 探索新的android6.0权限模型
- android6.23蓝牙操作
- android6.0 蓝牙搜索不到设备 BluetoothAdapter.getDefaultAdapter().startDiscovery()不起作用
- STM32移植lwip之建立tcp服务器
- 预编译——关于#和##
- session还是cookie
- Android多线程下载服务器资源
- BZOJ3630
- Android6.0蓝牙探索旅程
- n个骰子的点数之和
- 这几条UI原则可以让你的设计提高(中)
- 头尾式动画
- 几种计算机视觉中常用的聚类算法(K-means, Agglomerative clustering, Mean shift, Spectral clustering)
- Scala 中的foreach和map方法比较
- Java持久层的三种查询方式
- MyBatis学习笔记
- 操作系统与网络实现 之十八(丙)