Android14 蓝牙启动流程

news2024/9/22 1:28:00

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 的暴露的静态方法
    @RequiresNoPermission
    public 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、uid
        final 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,默认都是非ble
        sendEnableMsg(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(); //记录时间
    }

    @VisibleForTesting
    class BluetoothHandler extends Handler {
        boolean mGetNameAddressOnly = false;
        private int mWaitForEnableRetry; //打开蓝牙后会多次判断蓝牙是否完成打开
        private int mWaitForDisableRetry;

        BluetoothHandler(Looper looper) {
            super(looper);
        }

        @Override
        public 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 state
                    mBluetoothLock.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_OFF
                    if (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 bluetooth
                try {
                    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;
    @VisibleForTesting
    AdapterProperties 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 的服务类,调用的方法,是调用到下面方法
    //然后再调用到具体的处理方法
    @VisibleForTesting
    public 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;
        }

        @Override
        public 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 UI
            AdapterService service = getService();
            if (service == null) {
                return BluetoothAdapter.STATE_OFF;
            }

            return service.getState();
        }

        //3、封装的 enable方法,蓝牙开启
        @Override
        public 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);
        }

        //关闭蓝牙,就不重复说明了
        @Override
        public 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 的开启蓝牙实现方法 enable
    public 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 {
        @Override
        public 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
        @Override
        public 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.coloradmin.cn/o/2153826.html

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

相关文章

vue3(整合版)

创建第一个vue项目 1.安装node.js cmd输入node查看是否安装成功 2.vscode开启一个终端&#xff0c;配置淘宝镜像 # 修改为淘宝镜像源 npm config set registry https://registry.npmmirror.com 输入如下命令创建第一个Vue项目 3.下载依赖&#xff0c;启动项目 访问5173端口 …

年度巨献 | OpenCSG开源最大中文合成数据集Chinese Cosmopedia

01 背景 近年来&#xff0c;生成式语言模型&#xff08;GLM&#xff09;的飞速发展正在重塑人工智能领域&#xff0c;尤其是在自然语言处理、内容创作和智能客服等领域展现出巨大潜力。然而&#xff0c;大多数领先的语言模型主要依赖于英文数据集进行训练&#xff0c;中文数据…

python:给1个整数,你怎么判断是否等于2的幂次方?

最近在csdn上刷到一个比较简单的题目&#xff0c;题目要求不使用循环和递归来实现检查1个整数是否等于2的幂次方&#xff0c;题目如下&#xff1a; 题目的答案如下&#xff1a; def isPowerofTwo(n):z bin(n)[2:]print(bin(n))if z[0] ! 1:return Falsefor i in z[1:]:if i !…

NXP官方或正点原子mfgtool下载系统报错initialize the library falied error code:29

这是因为mfgtool版本或者源文件被破坏了&#xff0c;你可以重新下载一个被改过的mfgtool程序&#xff0c;我就是去原子官网重新在linux包里找了新的更迭过的mfgtool

VMware虚拟机因磁盘空间不足黑屏无法登录

在虚拟机里存储了一些文件之后&#xff0c;再打开发现进不去了&#xff0c;只有光标一直在左上角&#xff0c;登录的框都是黑的&#xff0c;具体如下&#xff1a; 明明知道登录框的存在却怎么也触碰不到它T_T &#xff0c;先说解决方法&#xff1a; 产生这个问题的原因是因为磁…

yolov5/8/9模型在COCO分割数据集上的应用【代码+数据集+python环境+GUI系统】

yolov5/8/9模型在COCO分割数据集上的应用【代码数据集python环境GUI系统】 yolov5/8/9模型在COCO分割数据集上的应用【代码数据集python环境GUI系统】 1.COCO数据集介绍 COCO数据集&#xff0c;全称为Microsoft Common Objects in Context&#xff0c;是微软于2014年出资标注的…

多态与绑定例题

答案&#xff1a; B D C 知识点&#xff1a; 多态是相同方法不同的表现&#xff0c;分为重写和重载 重写体现在父类与子类不同表现&#xff0c;主要表现为子类重现父类的方法 重载体现在同一个类中的不同表现 绑定分为动态绑定和静态绑定 动态绑定是在运行时 静态绑定是…

动态规划算法:09.路径问题_最小路径和_C++

目录 题目链接&#xff1a;LCR 099. 最小路径和 - 力扣&#xff08;LeetCode&#xff09; 一、题目解析 题目&#xff1a; 解析&#xff1a; 二、算法原理 1、状态表示 2、状态转移方程 3、初始化 dp表初始化: 特殊位置初始化&#xff1a; 4、填表顺序 5、返回值 …

【HTTP】认识 URL 和 URL encode

文章目录 认识 URLURL 基本格式**带层次的文件路径****查询字符串****片段标识符** URL encode 认识 URL 计算机中非常重要的概念&#xff0c;并不仅仅是在 HTTP 中使用。用来描述一个网络资源所处的位置&#xff0c;全称“唯一资源定位符” URI 是“唯一资源标识符“严格的说…

超越极限!Qwen2.5 助力多领域智能应用

前沿科技速递&#x1f680; 近日&#xff0c;Qwen2.5 系列重磅发布&#xff0c;成为开源语言模型领域的又一里程碑。作为一款全新的通用语言模型&#xff0c;Qwen2.5 在支持自然语言处理的基础上&#xff0c;还在编程、数学等领域进行了专项优化。Qwen2.5 模型支持长文本生成&a…

黑群晖安装教程

黑群晖&#xff08;一种非官方的群晖NAS系统安装方式&#xff09;的安装教程相对复杂&#xff0c;但按照以下步骤操作&#xff0c;可以顺利完成安装。请注意&#xff0c;由于黑群晖涉及非官方操作&#xff0c;安装过程中可能遇到各种不确定因素&#xff0c;建议具备一定的计算机…

十四、运算放大电路

运算放大电路 1、理想运算放大器的概念。运放的输入端虚拟短路、虚拟断路之间的区别; 2、反相输入方式的运放电路的主要用途&#xff0c;以及输入电压与输出电压信号的相位 3、同相输入方式下的增益表达式(输入阻抗、输出阻抗)

英语<数词>

1.基数 one two three 整数 1 2 3 小数 1.1 2.2 3.2 分数 分子用基数&#xff0c;分母用序数 例子 1/3 one third 分子>1 2/3 two thirds 百分数 2.序数 first second

【软考】传输层协议TCP与UDP

目录 1. TCP1.1 说明1.2 三次握手 2. UDP3. 例题3.1 例题1 1. TCP 1.1 说明 1.TCP(Transmission Control Protocol&#xff0c;传输控制协议)是整个 TCP/IP 协议族中最重要的协议之一。2.它在IP提供的不可靠数据服务的基础上为应用程序提供了一个可靠的、面向连接的、全双工的…

[UTCTF2020]sstv

用goldwave和010editor打开均未发现线索&#xff0c; 网上搜索sstv&#xff0c;豆包回答如下&#xff1a; 慢扫描电视&#xff08;Slow Scan Television&#xff0c;简称 SSTV&#xff09;是一种通过无线电传输和接收静态图像的技术。 一、工作原理 SSTV 通过将图像逐行扫描并…

十九、石英晶体振荡电路

石英晶体振荡电路 1、石英晶体的特点、等效电路、特性曲线; 2、石英晶体振动器的特点&#xff0c; 3、石英晶体振动器的振荡频率

Vision Transformer (ViT)、Swin Transformer 和 Focal Transformer

1. Vision Transformer (ViT) Vision Transformer详解-CSDN博客https://blog.csdn.net/qq_37541097/article/details/118242600?ops_request_misc%257B%2522request%255Fid%2522%253A%2522F8BBAFBF-A4A1-4D38-9C0F-9A43B56AF6DB%2522%252C%2522scm%2522%253A%252220140713.13…

互联网全景消息(5)之RocketMq快速入门(下)

一、RocketMQ的存储设计 1.1 Domain Model 1.1.1 Message Message是RocketMQ消息引擎中的主体。messageId是全局唯一的。MessageKey是业务系统(生产者)生成的,所以如果要结合业务,可以使用MessageKey作为业务系统的唯一索引。 1.1.2 Topic subTopics==Message Queue,其实…

机器学习——Stacking

Stacking&#xff1a; 方法&#xff1a;训练多个模型(可以是强模型)&#xff0c;然后将这些模型的预测结果作为新的特征&#xff0c;输入到下一层新的模型&#xff08;可以是多个&#xff09;中进行训练&#xff0c;从而得到最终的预测结果。 代表&#xff1a;Stacking本身并没…

跨游戏引擎的H5渲染解决方案(腾讯)

本文是腾讯的一篇H5 跨引擎解决方案的精炼。 介绍 本文通过实现基于精简版的HTML5&#xff08;HyperText Mark Language 5&#xff09;来屏蔽不同引擎&#xff0c;平台底层的差异。 好处&#xff1a; 采用H5的开发方式&#xff0c;可以将开发和运营分离&#xff0c;运营部门自…