淺談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資訊。 它的實現是service_manager.c。而java中的ServiceManager.java僅僅是service_manager.c的封裝。這裡,我們不討論service_manager.c是如何向下與Binder driver通訊的,也不討論註冊、查詢service的具體邏輯。
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);
}