1. 程式人生 > >淺談Android java層ServiceManager

淺談Android java層ServiceManager

概述

ServiceManager作為Android程序間通訊binder機制中的重要角色,執行在native層,由c++語言實現,任何Service被使用之前,例如播放音樂的MediaService,例如管理activity的ActivityManagerService,均要向SM註冊,同時客戶端使用某個service時,也需要向ServiceManager查詢該Service是否註冊過了。

ServiceManager作用

1、負責與Binder driver通訊,維護一個死迴圈,不斷地讀取核心binder driver。即不斷讀取看是否有對service的操作請求。2、維護一個svclist列表來儲存service資訊。
3、向客戶端提供Service的代理,也就是BinderProxy。延伸:客戶端向ServiceManager查詢Service並獲取BinderProxy,通過BinderProxy實現與Service端的通訊。4、負責提供Service註冊服務其實,ServiceManager就像是一個路由,首先,Service把自己註冊在ServiceManager中,呼叫方(客戶端)通過ServiceManager查詢服務

    它的實現是service_manager.c。而java中的ServiceManager.java僅僅是service_manager.c的封裝。這裡,我們不討論service_manager.c是如何向下與Binder driver通訊的,也不討論註冊、查詢service的具體邏輯。

而是從java層面,也就是Android FrameWork層面討論是如何使用ServceManager.java服務的。

   ServiceManager.java的原始碼很簡單,如下:

public final class ServiceManager {
    private static final String TAG = "ServiceManager";

    private static IServiceManager sServiceManager;
    private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();

    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

        // Find the service manager
        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
        return sServiceManager;
    }

    /**
     * Returns a reference to a service with the given name.
     * 
     * @param name the name of the service to get
     * @return a reference to the service, or <code>null</code> if the service doesn't exist
     */
    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                return getIServiceManager().getService(name);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }

    /**
     * Place a new @a service called @a name into the service
     * manager.
     * 
     * @param name the name of the new service
     * @param service the service object
     */
    public static void addService(String name, IBinder service) {
        try {
            getIServiceManager().addService(name, service, false);
        } catch (RemoteException e) {
            Log.e(TAG, "error in addService", e);
        }
    }

    /**
     * Place a new @a service called @a name into the service
     * manager.
     * 
     * @param name the name of the new service
     * @param service the service object
     * @param allowIsolated set to true to allow isolated sandboxed processes
     * to access this service
     */
    public static void addService(String name, IBinder service, boolean allowIsolated) {
        try {
            getIServiceManager().addService(name, service, allowIsolated);
        } catch (RemoteException e) {
            Log.e(TAG, "error in addService", e);
        }
    }
    
    /**
     * Retrieve an existing service called @a name from the
     * service manager.  Non-blocking.
     */
    public static IBinder checkService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                return getIServiceManager().checkService(name);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in checkService", e);
            return null;
        }
    }

    /**
     * Return a list of all currently running services.
     * @return an array of all currently running services, or <code>null</code> in
     * case of an exception
     */
    public static String[] listServices() {
        try {
            return getIServiceManager().listServices();
        } catch (RemoteException e) {
            Log.e(TAG, "error in listServices", e);
            return null;
        }
    }

    /**
     * This is only intended to be called when the process is first being brought
     * up and bound by the activity manager. There is only one thread in the process
     * at that time, so no locking is done.
     * 
     * @param cache the cache of service references
     * @hide
     */
    public static void initServiceCache(Map<String, IBinder> cache) {
        if (sCache.size() != 0) {
            throw new IllegalStateException("setServiceCache may only be called once");
        }
        sCache.putAll(cache);
    }
}

有如下功能

1、提供addService()方法,向native層註冊服務

2、提供getService()方法,從native層獲取服務

3、維護了快取Map

    其實getService()就是從native層獲取Binder,獲取後通過Stub.asInterface()方法轉化為BinderProxy,通過BinderProxy就可以通過其呼叫遠端方法了。這部分知識我們是比較熟悉的,在通過AIDL自定義Service時,用到的就是這部分知識。這裡我們先認為native層對我們是不透明的,只要瞭解到通過addService()和getService()就可以向native註冊服務或從native層獲取服務。想了解native是如何實現註冊和獲取服務的同學可以看這兩篇文章:

我們這裡暫時不討論

App端

