软件编程
位置:首页>> 软件编程>> Android编程>> Android蓝牙服务启动流程分析探索

Android蓝牙服务启动流程分析探索

作者:c小旭  发布时间:2023-12-20 17:45:35 

标签:Android,蓝牙,服务,启动

Android蓝牙服务启动流程分析探索

首先我们要知道,主要系统服务都是在 SystemServer 启动的,蓝牙也是如此:

1、SystemServer

源码路径:/frameworks/base/services/java/com/android/server/SystemServer.java

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
   if (mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
       Slog.i(TAG, "No Bluetooth Service (factory test)");
   } else if    (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) {
       Slog.i(TAG, "No Bluetooth Service (Bluetooth Hardware Not Present)");
   } else {
       t.traceBegin("StartBluetoothService");
       mSystemServiceManager.startService(BluetoothService.class);
       t.traceEnd();
   }
}

SystemServer 在启动其他服务的方法里,启动了 BluetoothService。

2、BluetoothService

class BluetoothService extends SystemService {
   private BluetoothManagerService mBluetoothManagerService;
   public BluetoothService(Context context) {
       super(context);
       //创建BluetoothManagerService的实例
       mBluetoothManagerService = new BluetoothManagerService(context);
   }
   ......
   @Override
   public void onBootPhase(int phase) {
       if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
           //将BluetoothManagerService实例发布到系统中,这样就可以Context根据BT的service名去获取它的Binder代理操作API了
           publishBinderService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE,
                   mBluetoothManagerService);
       } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
           //此时系统应该启动到一个比较晚的阶段了,可以使用AMS去Bind需要的Service了
           mBluetoothManagerService.handleOnBootPhase();
       }
   }
   ......
}

可以看到,真正获取的服务是BluetoothManagerService 而非 BluetoothService。可以通过 ServiceManager.getService(BLUETOOTH_MANAGER _SERVICE) 获取蓝牙服务。

onBootPhase(int):这个函数应该是 systemserver 在启动的时候会多次调用,参数代表当前启动进行到了什么阶段,用户定义的 service 针对各个阶段需要做怎样的处理或者是不做任何处理。

3、BluetoothManagerService

BluetoothManagerService(Context context) {
       //创建内部处理msg的handler
       mHandler = new BluetoothHandler(IoThread.get().getLooper());
       mContext = context;
       ......
       //false表示此次enable需要触发auto connect device和保存状态,BluetoothAdapter::enableNoAutoConnect()可以改变此状态
       mQuietEnableExternal = false;
       mEnableExternal = false;
       ......
       IntentFilter filter = new IntentFilter();
       //监听App通过接口修改BT 名称的广播
       filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
       //监听bt地址改变的广播
       filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED);
       //监听当前设置需要restore回上一次设置的广播,此时需要重新保存name和addr为上一次的信息
       filter.addAction(Intent.ACTION_SETTING_RESTORED);
       filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
       mContext.registerReceiver(mReceiver, filter);
       //从数据库中加载本机Bt的local name和address
       loadStoredNameAndAddress();
       //查看上一次关机时,BT是否为enable状态;如果是,这次开机也需要enable BT
       if (isBluetoothPersistedStateOn()) {
           if (DBG) {
               Slog.d(TAG, "Startup: Bluetooth persisted state is ON.");
           }
           mEnableExternal = true;//表明开机过程中需要enable BT
       }
   }

在服务启动到一定阶段就会回调到 SystemService 的 onBootPhase(int) 方法,即 2 中的该方法,然后调用 BMS 中的 handleOnBootPhase() 方法。

public void handleOnBootPhase() {  
       ......
       final boolean isSafeMode = mContext.getPackageManager().isSafeMode();
       if (mEnableExternal && isBluetoothPersistedStateOnBluetooth() && && !isSafeMode) {
           sendEnableMsg(mQuietEnableExternal/*默认false,表示此次enable需要自动连接device/保存enable状态*/,
                   BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT,
                   mContext.getPackageName());
       } else if (!isNameAndAddressSet()) {
           Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
           mHandler.sendMessage(getMsg);
       }
       ......
   }

handleOnBootPhase()的内容比较单一,根据一些flag判断是否需要enable BT;而enable蓝牙这里是通过触发send msg实现。

