蓝牙服务的注册,启动源码分析
来源:互联网 发布:剑三花姐捏脸数据 编辑:程序博客网 时间:2024/04/30 09:13
1,蓝牙服务的注册
Android中一切皆服务,首先分析蓝牙服务的注册,获取过程。
ServiceManager:管理所有服务,主要是注册和获取,并且单独运行在一个进程中,通过init启动。
BluetoothService :和其它服务一样, 运行于Framework-res这一进程中。
mSystemServiceManager.startService(BluetoothService.class);
@SuppressWarnings("unchecked") public SystemService startService(String className) { final Class<SystemService> serviceClass; try { serviceClass = (Class<SystemService>)Class.forName(className); } catch (ClassNotFoundException ex) { Slog.i(TAG, "Starting " + className); ••• } return startService(serviceClass);}
@SuppressWarnings("unchecked") public <T extends SystemService> T startService(Class<T> serviceClass) { final String name = serviceClass.getName(); Slog.i(TAG, "Starting " + name); final T service; try { Constructor<T> constructor = serviceClass.getConstructor(Context.class); service = constructor.newInstance(mContext); } catch (InstantiationException ex) { } // Register it. mServices.add(service); // 添加到list中,便于管理 // Start it. try { service.onStart(); // 注册 } catch (RuntimeException ex) { } return service; }
public void onStart() { Log.d(TAG, "onStart: publishing BluetoothManagerService"); publishBinderService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, mBluetoothManagerService); }
protected final void publishBinderService(String name, IBinder service, boolean allowIsolated) { ServiceManager.addService(name, service, allowIsolated); }
代码不是很难,但是要注意以下几点:
1,注册服务是为了其他进程获取服务并且使用服务,注册服务就像开了一个带锁的房间,使用该房间必须拥有对应的钥匙。在上面的例子中:
注册蓝牙服务时,钥匙为String类型的BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE
BluetoothAdapter.java中,该字符定义如下:
public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager";
再看使用该钥匙获取蓝牙服务
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; }
2,真正获取的服务是 BluetoothManagerService 而非 BluetoothService
3,注册和获取服务远远不止这么简单,因为服务和服务管理分属于不同进程,所以还涉及到进程间通信机制,在这里就不详细的说Binder通信机制了。
这样就将BluetoothAdapter和BluetoothManagerService联系在一起了。
2,服务的启动
Init进程启动之后,首先会启动native服务,然后启动System server,最后才是启动launcher,其他apk。在System server进程中,首先会初始化系统服务,启动一些特殊的系统服务,比如AMS,PMS等,然后启动SystemUI.apk,最后在AMS服务中启动一些其他服务,比如Bluetooth服务等。上一节只是论述了蓝牙服务的初始化,现在看看到底是如何启动的。
final void finishBooting() {•••// Let system services know. mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETED);•••}
当SystemUI.apk启动后,AMS会调用finishBooting方法启动其他系统服务。
public void startBootPhase(final int phase) { if (phase <= mCurrentPhase) { throw new IllegalArgumentException("Next phase must be larger than previous"); } mCurrentPhase = phase; Slog.i(TAG, "Starting phase " + mCurrentPhase); final int serviceLen = mServices.size(); for (int i = 0; i < serviceLen; i++) { final SystemService service = mServices.get(i); try { service.onBootPhase(mCurrentPhase); } catch (Exception ex) { throw new RuntimeException("Failed to boot service " + service.getClass().getName() + ": onBootPhase threw an exception during phase " + mCurrentPhase, ex); } } }mServices是一个ArrayList,在上节中,服务注册时会添加到该ArrayList中,逻辑很简单,逐个取出服务,然后分别启动。
public void onBootPhase(int phase) { if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { Log.d(TAG, "onBootPhase: PHASE_SYSTEM_SERVICES_READY"); mBluetoothManagerService.handleOnBootPhase(); }}public void handleOnBootPhase() { if (DBG) Log.d(TAG, "Bluetooth boot completed"); if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { if (DBG) Log.d(TAG, "Auto-enabling Bluetooth."); sendEnableMsg(mQuietEnableExternal); // 发送消息,false } if (!isNameAndAddressSet()) { // Sync the Bluetooth name and address from the Bluetooth Adapter if (DBG) Log.d(TAG, "Retrieving Bluetooth Adapter name and address..."); getNameAndAddress(); // 得到蓝牙的名字和地址 }}到此, BluetoothManagerService真正启动了,开始运行。
在初始化时的BluetoothManagerService构造函数中,
BluetoothManagerService(Context context) { // 构造一个BluetoothHandler 处理各种消息 mHandler = new BluetoothHandler(IoThread.get().getLooper()); mContext = context; mBluetooth = null; mBluetoothGatt = null; mBinding = false; mUnbinding = false; mEnable = false; mState = BluetoothAdapter.STATE_OFF; mQuietEnableExternal = false; mEnableExternal = false; mAddress = null; mName = null; mErrorRecoveryRetryCounter = 0; mContentResolver = context.getContentResolver(); // Observe BLE scan only mode settings change. registerForBleScanModeChange(); mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>(); mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>(); IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); registerForAirplaneMode(filter); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); mContext.registerReceiver(mReceiver, filter); loadStoredNameAndAddress(); if (isBluetoothPersistedStateOn()) { // 上次关机时蓝牙的状态(开/关) mEnableExternal = true; // 服务启动时蓝牙是否打开的标志位 } int sysUiUid = -1; try { sysUiUid = mContext.getPackageManager().getPackageUid("com.android.systemui", UserHandle.USER_OWNER); } catch (PackageManager.NameNotFoundException e) { Log.wtf(TAG, "Unable to resolve SystemUI's UID.", e); } mSystemUiUid = sysUiUid; }3 Bluetooth.apk的启动
Bluetooth.apk都是在打开蓝牙时启动的,一般一个系统会有3个地方打开蓝牙:
1,如何关机之前蓝牙时打开的, mEnableExternal标志位true,
BluetoothManagerService 的handleOnBootPhase会调用方法sendEnableMsg发送消息来打开蓝牙。
2,在设置中,手动打开蓝牙,最后会调用BluetoothAdapter的enable方法打开蓝牙。
3.1 发送消息
private void sendEnableMsg(boolean quietMode) { mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0)); }mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); mEnable = true; handleEnable(msg.arg1 == 1); break;private void handleEnable(boolean quietMode) { mQuietEnable = quietMode; synchronized(mConnection) { if ((mBluetooth == null) && (!mBinding)) { //Start bind timeout and bind 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)) { mHandler.removeMessages(MESSAGE_TIMEOUT_BIND); } else { mBinding = true; } } else if (mBluetooth != null) { if (mConnection.isGetNameAddressOnly()) { // if GetNameAddressOnly is set, we can clear this flag, // so the service won't be unbind // after name and address are saved mConnection.setGetNameAddressOnly(false); //Register callback object try { mBluetooth.registerCallback(mBluetoothCallback); } catch (RemoteException re) { Log.e(TAG, "Unable to register BluetoothCallback",re); } //Inform BluetoothAdapter instances that service is up sendBluetoothServiceUpCallback(); } //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); } } } }首先看IBluetooth,该类对应的服务端是谁呢?
Packages/apps/Bluetooth的bluetooth.cpk 里的AdapterService的内部类
AdapterServiceBinder,其定义如下:
private static class AdapterServiceBinder extends IBluetooth.Stub {这是典型的跨进程通信实现的方法。
调用bindServiceAsUser方法将客户端和服务端进行绑定。
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;}再来看看BluetoothServiceConnection,主要是对2个变量进行初始化
private IBluetooth mBluetooth; private IBluetoothGatt mBluetoothGatt;private BluetoothServiceConnection mConnection = new BluetoothServiceConnection();private class BluetoothServiceConnection implements ServiceConnection { private boolean mGetNameAddressOnly; public void setGetNameAddressOnly(boolean getOnly) { mGetNameAddressOnly = getOnly; } public boolean isGetNameAddressOnly() { return mGetNameAddressOnly; } 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); } public void onServiceDisconnected(ComponentName className) { // Called if we unexpected disconnected. if (DBG) Log.d(TAG, "BluetoothServiceConnection, disconnected: " + className.getClassName()); Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED); if (className.getClassName().equals( "com.android.bluetooth.btservice.AdapterService")) { msg.arg1 = SERVICE_IBLUETOOTH; } else if (className.getClassName().equals( "com.android.bluetooth.gatt.GattService")) { msg.arg1 = SERVICE_IBLUETOOTHGATT; } else { Log.e(TAG, "Unknown service disconnected: " + className.getClassName()); return; } mHandler.sendMessage(msg); } }case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: { if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1); 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); } if (mConnection.isGetNameAddressOnly()) { //Request GET NAME AND ADDRESS Message getMsg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS); mHandler.sendMessage(getMsg); if (!mEnable) return; } mConnection.setGetNameAddressOnly(false); //Register callback object try { mBluetooth.registerCallback(mBluetoothCallback); } catch (RemoteException re) { Log.e(TAG, "Unable to register BluetoothCallback",re); } //Inform BluetoothAdapter instances that service is up sendBluetoothServiceUpCallback(); //Do enable request try { if (mQuietEnable == false) { 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); } } if (!mEnable) { waitForOnOff(true, false); handleDisable(); waitForOnOff(false, false); } break; }这样,就将BluetoothManagerService和bluetooth.apk里的
AdapterService/ GattService 对应起来了
3.2 enable方法
public boolean enable() { if (isEnabled() == true){ if (DBG) Log.d(TAG, "enable(): BT is already enabled..!"); return true; } try { return mManagerService.enable(ActivityThread.currentPackageName()); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; }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); } synchronized(mReceiver) { mQuietEnableExternal = false; mEnableExternal = true; // waive WRITE_SECURE_SETTINGS permission check sendEnableMsg(false); } if (DBG) Log.d(TAG, "enable returning"); return true; }由此可见,最后还是调用BluetoothManagerService通过发送消息的方法启动bluetooth.apk
小结
BluetoothAdapter一般被第三方apk获取,运行于第三方apk中.
BluetoothManagerService 运行于framework的服务进程中。
AdapterService等协议服务运行于bluetooth.apk中。
以上三节的论述打通了三个apk/进程之间的跨进程调用原理。
0 0
- 蓝牙服务的注册,启动源码分析
- Dubbo注册dubbo服务的源码分析
- cinder服务启动源码分析
- filebeat源码分析服务启动
- Android请求注册服务过程源码分析
- Android服务注册完整过程源码分析
- Android请求注册服务过程源码分析
- Android服务注册完整过程源码分析
- 【CSRMesh蓝牙开发】CSRMeshDemo源码分析 -- 启动过程
- Tomcat源码分析(一)--服务启动
- ActivityManagerService服务线程启动源码分析
- Android服务启动之StartService源码分析
- Android服务之PackageManagerService启动源码分析
- Android SurfaceFlinger服务启动过程源码分析
- Android服务之PackageManagerService启动源码分析
- Android服务之PackageManagerService启动源码分析
- ActivityManagerService服务线程启动源码分析
- dataserver 源码分析(二) 启动服务
- 贪婪算法原理介绍与实例解析
- Android GridView获取子View(并操作)
- iOS中 最新微信支付/最全的微信支付教程详解
- 模型预测控制(MPC,Model Predictive Control)
- raspbian开启ssh服务
- 蓝牙服务的注册,启动源码分析
- poj 1376 Robot
- Html 标题滚动效果实现 marquee标签属性
- linux下安装oracle jdk
- Eclipse使用Git图解教程
- 循环遍历标签的值
- [排序算法,选择排序]--简单选择排序
- 编程算法练习
- Windows镜像制作