蓝牙服务的注册,启动源码分析

来源:互联网 发布:剑三花姐捏脸数据 编辑:程序博客网 时间: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