從本人總結的的上一篇文章Android SystemServer解析中我們可以瞭解到,通過getSystemService()獲取遠端服務代理時,最終是通過ServiceFetcher.createService()方法建立XXManager,XXManager中封裝了用於訪問遠端服務的BinderProxy,那麼,這裡我們探究下XXManager中的BinderProxy是如何而來的。其實我們猜也能猜到一定是通過ServiceManager.getService()獲取的,我們來證實這一過程。

先挑一個最常用的ActivityManager,ActivityManager封裝了對遠端訪問的業務方法,那麼在這些方法中必然是通過呼叫BinderProxy來實現的,我們舉兩個例子:

    @Deprecated
    public List<RunningTaskInfo> getRunningTasks(int maxNum)
            throws SecurityException {
        try {
            return ActivityManagerNative.getDefault().getTasks(maxNum, 0);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
可以看到是通過呼叫ActivityManagerNative.getDefault().getTasks()方法,說明ActivityManagerNative.getDefault()返回的

BinderProxy,我們跟進去看:

ActivityManagerNative.getDefault()

/**
     * Retrieve the system's default/global activity manager.
     */
    static public IActivityManager getDefault() {
        return gDefault.get();
    }

看看getDefault()是什麼:

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

果不其然,是從ServiceManager中獲取的IBinder,並轉換為BinderProxy。

再看一個XXManager,BluetoothManager,其中有一個邏輯方法getConnectedSevices()如下:

public List<BluetoothDevice> getConnectedDevices(int profile) {
        if (DBG) Log.d(TAG,"getConnectedDevices");
        if (profile != BluetoothProfile.GATT && profile != BluetoothProfile.GATT_SERVER) {
            throw new IllegalArgumentException("Profile not supported: " + profile);
        }

        List<BluetoothDevice> connectedDevices = new ArrayList<BluetoothDevice>();

        try {
            IBluetoothManager managerService = mAdapter.getBluetoothManager();
            IBluetoothGatt iGatt = managerService.getBluetoothGatt();
            if (iGatt == null) return connectedDevices;

            connectedDevices = iGatt.getDevicesMatchingConnectionStates(
                new int[] { BluetoothProfile.STATE_CONNECTED });
        } catch (RemoteException e) {
            Log.e(TAG,"",e);
        }

        return connectedDevices;
    }

可以看到是通過mAdapter獲取IBluetoothManager介面,也就是BinderProxy,跟進去BluetoothAdapter:

/*package*/ IBluetoothManager getBluetoothManager() {
            return mManagerService;
    }

返回mManagerService,該變數是構造BluetoothAdapter時傳入的,發現BluetoothAdapter中包含建立BluetoothAdapter的方法getDefaultAdapter,如下:

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;
    }

可以看到,也是通過ServiceManager.getService()獲取IBinder,並通過adInterface(b)方法轉換為BinderProxy。

當然並不是所有的XXManager都需要遠端服務,有些XXManager的業務方法是通過ContentProvider來實現的。

由此,我們驗證了一點:XXManager中包含的BinderProxy是從ServiceManager.getService()獲取的並通過asInterface()得到的。

SystemServer端

下面,我們再來驗證註冊服務是通過ServiceManager.addService()實現的,從上一篇文章Android SystemServer解析,我們得知,各中XXManagerService都是通過SystemServer.java的靜態程式碼塊建立並呼叫onStart()方法啟動,看起來並沒有和ServiceManager.addService()發生聯絡,不急,我們可以看到SystemServer.startOtherService()方法中存在如下程式碼:

telephonyRegistry = new TelephonyRegistry(context);
ServiceManager.addService("telephony.registry", telephonyRegistry);
vibrator = new VibratorService(context);
ServiceManager.addService("vibrator", vibrator);

可以發現就是通過ServiceManager.addService()向native註冊服務

同時,在AMS中也可以發現註冊核心Service的程式碼:

ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
ServiceManager.addService("meminfo", new MemBinder(this));
ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
ServiceManager.addService("dbinfo", new DbBinder(this));

說是註冊Service,其實就是註冊一個IBinder,該IBinder標明瞭自己的身份,我們可以發現addService()的第二個引數的類均是Binder,如VibratorService:

public class VibratorService extends IVibratorService.Stub
        implements InputManager.InputDeviceListener {
....

如TelephonyRegistory:

class TelephonyRegistry extends ITelephonyRegistry.Stub {
    private static final String TAG = "TelephonyRegistry";
.....

另外,XXManagerService的父類SystemService中,也提供了向ServiceManager註冊的方法:

    protected final void publishBinderService(String name, IBinder service,
            boolean allowIsolated) {
        ServiceManager.addService(name, service, allowIsolated);
    }