private void sendEnableMsg(boolean quietMode, int reason, String packageName) {
   //发送MESSAGE_ENABLE msg
   mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0));
   addActiveLog(reason, packageName, true);
   mLastEnabledTime = SystemClock.elapsedRealtime();
}
case MESSAGE_ENABLE:
   int quietEnable = msg.arg1;
   mQuietEnable = (quietEnable == 1);//此时为false
   //mBluetooth是后面绑定Bt apk中AdapterService时拿到的Binder代理对象;用以把操作bypass到BT核心框架中
   if (mBluetooth == null) {
       handleEnable(mQuietEnable);
   } else {//如果mBluetooth不是null,说明之前已经启动过了;此时是Restart flow,以MESSAGE_RESTART_BLUETOOTH_SERVICE触发
       mWaitForEnableRetry = 0;
       Message enableDelayedMsg = mHandler.obtainMessage(MESSAGE_HANDLE_ENABLE_DELAYED);
       mHandler.sendMessageDelayed(enableDelayedMsg, ENABLE_DISABLE_DELAY_MS);
   }
   break;

handleEnable() 去 Bind AdapterService 拿到它的Binder句柄。同样的在调用 BluetoothManagerService 中的 enable()、disable()等方法时,也是调到 handleEnable() 方法,从而最终调用 AdapterService 中的 enable()、disable() 方法。

private void handleEnable(boolean quietMode) {
   mQuietEnable = quietMode;
   try {
       mBluetoothLock.writeLock().lock();
       if ((mBluetooth == null) && (!mBinding)) {
           //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());
           if (!doBind(i, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.CURRENT)) {
               mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
           } else {
               mBinding = true;
           }
       }
   } finally {
       mBluetoothLock.writeLock().unlock();
   }
}

然后我们看一下 doBind() 方法中的 mConnection 参数:

private BluetoothServiceConnection mConnection = new BluetoothServiceConnection();
private class BluetoothServiceConnection implements ServiceConnection {
   public void onServiceConnected(ComponentName componentName, IBinder service) {
       String name = componentName.getClassName();
       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 {
           Slog.e(TAG, "Unknown service connected: " + name);
           return;
       }
       msg.obj = service;
       mHandler.sendMessage(msg);
   }
   public void onServiceDisconnected(ComponentName componentName) {
       // Called if we unexpectedly disconnect.
       String name = componentName.getClassName();
       Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
       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 {
           Slog.e(TAG, "Unknown service disconnected: " + name);
           return;
       }
       mHandler.sendMessage(msg);
   }
}

拿到 AdapterService 服务后,发送MESSAGE_BLUETOOTH_SERVICE_CONNECTED消息且 arg1 = SERVICE_IBLUETOOTH。

case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: {
   IBinder service = (IBinder) msg.obj;
   try {
       mBluetoothLock.writeLock().lock();
       mBinding = false;
       mBluetoothBinder = service;
       mBluetooth = IBluetooth.Stub.asInterface(Binder.allowBlocking(service));
       //Register callback object
       try {
           mBluetooth.registerCallback(mBluetoothCallback, mContext.getAttributionSource());
       } catch (RemoteException re) {
           Slog.e(TAG, "Unable to register BluetoothCallback", re);
       }
       //Inform BluetoothAdapter instances that service is up
       sendBluetoothServiceUpCallback();
       //Do enable request
       try {
           if (!mBluetooth.enable(mQuietEnable, mContext.getAttributionSource())) {
               Slog.e(TAG, "IBluetooth.enable() returned false");
           }
       } catch (RemoteException e) {
           Slog.e(TAG, "Unable to call enable()", e);
       }
   } finally {
        mBluetoothLock.writeLock().unlock();
   }
   if (!mEnable) {
       waitForState(Set.of(BluetoothAdapter.STATE_ON));
       handleDisable();
       waitForState(Set.of(BluetoothAdapter.STATE_OFF,
       BluetoothAdapter.STATE_TURNING_ON,
       BluetoothAdapter.STATE_TURNING_OFF,
       BluetoothAdapter.STATE_BLE_TURNING_ON,
       BluetoothAdapter.STATE_BLE_ON,
       BluetoothAdapter.STATE_BLE_TURNING_OFF));
   }
}

主要操作:

1、拿到 bind 服务的 onBinder() 句柄,并转成 IBluetooth 类型

2、通过 IBluetooth 类型的 obj,调用 enable() 接口,将 flow 转到 AdapterService 中,做一些初始化、并向 stack 下 enable 蓝牙的 cmd

至此,enable 蓝牙的 flow 就从 BluetoothManagerService 转到 AdapterService 中了;实际上,通过 BluetoothAdapter 下来的大部分 API 调用最终都是调用到 AdapterService,再通过它下cmd 给 stack。

两个常见到的flag:

mEnable:用来标记系统运行时,蓝牙状态的变化,它有些时候跟 mEnableExternal 值一致。但如果蓝牙的状态是因为某些原因,如 stack 崩溃,导致蓝牙需要重启,重新启动时,需要靠这个 flag 来标记这种 case 的 enable/disable 状态。

mEnableExternal:它主要是记录通过用户手动操作导致的BT使能状态,如通过蓝牙功能按钮来 enable/disable 蓝牙。

来源:https://blog.csdn.net/c19344881x/article/details/128718529

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com