Android14 蓝牙启动流程

Android14 蓝牙启动流程

文章目录

  • Android14 蓝牙启动流程
    • 一、前言
    • 二、流程
      • 1、系统应用控制蓝牙开关
      • 2、蓝牙开关控制 BluetoothAdapter.java
      • 3、IBluetoothManager 中暴露的实现方法如下:
      • 3、蓝牙 IBluetoothManager.java 实现类 BluetoothManagerService
      • 4、蓝牙 AdapterService
      • 5、AdapterProperties 是 AdapterService的小助手
        • AdapterProperties.java
    • 三、其他
      • 1、蓝牙开启流程小结
      • 2、Android 13 蓝牙源码分析
      • 3、Android14 蓝牙 BluetoothService 启动和相关代码介绍

一、前言

基于Android14 分析了一下蓝牙的开启流程,本来以为比较简单的,但是发现具体处理会有点绕。
主要是从应用上层到cpp层蓝牙的开启过程代码进行的一定的分析。
BluetoothAdapter、BluetoothManagerService、AdapterService 是蓝牙开启最相关的上层代码。

这里记录一下,本文的代码都是基于Android14 讲解的,有兴趣的可以收藏看看。

这个对蓝牙开启失败、或者蓝牙其他流程有问题有一定的分析研究价值,有助于确定是哪个流程出现了问题。

二、流程

从应用把蓝牙开关控制的代码到底层流程进行分析。
从应用app层的enable 到cpp调用的地方。
如果不想细看每个类的主要相关代码,直接看后面总结流程就行。

1、系统应用控制蓝牙开关

//BluetoothAdapter 的获取
BluetoothAdapter bluetoothAdapter= BluetoothAdapter.getDefaultAdapter();//开启蓝牙
bluetoothAdapter.enable();

需要系统应用和对应的蓝牙权限才能调用开启蓝牙。

2、蓝牙开关控制 BluetoothAdapter.java

package\modules\Bluetooth\framework\java\android\bluetooth\BluetoothAdapter.java

public final class BluetoothAdapter {private static final String TAG = "BluetoothAdapter";private static final String DESCRIPTOR = "android.bluetooth.BluetoothAdapter";private static final boolean DBG = true;private static final boolean VDBG = false;private final IBluetoothManager mManagerService;private IBluetooth mService;//1、获取 BluetoothAdapter 的暴露的静态方法@RequiresNoPermissionpublic static synchronized BluetoothAdapter getDefaultAdapter() {if (sAdapter == null) {sAdapter = createAdapter(AttributionSource.myAttributionSource());}return sAdapter;}//2、打开蓝牙的暴露方法@RequiresLegacyBluetoothAdminPermission@RequiresBluetoothConnectPermission@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)public boolean enable() {if (isEnabled()) {if (DBG) {Log.d(TAG, "enable(): BT already enabled!");}return true;}try {return mManagerService.enable(mAttributionSource);} catch (RemoteException e) {Log.e(TAG, "", e);}return false;}。。。
}

mAttributionSource 没啥东西,就是应用的基本特征对象,
比如包含了创建类的应用包名和应用的pid和uid,用来区别调用者。

上面开关蓝牙都是通过接口类 IBluetoothManager 实现的。

3、IBluetoothManager 中暴露的实现方法如下:

没啥必要细看,看一遍知道有下面这些方法就行了。

package\modules\Bluetooth\system\binder\android\bluetooth\IBluetoothManager.aidl

interface IBluetoothManager
{IBluetooth registerAdapter(in IBluetoothManagerCallback callback);void unregisterAdapter(in IBluetoothManagerCallback callback);void registerStateChangeCallback(in IBluetoothStateChangeCallback callback);void unregisterStateChangeCallback(in IBluetoothStateChangeCallback callback);boolean enable(in AttributionSource attributionSource);boolean enableNoAutoConnect(in AttributionSource attributionSource);boolean disable(in AttributionSource attributionSource, boolean persist);int getState();IBluetoothGatt getBluetoothGatt();boolean bindBluetoothProfileService(int profile, String serviceName, IBluetoothProfileServiceConnection proxy);void unbindBluetoothProfileService(int profile, IBluetoothProfileServiceConnection proxy);String getAddress(in AttributionSource attributionSource);String getName(in AttributionSource attributionSource);boolean onFactoryReset(in AttributionSource attributionSource);boolean isBleScanAlwaysAvailable();boolean enableBle(in AttributionSource attributionSource, IBinder b);boolean disableBle(in AttributionSource attributionSource, IBinder b);boolean isBleAppPresent();boolean isHearingAidProfileSupported();int setBtHciSnoopLogMode(int mode);@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)")int getBtHciSnoopLogMode();
}

