天天看點

淺談Android java層ServiceManager概述ServiceManager作用Android Framework學習(十一)之從ServiceManager擷取Native層服務App端SystemServer端

概述

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是如何實作注冊和擷取服務的同學可以看這兩篇文章:

Android Framework學習(十)之向ServiceManager注冊Native層服務

Android Framework學習(十一)之從ServiceManager擷取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);
    }
           

繼續閱讀