打开和关闭功能是常用的,其他功能不常用;
还有些蓝牙连接之类的功能是其他类控制的。

BluetoothManagerService 是 IBluetoothManager 的实现类。
这类起到比较关键的中间类的作用,打开蓝牙后,
会一直在这里类里面判断蓝牙是否完成打开,并且还有相关日志。

3、蓝牙 IBluetoothManager.java 实现类 BluetoothManagerService

package\modules\Bluetooth\service\src\com\android\server\bluetooth\BluetoothManagerService.java

public class BluetoothManagerService extends IBluetoothManager.Stub {private static final String TAG = "BluetoothManagerService";private static final boolean DBG = true; //1、可以打开debug模式默认的打开的。private IBluetooth mBluetooth;//这个不是底层的,还是上层的接口类BluetoothManagerService(Context context) {//基础设置,广播监听等}//初始化public void handleOnBootPhase() {if (DBG) {Log.d(TAG, "Bluetooth boot completed");}}//2、获取蓝牙是否打开public boolean isEnabled() {return getState() == BluetoothAdapter.STATE_ON;}//3、打开蓝牙public boolean enable(AttributionSource attributionSource) throws RemoteException {final String packageName = attributionSource.getPackageName(); //包名//权限检测if (!checkBluetoothPermissions(attributionSource, "enable", true)) {if (DBG) {Log.d(TAG, "enable(): not enabling - bluetooth disallowed");}return false;}//pid、uidfinal int callingUid = Binder.getCallingUid();final int callingPid = Binder.getCallingPid();if (isSatelliteModeOn()) {Log.d(TAG, "enable(): not enabling - satellite mode is on.");return false;}//4、关键打印,只要打开蓝牙就会有这个打印!//每次打开前,mBluetooth 都是null,mBinding 为false,应该是蓝牙关闭置空了if (DBG) {Log.d(TAG, "enable(" + packageName + "):  mBluetooth=" + mBluetooth + " mBinding="+ mBinding + " mState=" + BluetoothAdapter.nameForState(mState));}synchronized (mReceiver) {mQuietEnableExternal = false;mEnableExternal = true;if (isAirplaneModeOn()) {//5、飞行模式下的处理。。。}// waive WRITE_SECURE_SETTINGS permission check// 6、 重要的是 sendEnableMsg 方法的处理sendEnableMsg(false, BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);}if (DBG) {Log.d(TAG, "enable returning");}return true;}// 7、 蓝牙关闭public boolean disable(AttributionSource attributionSource, boolean persist)throws RemoteException {//关键打印,只要关闭蓝牙就会有这个打印!if (DBG) {Log.d(TAG, "disable(): mBluetooth=" + mBluetooth + ", persist=" + persist+ ", mBinding=" + mBinding);}}...// 8、 sendEnableMsg 方法追踪private void sendEnableMsg(boolean quietMode, int reason, String packageName) {//最后一个参数是否ble,默认都是非blesendEnableMsg(quietMode, reason, packageName, false);}// 9、 sendEnableMsg 方法追踪private void sendEnableMsg(boolean quietMode, int reason, String packageName, boolean isBle) {//10、发送Handler消息mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0,isBle ? 1 : 0));addActiveLog(reason, packageName, true); //日志mLastEnabledTime = SystemClock.elapsedRealtime(); //记录时间}@VisibleForTestingclass BluetoothHandler extends Handler {boolean mGetNameAddressOnly = false;private int mWaitForEnableRetry; //打开蓝牙后会多次判断蓝牙是否完成打开private int mWaitForDisableRetry;BluetoothHandler(Looper looper) {super(looper);}@Overridepublic void handleMessage(Message msg) {case MESSAGE_ENABLE:int quietEnable = msg.arg1;int isBle  = msg.arg2;// 10、 第一次不会进入这里,但是后续会持续在这个判断流程,知道蓝牙打开完成或者打开超时(3秒)if (mHandler.hasMessages(MESSAGE_HANDLE_DISABLE_DELAYED)|| mHandler.hasMessages(MESSAGE_HANDLE_ENABLE_DELAYED)) {// We are handling enable or disable right now, wait for it.mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_ENABLE,quietEnable, isBle), ENABLE_DISABLE_DELAY_MS);break;}// 12、 打开处理日志if (DBG) {Log.d(TAG, "MESSAGE_ENABLE(" + quietEnable + "): mBluetooth ="+ mBluetooth);}mEnable = true;if (isBle == 0) { // 13、非ble会记录蓝牙开关状态persistBluetoothSetting(BLUETOOTH_ON_BLUETOOTH);}// Use service interface to get the exact statemBluetoothLock.readLock().lock();try {//第一次是不会进入这里的if (mBluetooth != null) {boolean isHandled = true;//11、从蓝牙协议状态判断是否ble蓝牙正常打开int state = synchronousGetState();switch (state) {case BluetoothAdapter.STATE_BLE_ON:if (isBle == 1) {Log.i(TAG, "Already at BLE_ON State");} else {Log.w(TAG, "BT Enable in BLE_ON State, going to ON");synchronousOnLeServiceUp(mContext.getAttributionSource());}break;case BluetoothAdapter.STATE_BLE_TURNING_ON:case BluetoothAdapter.STATE_TURNING_ON:case BluetoothAdapter.STATE_ON:Log.i(TAG, "MESSAGE_ENABLE: already enabled");break;default:isHandled = false;break;}if (isHandled) break;}} catch (RemoteException | TimeoutException e) {Log.e(TAG, "", e);} finally {mBluetoothLock.readLock().unlock();}//上面只是ble蓝牙的判断,下面的才是重要的判断逻辑。mQuietEnable = (quietEnable == 1);if (mBluetooth == null) { //12、null的情况,进行绑定 IBluetooth//从日志看点击蓝牙开关,第一次到时打印 mBluetooth null//所以  handleEnable才是关键handleEnable(mQuietEnable);} else {mWaitForEnableRetry = 0;Message enableDelayedMsg =mHandler.obtainMessage(MESSAGE_HANDLE_ENABLE_DELAYED);//13、第二次正常是走到这里,发消息后面一直循环判断,知道蓝牙完成打开mHandler.sendMessageDelayed(enableDelayedMsg, ENABLE_DISABLE_DELAY_MS);}break;case MESSAGE_DISABLE:// 蓝牙关闭//14、执行打开蓝牙后是走到这里,延时300毫秒继续监听启动蓝牙状况case MESSAGE_HANDLE_ENABLE_DELAYED: {// The Bluetooth is turning off, wait for STATE_OFFif (mState != BluetoothAdapter.STATE_OFF) {if (mWaitForEnableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) {mWaitForEnableRetry++;Message enableDelayedMsg =mHandler.obtainMessage(MESSAGE_HANDLE_ENABLE_DELAYED);mHandler.sendMessageDelayed(enableDelayedMsg, ENABLE_DISABLE_DELAY_MS);break;} else {Log.e(TAG, "Wait for STATE_OFF timeout");}}// Either state is changed to STATE_OFF or reaches the maximum retry, we// should move forward to the next step.mWaitForEnableRetry = 0;Message restartMsg =mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE);mHandler.sendMessageDelayed(restartMsg, getServiceRestartMs());Log.d(TAG, "Handle enable is finished");break;}}}//15、打开的关键方法@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)private void handleEnable(boolean quietMode) {mQuietEnable = quietMode;mBluetoothLock.writeLock().lock();try {//16、打开蓝牙第一次都会进入这里!if ((mBluetooth == null) && (!mBinding)) {Log.d(TAG, "binding Bluetooth service");//Start bind timeout and bind//添加一个绑定超时消息Message timeoutMsg = mHandler.obtainMessage(MESSAGE_TIMEOUT_BIND);mHandler.sendMessageDelayed(timeoutMsg, TIMEOUT_BIND_MS);Intent i = new Intent(IBluetooth.class.getName());//17、doBind 方法才是绑定服务,启动蓝牙的关键//这个 doBind 方法贼隐蔽,很难看出是关键方法if (!doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,UserHandle.CURRENT)) {mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);} else {mBinding = true; //正常是进入这里}} else if (mBluetooth != null) {//Enable bluetoothtry {if (!synchronousEnable(mQuietEnable, mContext.getAttributionSource())) {Log.e(TAG, "IBluetooth.enable() returned false");}} catch (RemoteException | TimeoutException e) {Log.e(TAG, "Unable to call enable()", e);}}} finally {mBluetoothLock.writeLock().unlock();}}//18、doBind 方法boolean doBind(Intent intent, ServiceConnection conn, int flags, UserHandle user) {ComponentName comp = resolveSystemService(intent, mContext.getPackageManager(), 0);intent.setComponent(comp);//19、这里其实就是 bindService,绑定一个具体的service//这里类里面是有监听绑定是否成功或者失败监听的if (comp == null || !mContext.bindServiceAsUser(intent, conn, flags, user)) {Log.e(TAG, "Fail to bind to: " + intent);return false;}return true;}//20、执行bindService ,成功的情况,这里会有绑定监听回调private class BluetoothServiceConnection implements ServiceConnection {public void onServiceConnected(ComponentName componentName, IBinder service) {String name = componentName.getClassName();if (DBG) {Log.d(TAG, "BluetoothServiceConnection: " + name);}Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);if (name.equals("com.android.bluetooth.btservice.AdapterService")) {msg.arg1 = SERVICE_IBLUETOOTH;} else if (name.equals("com.android.bluetooth.gatt.GattService")) {msg.arg1 = SERVICE_IBLUETOOTHGATT;} else {Log.e(TAG, "Unknown service connected: " + name);return;}msg.obj = service;mHandler.sendMessage(msg);}}...//后续流程就不一一分析了。}

从上面的代码看,debug模式的默认打开的,
最重要的一点是可以看到 打开和关闭蓝牙的日志,
logcat 日志过滤关键字 "BluetoothManagerService"就可以看到是哪个应用在哪个时间点打开、关闭过蓝牙。

并且蓝牙打开成功、失败,绑定蓝牙失败,绑定蓝牙服务超时都是有日志的。

这里的蓝牙服务并不是底层的IBluetooth,而是上层的一个四大组件的Service服务类。
上面调用

4、蓝牙 AdapterService

package\modules\Bluetooth\android\app\src\com\android\bluetooth\btservice\AdapterService.java


public class AdapterService extends Service {  //1、真正的后台服务//这个类没啥打印,private static final String TAG = "BluetoothAdapterService";private static final boolean DBG = true;private static final boolean VERBOSE = false;private BluetoothAdapter mAdapter;@VisibleForTestingAdapterProperties mAdapterProperties;private AdapterState mAdapterStateMachine;private BondStateMachine mBondStateMachine;private JniCallbacks mJniCallbacks;private RemoteDevices mRemoteDevices;public void onCreate() {super.onCreate();initMetricsLogger();debugLog("onCreate()"); //这个是有打印的!只有开机第一次绑定,后续再被绑定不会继续打印mDeviceConfigListener.start();mRemoteDevices = new RemoteDevices(this, Looper.getMainLooper());mRemoteDevices.init();clearDiscoveringPackages();mBinder = new AdapterServiceBinder(this);mAdapter = BluetoothAdapter.getDefaultAdapter();mAdapterProperties = new AdapterProperties(this);。。。}//2、绑定 IBluetooth 的服务类,调用的方法,是调用到下面方法//然后再调用到具体的处理方法@VisibleForTestingpublic static class AdapterServiceBinder extends IBluetooth.Stub {private AdapterService mService; //通过这个调用到本类实现AdapterServiceBinder(AdapterService svc) {mService = svc;mService.invalidateBluetoothGetStateCache();BluetoothAdapter.getDefaultAdapter().disableBluetoothGetStateCache();}public void cleanup() {mService = null;}public AdapterService getService() {if (mService != null && mService.isAvailable()) {return mService;}return null;}@Overridepublic void getState(SynchronousResultReceiver receiver) {try {receiver.send(getState());} catch (RuntimeException e) {receiver.propagateException(e);}}private int getState() {// don't check caller, may be called from system UIAdapterService service = getService();if (service == null) {return BluetoothAdapter.STATE_OFF;}return service.getState();}//3、封装的 enable方法,蓝牙开启@Overridepublic void enable(boolean quietMode, AttributionSource source,SynchronousResultReceiver receiver) {try {receiver.send(enable(quietMode, source));} catch (RuntimeException e) {receiver.propagateException(e);}}//4、继续跟踪 enable方法,蓝牙开启private boolean enable(boolean quietMode, AttributionSource attributionSource) {AdapterService service = getService();if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "enable")|| !Utils.checkConnectPermissionForDataDelivery(service, attributionSource, "AdapterService enable")) {return false;}//5、继续跟踪 enable方法,service 的类return service.enable(quietMode);}//关闭蓝牙,就不重复说明了@Overridepublic void disable(AttributionSource source, SynchronousResultReceiver receiver) {try {receiver.send(disable(source));} catch (RuntimeException e) {receiver.propagateException(e);}}private boolean disable(AttributionSource attributionSource) {AdapterService service = getService();。。。return service.disable();}。。。//service其他暴露的方法,也是差不多的逻辑流程}//6、service 的开启蓝牙实现方法 enablepublic synchronized boolean enable(boolean quietMode) {//这个也会有打印debugLog("enable() - Enable called with quiet mode status =  " + quietMode);mQuietmode = quietMode;//7、AdapterState 状态机执行开启蓝牙mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_ON);return true;}//8、AdapterState 状态机的逻辑一两句话无法说清楚// AdapterState 的处理还涉及 另外一个Service ProfileService,也是四大组件中的Service类/*** Notify AdapterService that a ProfileService has started or stopped.** @param profile the service being removed.* @param state {@link BluetoothAdapter#STATE_ON} or {@link BluetoothAdapter#STATE_OFF}*///9、从上面注释可以看出 ProfileService 启动会 Notify AdapterService//但是实际上 ProfileService 是AdapterState状态机 刚开始起来的//ProfileService 调用到了AdapterService.startProfileServices()//然后就执行到了 onProfileServiceStateChanged,兜兜转转一圈!!!public void onProfileServiceStateChanged(ProfileService profile, int state) {if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) {throw new IllegalArgumentException(BluetoothAdapter.nameForState(state));}Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED);m.obj = profile;m.arg1 = state;mHandler.sendMessage(m);}//一个Handler消息处理类class AdapterServiceHandler extends Handler {@Overridepublic void handleMessage(Message msg) {verboseLog("handleMessage() - Message: " + msg.what);switch (msg.what) {case MESSAGE_PROFILE_SERVICE_STATE_CHANGED:verboseLog("handleMessage() - MESSAGE_PROFILE_SERVICE_STATE_CHANGED");// 10、 processProfileServiceStateChanged 开启蓝牙 processProfileServiceStateChanged((ProfileService) msg.obj, msg.arg1);break;...}}//11、继续追踪processProfileServiceStateChanged 方法private void processProfileServiceStateChanged(ProfileService profile, int state) {switch (state) {case BluetoothAdapter.STATE_ON:if (GattService.class.getSimpleName().equals(profile.getName())) {//11、正常情况打开蓝牙,追踪是调用到 enableNative 方法!enableNative();} else if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length&& mRegisteredProfiles.size() == mRunningProfiles.size()) {...}break;case BluetoothAdapter.STATE_OFF:...}}...}//12、下面还有一堆native 方法,到这里就终于追到了最接近底层的代码/*package*/native boolean enableNative();/*package*/native boolean disableNative();}

AdapterService 里面的处理逻辑真的会追晕一堆人,简单看一眼看不清楚的逻辑的,跟着日志一边看会好很多。

还有个 AdapterProperties.java 是帮忙处理一些逻辑的。

5、AdapterProperties 是 AdapterService的小助手

这里只简单说一个setName的示例。

比如AdapterService的setName 方法:

        //1、启动类通过Service调用到这里 setName@Overridepublic void setName(String name, AttributionSource source,SynchronousResultReceiver receiver) {try {receiver.send(setName(name, source));} catch (RuntimeException e) {receiver.propagateException(e);}}//2、继续追踪 setName 方法private boolean setName(String name, AttributionSource attributionSource) {AdapterService service = getService();if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setName")|| !Utils.checkConnectPermissionForDataDelivery(service, attributionSource, "AdapterService setName")) {return false;}//3、调用到 AdapterProperties对象的 setName 方法return service.mAdapterProperties.setName(name);}
AdapterProperties.java
class AdapterProperties {private static final boolean DBG = true;private static final boolean VDBG = false;private static final String TAG = "AdapterProperties";private AdapterService mService;//4、AdapterService onCreate 的时候调用的AdapterProperties(AdapterService service) {mService = service;mAdapter = BluetoothAdapter.getDefaultAdapter();mScanModeChanges = EvictingQueue.create(SCAN_MODE_CHANGES_MAX_SIZE);invalidateBluetoothCaches();}//5、setName方法,AdapterService 调用过来的boolean setName(String name) {synchronized (mObject) {//6、但是最后还是调用回 AdapterService 的 setAdapterPropertyNative,添加了一个参数return mService.setAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDNAME,name.getBytes());}}}

AdapterService中的方法并不是所有的处理方法都经过 AdapterProperties,只是一部分方法会让 AdapterProperties 进行一些判断和处理。
AdapterProperties.java 代码不多啊,但是也有一千多行。

package\modules\Bluetooth\android\app\jni\com_android_bluetooth_btservice_AdapterService.cpp

代码太多了,这里只抽取蓝牙开启和设置蓝牙名称的方法实现:

//蓝牙开启
static jboolean enableNative(JNIEnv* env, jobject obj) {ALOGV("%s", __func__);if (!sBluetoothInterface) return JNI_FALSE;int ret = sBluetoothInterface->enable();return (ret == BT_STATUS_SUCCESS || ret == BT_STATUS_DONE) ? JNI_TRUE: JNI_FALSE;
}//设置蓝牙名称
static jboolean setAdapterPropertyNative(JNIEnv* env, jobject obj, jint type,jbyteArray value) {ALOGV("%s", __func__);if (!sBluetoothInterface) return JNI_FALSE;jbyte* val = env->GetByteArrayElements(value, NULL);bt_property_t prop;prop.type = (bt_property_type_t)type;prop.len = env->GetArrayLength(value);prop.val = val;int ret = sBluetoothInterface->set_adapter_property(&prop);env->ReleaseByteArrayElements(value, val, 0);return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}

看logcat日志是没有这两个方法名称的,不清楚具体原因!
流程肯定是走到了这里的!后续的流程就不继续跟踪了。

三、其他

1、蓝牙开启流程小结

1、应用端 --> BluetoothAdapter.enable();
2、BluetoothAdapter.java --> mManagerService.enable(mAttributionSource);
3、BluetoothManagerService.java -->  doBind AdapterService
4、AdapterService.java --> enableNative();
5、com_android_bluetooth_btservice_AdapterService.cpp 执行对应的native方法

其中比较多处理逻辑的就是 BluetoothManagerService.java 和 AdapterService.java,并且这两个类都是有很多过程打印的。
AdapterService 是一个具体的Service, 还会拉起另外一个服务 ProfileService;
AdapterService 还加载了一个状态机AdapterState 处理一下状态事务;
ProfileService 就是状态机在蓝牙开启的时候拉起的服务;
AdapterService 还声明了 AdapterProperties 相当于工具类,协助处理一些方法的具体判断。

虽然蓝牙相关的几个类关联都比较复杂,但是通过上面的梳理,已经明确很多了。

2、Android 13 蓝牙源码分析

其他人写的,也可以参考一下:
只写了蓝牙相关几个类的作用,没啥具体代码和代码路径。
https://blog.csdn.net/u010870679/article/details/140504014

3、Android14 蓝牙 BluetoothService 启动和相关代码介绍

这个介绍比较简单一点,没有到后面 AdapterService 的代码。
但是对于系统启动后上层是否启动蓝牙有一些分析。

https://blog.csdn.net/wenzhi20102321/article/details/142264944

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/146326.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

华为HarmonyOS地图服务 13 - 如何实现地图数据聚合效果?

场景介绍 本章节将向您介绍如何根据地图数据实现聚合效果。 您可以通过比例尺缩放自适应聚合效果,聚合图标可点击。聚合支持功能: 支持按距离聚合ClusterItem。支持绘制聚合Overlay的默认图标。支持绘制聚合Overlay的自定义图标。支持监听聚合Overlay的点击事件。支持添加单…

华为为什么要做三折叠屏手机?

前些天我做了一条视频&#xff0c;关于讲华W的新的三折叠屏手机。我说我有点失望&#xff0c;结果引起了华W的同事的一些关注。于是&#xff0c;华W几位高管都跑过来&#xff0c;跟我解释为什么会出现这样的一个状态。 我才知道&#xff0c;这款手机他们其实是亏着钱在卖的。因…

云盘视频保护神器,支持云盘视频加密与在线播放,配合alist使用,超完美!

平时我们保护视频&#xff0c;一般都是采用压缩工具&#xff0c;进行加密打包&#xff0c;然后在上传到网盘存储。这虽然能起到很好的保护&#xff0c;但是有很多问题&#xff1f;比如&#xff1a;无法直接在线播放&#xff0c;还得从网盘中下载后解压&#xff0c;才能进行观看…

【shell脚本1】Shell脚本学习--入门

目录 简介 Hello World 注释 打印输出 简介 Shell是一种脚本语言&#xff0c;那么&#xff0c;就必须有解释器来执行这些脚本。 Unix/Linux上常见的Shell脚本解释器有bash、sh、csh、ksh等&#xff0c;习惯上把它们称作一种Shell。我们常说有多少种Shell&#xff0c;其实说的…

ProtoBuf序列化框架介绍

文章目录 ProtoBuf介绍使用流程 QUICK START创建.proto文件注释语法编译部分代码展示使用接口运行结果 ProtoBuf介绍 ProtoBuf全称是Protocol Buffer&#xff0c;是一个数据结构的序列化和反序列化框架 他又很多好处&#xff0c;首先是他支持跨平台&#xff0c;支持Java、C、…

进程间通信的七种方法实战演示!值得收藏!

文章目录 前言一、管道&#xff08;Pipes&#xff09;管道示例代码&#xff1a;管道示例流程解读&#xff1a;管道示例运行效果&#xff1a; 二、消息队列&#xff08;Message Queues&#xff09;消息队列示例代码消息队列示例流程解读&#xff1a;消息队列示例执行效果 三、共…

分析redis实现分布式锁的思路

文章目录 1、基于redis实现分布式锁&#xff1a;利用key的唯一性1.1、独占排他1.2、死锁问题1.2.1、redis客户端程序获取了锁之后&#xff0c;服务器立马宕机&#xff0c;就会导致死锁。1.2.2、不可重入&#xff1a;可重入 1.3、原子性&#xff1a;加锁和过期之间&#xff1a;s…

【JavaEE】——线程的安全问题和解决方式

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯&#xff0c;你们的点赞收藏是我前进最大的动力&#xff01;&#xff01;希望本文内容能够帮助到你&#xff01; 目录 一&#xff1a;问题引入 二&#xff1a;问题深入 1&#xff1a;举例说明 2&#xff1a;图解双线程计算…

springboot数字化超市管理系统—计算机毕业设计源码34804

摘 要 在网络信息的时代&#xff0c;众多的软件被开发出来&#xff0c;给用户带来了很大的选择余地&#xff0c;而且人们越来越追求更个性的需求。在这种时代背景下&#xff0c;超市只能以用户为导向&#xff0c;按品种小批量组织生产&#xff0c;以产品的持续创新作为超市最重…

ONES 与华为云深度合作,共同打造企业智能研发管理平台

9月20日&#xff0c;在华为全联接大会&#xff08;HUAWEI CONNECT 2024&#xff09;上&#xff0c;深圳复临科技有限公司&#xff08;以下简称“ONES”&#xff09;与华为云计算技术有限公司&#xff08;以下简称“华为云”&#xff09;正式签署合作协议&#xff0c;双方将在企…

Python | Leetcode Python题解之第421题数组中两个数的最大异或值

题目&#xff1a; 题解&#xff1a; class Trie:def __init__(self):# 左子树指向表示 0 的子节点self.left None# 右子树指向表示 1 的子节点self.right Noneclass Solution:def findMaximumXOR(self, nums: List[int]) -> int:# 字典树的根节点root Trie()# 最高位的二…

【图灵完备 Turing Complete】游戏经验攻略分享 Part.6 处理器架构2 函数

新的架构来了&#xff0c;本游戏的最后一个攻略分享&#xff0c;最后汇编部分无非是对于操作码的熟练&#xff0c;硬件没有问题&#xff0c;那么也就无关痛痒了。 汇编实现&#xff0c;两数相或和两数相与非一起相与即可。 八位异或器&#xff0c;整就完事了。 有手就行。 利…

十七、RC振荡电路

振荡电路 1、振荡电路的组成、作用、起振的相位条件以及振荡电路起振和平衡幅度条件&#xff0c; 2、RC电路阻抗与频率、相位与频率的关系曲线; 3、RC振荡电路的相位条件分析和振荡频率

秩一的等价转化

Lemma 2. For a positive semi-definite Hermitian matrix A ∈ C M M \mathbf{A}\in\mathbb{C}^{M\times M} A∈CMM, the condition Rank ( A ) 1 \left(\mathbf{A}\right)1 (A)1 is equivalent to t h e following conditions the\textit{ following conditions} the fol…

JavaWeb 实验一

实验一 环境配置和Web工程的创建 目的&#xff1a; 掌握Java Web编程环境的配置创建简单的Web工程&#xff0c;并了解Web工程下各目录的作用掌握部署、运行Web工程的流程 实验过程&#xff1a; 一、完成如下要求。 安装并设置JDK 1.8、Tomcat 9.0&#xff08;tomcat和jdk版…

PDF转JPG神器!一键转换,轻松搞定文档分享难题

亲爱的朋友们&#xff0c;你是不是也常常被PDF文件格式所困扰&#xff1f;特别是当你想要将PDF文件转换为JPG格式时&#xff0c;是否觉得有些头大呢&#xff1f;别担心&#xff0c;今天我将向你推荐五款非常棒的PDF转JPG工具&#xff0c;它们绝对能让你的转换过程轻松愉快&…

暴力枚举算法

《啊哈&#xff01;算法》学习笔记 本博客的题目仅用暴力枚举&#xff0c;并不一定是最好的解法&#xff0c;主要是了解枚举算法 例题一&#xff1a;两方框奥数 在两个方框内填入相同的数字使得等式成立&#xff1a; 代码如下&#xff1a; for(i1;i<9;i) {if((i*103)*652…

数据结构---二叉搜索树(二叉排序树)

什么是二叉排序树 二叉搜索树又是二叉排序树&#xff0c;当我们的是一颗空树或者具有以下性质时&#xff1a; 左子树不为空&#xff0c;左子树上的值都小于我们的根节点上的值。右子树不为空时&#xff0c;右子树上的值都大于我们的根节点上的值左右子树都是二叉搜索树&#…

Java异常架构与异常关键字

1. Java异常简介 Java 异常是 Java 提供的一种识别及响应错误的一致性机制。 Java 异常机制可以使程序中异常处理代码和正常业务代码分离&#xff0c;保证程序代码更加优雅&#xff0c;并提高程 序健壮性。在有效使用异常的情况下&#xff0c;异常能清晰的回答 what, where,…

2023北华大学程序设计新生赛部分题解

时光如流水般逝去&#xff0c;我已在校园中奋战大二&#xff01;(≧▽≦) 今天&#xff0c;静静回顾去年的新生赛&#xff0c;心中涌起无尽感慨&#xff0c;仿佛那段青春岁月如烟花般绚烂。✧&#xff61;(≧▽≦)&#xff61;✧ 青春就像一场燃烧的盛宴&#xff0c;激情澎湃&…