(轉(zhuǎn)載)Android系統(tǒng)服務(wù)(SystemService)簡介

原文鏈接:Android系統(tǒng)服務(wù)(SystemService)簡介 - CSDN博客

什么是SystemService

我們在Android開發(fā)過程中經(jīng)常會用到各種各樣的系統(tǒng)管理服務(wù)巴粪,如進(jìn)行窗口相關(guān)的操作會用到窗口管理服務(wù)WindowManager创淡,進(jìn)行電源相關(guān)的操作會用到電源管理服務(wù)PowerManager辣垒,還有很多其他的系統(tǒng)管理服務(wù)刁品,如通知管理服務(wù)NotifacationManager、振動管理服務(wù)Vibrator合住、電池管理服務(wù)BatteryManager…… 這些Manager提供了很多對系統(tǒng)層的控制接口绰精。對于App開發(fā)者撒璧,只需要了解這些接口的使用方式就可以方便的進(jìn)行系統(tǒng)控制透葛,獲得系統(tǒng)各個服務(wù)的信息,而不需要了解這些接口的具體實現(xiàn)方式卿樱。而對于Framework開發(fā)者僚害,則需要了解這些Manager服務(wù)的常用實現(xiàn)模式,維護(hù)這些Manager的接口,擴(kuò)展這些接口萨蚕,或者實現(xiàn)新的Manager靶草。?

APP與服務(wù)框架通信

一個簡單的SystemService

我們從一個簡單的系統(tǒng)服務(wù)Vibrator服務(wù)來看一下一個系統(tǒng)服務(wù)是怎樣建立的。?

Vibrator服務(wù)提供的控制手機(jī)振動的接口岳遥,應(yīng)用可以調(diào)用Vibrator的接口來讓手機(jī)產(chǎn)生振動奕翔,達(dá)到提醒用戶的目的。?

從Android的官方文檔中可以看到Vibrator只是一個抽象類浩蓉,只有4個抽象接口:

abstract void cancel()?取消振動

abstract boolean hasVibrator()?是否有振動功能

abstract void vibrate(long[] pattern, int repeat)?按節(jié)奏重復(fù)振動

abstract void vibrate(long milliseconds)?持續(xù)振動

應(yīng)用中使用振動服務(wù)的方法也很簡單派继,如讓手機(jī)持續(xù)振動500毫秒:

Vibrator mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);

mVibrator.vibrate(500);

Vibrator使用起來很簡單,我們再來看一下實現(xiàn)起來是不是也簡單捻艳。?

從文檔中可以看到Vibrator只是定義在android.os?包里的一個抽象類驾窟,在源碼里的位置即frameworks/base/core/java/android/os/Vibrator.java,那么應(yīng)用中實際使用的是哪個實例呢认轨?應(yīng)用中使用的Vibrator實例是通過Context的一個方法getSystemService(Context.VIBRATOR_SERVICE)獲得的绅络,而Context的實現(xiàn)一般都在ContextImpl中,那我們就看一下ContextImpl是怎么實現(xiàn)getSystemService的:?

frameworks/base/core/java/android/app/ContextImpl.java

@Override

public Object getSystemService(String name) {

? ? return SystemServiceRegistry.getSystemService(this, name);

}

frameworks/base/core/java/android/app/SystemServiceRegistry.java?

(SystemServiceRegistry是 Android 6.0之后才有的嘁字,Android 6.0 之前的代碼沒有該類恩急,下面的代碼是直接寫在ContextImpl里的)

public static Object getSystemService(ContextImpl ctx, String name) {

? ? ServiceFetcher fetcher = SYSTEM_SERVICE_FETCHERS.get(name);

? ? return fetcher != null ? fetcher.getService(ctx) : null;

}

SYSTEM_SERVICE_MAP是一個HashMap,通過我們服務(wù)的名字name字符串纪蜒,從這個HashMap里取出一個ServiceFetcher假栓,再return這個ServiceFetcher的getService()。ServiceFetcher是什么霍掺?它的getService()又是什么匾荆?既然他是從SYSTEM_SERVICE_MAP這個HashMap里get出來的,那就找一找這個HashMap都put了什么杆烁。?

通過搜索SystemServiceRegistry可以找到如下代碼:

private static void registerService(String serviceName, Class serviceClass,

? ? ? ? ServiceFetcher serviceFetcher) {

? ? SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);

? ? SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);

}

這里往SYSTEM_SERVICE_MAP里put了一對String與ServiceFetcher組成的key/value對牙丽,registerService()又是從哪里調(diào)用的?繼續(xù)搜索可以發(fā)現(xiàn)很多類似下面的代碼:

static {

? ? registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,

? ? ? ? ? ? new CachedServiceFetcher() {

? ? ? ? @Override? ? ? ??

????????public AccessibilityManager createService(ContextImpl ctx) {

? ? ? ? ? ? return AccessibilityManager.getInstance(ctx);

? ? ? ? }});

? ? ...

? ? registerService(Context.VIBRATOR_SERVICE, Vibrator.class,

? ? ? ? ? ? new CachedServiceFetcher() {

? ? ? ? @Override? ? ? ??

????????public Vibrator createService(ContextImpl ctx) {

? ? ? ? ? ? return new SystemVibrator(ctx);

? ? ? ? }});

? ? ...

}

SystemServiceRegistry的static代碼塊里通過registerService注冊了很多的系統(tǒng)服務(wù)兔魂,其中就包括我們正在調(diào)查的VIBRATOR_SERVICE烤芦,通過結(jié)合上面的分析代碼可以可以知道getSystemService(Context.VIBRATOR_SERVICE)得到的是一個SystemVibrator的實例,通過查看SystemVibrator的代碼也可以發(fā)現(xiàn)SystemVibrator確實是繼承自Vibrator:

public class SystemVibrator extends Vibrator {

?????...

}

我們再從SystemVibrator看一下系統(tǒng)的振動控制是怎么實現(xiàn)的析校。以hasVibrator()為例构罗,這個是查詢當(dāng)前系統(tǒng)是否能夠振動,在SystemVibrator中它的實現(xiàn)如下:

public boolean hasVibrator() {

? ? ...

? ? try {

? ? ? ? return mService.hasVibrator();

? ? } catch (RemoteException e) {

? ? }

? ? ...

}

這里直接調(diào)用了一個mService.hasVibrator()智玻。mService是什么遂唧?哪來的?搜索一下可以發(fā)現(xiàn):

private final IVibratorService mService;

public SystemVibrator() {

? ? ...

? ? mService = IVibratorService.Stub.asInterface(

? ? ? ? ? ? ServiceManager.getService("vibrator"));

}

mService?是一個IVibratorService吊奢,我們先不去管IVibratorService.Stub.asInterface是怎么回事盖彭,先看一下IVibratorService是什么。搜索一下代碼發(fā)現(xiàn)這并不是一個java文件,而是一個aidl文件:?

frameworks/base/core/java/android/os/IVibratorService.aidl?

AIDL (Android Interface Definition Language) 是Android中的接口定義文件召边,為系統(tǒng)提供了一種簡單跨進(jìn)程通信方法铺呵。?

IVibratorService?中定義了幾個接口,SystemVibrator中使用的也是這幾個接口隧熙,包括我們剛才使用的hasVibrator()

interface IVibratorService

{

? ? boolean hasVibrator();

? ? void vibrate(...);

? ? void vibratePattern(...);

? ? void cancelVibrate(IBinder token);

}

這里又只是接口定義片挂,接口實現(xiàn)在哪呢?通過在frameworks/base目錄下進(jìn)行g(shù)rep搜索贞盯,或者在AndroidXRef搜索宴卖,可以發(fā)現(xiàn)IVibratorService接口的實現(xiàn)在frameworks/base/services/java/com/android/server/VibratorService.java

public class VibratorService extends IVibratorService.Stub

可以看到?VibratorService實現(xiàn)了IVibratorService定義的所有接口,并通過JNI調(diào)用到native層邻悬,進(jìn)行更底層的實現(xiàn)症昏。更底層的實現(xiàn)不是這篇文檔討論的內(nèi)容,我們需要分析的是VibratorService怎么成為系統(tǒng)服務(wù)的父丰。那么VibratorService是怎么注冊為系統(tǒng)服務(wù)的呢肝谭?在SystemServer里面:

VibratorService vibrator = null;

...

//實例化VibratorService并添加到ServiceManager

traceBeginAndSlog("StartVibratorService");

vibrator = new VibratorService(context);

ServiceManager.addService("vibrator", vibrator);

Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);

...

//通知服務(wù)系統(tǒng)啟動完成

Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "MakeVibratorServiceReady");

try {

? ? vibrator.systemReady();

} catch (Throwable e) {

? ? reportWtf("making Vibrator Service ready", e);

}

Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);

這樣在SystemVibrator里就可以通過下面的代碼連接到VibratorService,與底層的系統(tǒng)服務(wù)進(jìn)行通信了:

IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator"));

mService相當(dāng)于IVibratorService在應(yīng)用層的一個代理蛾扇,所有的實現(xiàn)還是在SystemServer的VibratorService里攘烛。?

看代碼時可以發(fā)現(xiàn)registerService是在static代碼塊里靜態(tài)調(diào)用的,所以getSystemService獲得的各個Manager也都是單例的镀首。

System Service實現(xiàn)流程

從上面的分析坟漱,我們可以總結(jié)出Vibrator服務(wù)的整個實現(xiàn)流程:

1. 定義一個抽象類Vibrator,定義了應(yīng)用中可以訪問的一些抽象方法?

frameworks/base/core/java/android/os/Vibrator.java

2. 定義具體的類SystemVibrator繼承Vibrator更哄,實現(xiàn)抽象方法?

frameworks/base/core/java/android/os/SystemVibrator.java

3. 定義一個AIDL接口文件IVibratorService芋齿,定義系統(tǒng)服務(wù)接口?

frameworks/base/core/java/android/os/IVibratorService.aidl

4. 定義服務(wù)VibratorService,實現(xiàn)IVibratorService定義的接口?

frameworks/base/services/java/com/android/server/VibratorService.java

public class Vibrator Service extends IVibratorService.Stub

5.將VibratorServicey添加到系統(tǒng)服務(wù)?

frameworks/base/services/java/com/android/server/SystemServer.java

VibratorService vibrator = null;

...

//實例化VibratorService并添加到ServiceManager

Slog.i(TAG, "Vibrator Service");

vibrator = new VibratorService(context);

ServiceManager.addService("vibrator", vibrator);

...

//通知服務(wù)系統(tǒng)啟動完成

try {

? ? vibrator.systemReady();

} catch (Throwable e) {

? ? reportWtf("making Vibrator Service ready", e);

}

6. 在SystemVibrator中通過IVibratorService的代理連接到VibratorService成翩,這樣SystemVibrator的接口實現(xiàn)里就可以調(diào)用IVibratorService的接口:?

frameworks/base/core/java/android/os/SystemVibrator.java

private final IVibratorService mService;

...

public SystemVibrator() {

? ? ...

? ? mService = IVibratorService.Stub.asInterface(

? ? ? ? ? ? ServiceManager.getService("vibrator"));

? ? ...

? ? public boolean hasVibrator() {

? ? ? ? ...

? ? ? ? try {

? ? ? ? ? ? return mService.hasVibrator();

? ? ? ? } catch (RemoteException e) {

? ? ? ? }

? ? ? ? ...

? ? }

}

7. 在Context里定義一個代表Vibrator服務(wù)的字符串?

frameworks/base/core/java/android/content/Context.java

public static final String VIBRATOR_SERVICE = "vibrator";

8. 在ContextImpl里添加SystemVibrator的實例化過程?

frameworks/base/core/java/android/app/ContextImpl.java

registerService(VIBRATOR_SERVICE, new ServiceFetcher() {

public Object createService(ContextImpl ctx) {

? ? return new SystemVibrator(ctx);

}});?

9. 在應(yīng)用中使用Vibrator的接口

Vibrator mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);

mVibrator.vibrate(500);

10. 為保證編譯正常觅捆,還需要將AIDL文件添加到編譯配置里?

frameworks/base/Android.mk

LOCAL_SRC_FILES += \

...

core/java/android/os/IVibratorService.aidl \

System Service 新加接口

如果我們需要實現(xiàn)一個新的系統(tǒng)服務(wù),就可以按照上面的步驟在系統(tǒng)中擴(kuò)展出一個新的服務(wù)麻敌,并給應(yīng)用層提供出使用接口栅炒。如果想在Vibrator里添加一個新的接口,需要下面3步:

1. 在IVibratorService添加接口术羔;

2. 在VibratorService添加接口的實現(xiàn)赢赊;

3. 在Vibrator及SystemVibrator里擴(kuò)展新的接口;

這樣應(yīng)用中就可以使用Vibrator的新接口了级历。

應(yīng)用層與 System Service 通信

????上面的實現(xiàn)我們看到的只是從應(yīng)用層通過服務(wù)代理释移,調(diào)用系統(tǒng)服務(wù)的接口,如果我們想反過來鱼喉,將系統(tǒng)服務(wù)的狀態(tài)通知給應(yīng)用層秀鞭,該怎么做呢?

方法一:使用Broadcast

????我們知道使用Broadcast廣播可以實現(xiàn)跨進(jìn)程的消息傳遞扛禽,一些系統(tǒng)服務(wù)也使用了這種方法锋边。如電池管理服務(wù)BatteryManagerService,收到底層上報的電池狀態(tài)變化信息時编曼,就將當(dāng)前的電池狀態(tài)封裝在一個Intent里豆巨,action為android.intent.action.BATTERY_CHANGED。應(yīng)用只要注冊一個對應(yīng)的BroadcastReceiver就可以收到BatterManagerService發(fā)送的電池狀態(tài)信息掐场。

方法二:使用AIDL?

????從上面我們可以知道往扔,通過AIDL定義一套接口,由系統(tǒng)服務(wù)端實現(xiàn)這些接口熊户,應(yīng)用端使用一個相應(yīng)的代理就可以訪問系統(tǒng)服務(wù)的接口萍膛,那反過來讓應(yīng)用端實現(xiàn)AIDL接口,系統(tǒng)服務(wù)端使用代理調(diào)用應(yīng)用端的接口可不可以呢嚷堡?答案是YES蝗罗。那么接下來的問題是怎么讓系統(tǒng)服務(wù)得到這個代理。我們再來看一個LocationManager的例子蝌戒。

LocationManager是系統(tǒng)的定位服務(wù)串塑,應(yīng)用通過LocationManager可以獲得設(shè)備當(dāng)前的地理位置信息。下面是LocationManager的使用代碼片段:

//獲得定位服務(wù)

LocationManager locationManager =

? ? ? ? (LocationManager) getSystemService(Context.LOCATION_SERVICE);

//定義定位監(jiān)聽器

LocationListener locationListener = new LocationListener() {

? ? public void onLocationChanged(Location location) {

? ? ? ? //監(jiān)聽到位置信息

? ? }

? ? ...

};

//注冊監(jiān)聽器

locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,

? ? ? ? 0, 0, locationListener);

從上面的代碼可以看到北苟,我們創(chuàng)建了一個位置監(jiān)聽器LocationListener桩匪,并將這個監(jiān)聽器在LocationManager里進(jìn)行了注冊。當(dāng)系統(tǒng)定位到系統(tǒng)的位置后友鼻,就會回調(diào)監(jiān)聽器的onLocationChanged()傻昙,將位置信息通知給監(jiān)聽器。LocationListener就是一個系統(tǒng)服務(wù)調(diào)用應(yīng)用層接口的例子彩扔,我們就研究一下LocationListener的實現(xiàn)方式屋匕。?

我們先從LocationManager怎么注冊LocationListener開始研究:?

frameworks/base/location/java/android/location/LocationManager.java

private final ILocationManager mService;

...

private void requestLocationUpdates(LocationRequest request,

? ? ? ? LocationListener listener, Looper looper, PendingIntent intent) {

? ? ...

? ? // wrap the listener class

? ? ListenerTransport transport = wrapListener(listener, looper);

? ? try {

? ? ? ? mService.requestLocationUpdates(request, transport,

? ? ? ? ? ? ? ? intent, packageName);

? } catch (RemoteException e) {

? ? ? Log.e(TAG, "RemoteException", e);

? }

}

可以看到LocationListener被重新封裝成了一個ListenerTransport,然后傳遞給了ILocationManager?借杰,從前面的分析可以猜測到這個ILocationManager應(yīng)該就是LocationManagerService的一個代理过吻。那么ListenerTransport又是什么呢?搜索LocationManager.java可以找到:

private class ListenerTransport extends ILocationListener.Stub {

?...

? ? @Override

? ? public void onLocationChanged(Location location) {

? ? ? ? ...

? ? }

}

原來是ILocationListener.Stub的一個繼承實現(xiàn)蔗衡,那么ILocationListener應(yīng)該就是一個AIDL接口定義:?

frameworks/base/location/java/android/location/ILocationListener.aidl

oneway interface ILocationListener

{

? ? void onLocationChanged(in Location location);

? ? ...

}

而在LocationManagerService里只要調(diào)用ILocationListener的方法就可以將消息傳遞給應(yīng)用層的監(jiān)聽:

mListener.onLocationChanged(new Location(location));

實現(xiàn) System Service 的注意事項

1. 注意防止阻塞?

應(yīng)用層訪問系統(tǒng)服務(wù)提供的接口時會有兩種情況:

一種是應(yīng)用調(diào)用端需要等待服務(wù)實現(xiàn)端處理完成纤虽,返回處理結(jié)果,這樣如果服務(wù)端發(fā)生阻塞绞惦,那么應(yīng)用端也會發(fā)生阻塞逼纸,因此在實現(xiàn)服務(wù)端的實現(xiàn)時要注意不要發(fā)生阻塞。

另一種是調(diào)用端不需要等待服務(wù)端返回結(jié)果济蝉,調(diào)用完成后直接返回void杰刽,這樣服務(wù)端發(fā)生阻塞不會影響到應(yīng)用端菠发,這樣的單向的接口在AIDL里定義時需要添加oneway關(guān)鍵字,如:

oneway void statusBarVisibilityChanged(int visibility);

對于需要在服務(wù)端調(diào)用贺嫂,在應(yīng)用端實現(xiàn)的接口滓鸠,考慮到系統(tǒng)的穩(wěn)定性以及安全性,一般都會設(shè)計成上面的第二種第喳,即AIDL里所有的接口都是單向的糜俗,如上面的ILocationListener

oneway interface ILocationListener

2. 注意多線程訪問?

每個系統(tǒng)服務(wù)在系統(tǒng)進(jìn)程中只有一個實例,而且應(yīng)用中系統(tǒng)服務(wù)的代理也是單例的曲饱,而且應(yīng)用端的訪問悠抹,在系統(tǒng)進(jìn)程都是使用獨(dú)立的線程進(jìn)行響應(yīng),所以訪問同一個系統(tǒng)服務(wù)的接口時必然會出現(xiàn)多個線程或者多個進(jìn)程同時訪問的情況扩淀。為保證系統(tǒng)服務(wù)的線程安全楔敌,需要對系統(tǒng)服務(wù)的進(jìn)程進(jìn)行多線程訪問的保護(hù),目前主要有兩種實現(xiàn)線程安全的方法:

一種是通過同步鎖機(jī)制驻谆,鎖住一個對象實例(一般是這個服務(wù)對象本身)梁丘,這樣這個服務(wù)同一時間只能響應(yīng)一個訪問請求,如LocationManagerService里:

public boolean callStatusChangedLocked(...) {

? ? ...

? ? synchronized (this) {

? ? ...

? ? }

}

另一種方法就是使用Handler機(jī)制旺韭,這種服務(wù)一般會創(chuàng)建一個單獨(dú)的線程氛谜,當(dāng)有應(yīng)用端訪問請求到來時會向服務(wù)線程的Handler里發(fā)送一個Message,利用單線程順序執(zhí)行的特性区端,保證所有的訪問都按順序進(jìn)行處理值漫,但這種方法只適合單向的訪問,不適合需要返回的雙向訪問织盼。

ServiceManager原理

從上面流程的分析我們可以看到杨何,所有的系統(tǒng)服務(wù)最終都是由ServiceManager來管理的,那么ServiceManager是怎么管理這些系統(tǒng)服務(wù)的呢沥邻?還是先看上面的VibratorService的實現(xiàn):?

ServiceManager管理服務(wù)

VibratorService通過addService()將自己注冊到ServiceManager里危虱,SystemVibrator通過getService()獲得一個服務(wù)代理,并與服務(wù)進(jìn)行通信交互唐全,那么ServiceManager又是什么埃跷?它是怎么管理服務(wù)的注冊與代理的呢?我們先從addService()與getService()開始邮利,分析一下ServiceManager:?

frameworks/base/core/java/android/os/ServiceManager.java

public final classServiceManager{

?public static void addService(String name, IBinder service) {

? ? ? ? ...

? ? ? ? getIServiceManager().addService(name, service, false);

? ? }

? ? public static IBinder getService(String name) {

? ? ? ? ...

? ? ? ? return getIServiceManager().getService(name);

? ? }

}

addService()和getService()都是直接調(diào)用了getIServiceManager()的方法弥雹,getIServiceManager()返回的又是什么呢?

private static IServiceManager getIServiceManager() {

? ? if (sServiceManager != null) {

? ? ? ? return sServiceManager;

? ? }

? ? // Find the service manager

? ? sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());

? ? return sServiceManager;

}

這里是創(chuàng)建了一個IServiceManager類型的單實例延届,具體的實例又是通過ServiceManagerNative創(chuàng)建的:

ServiceManagerNative.asInterface(BinderInternal.getContextObject());

先來看BinderInternal.getContextObject()?

frameworks/base/core/java/com/android/internal/os/BinderInternal.java

public static final native IBinder getContextObject();

getContextObject()是在native層實現(xiàn)的?

frameworks/base/core/jni/android_util_Binder.cpp

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env,

? ? ? ? jobject clazz)

{

? ? sp b = ProcessState::self()->getContextObject(NULL);

? ? return javaObjectForIBinder(env, b);

}

后面的實現(xiàn)過程邏輯比較復(fù)雜剪勿,這里就不詳細(xì)分析了,只是說明一下大致流程方庭,感興趣的可以自己詳細(xì)研究一下binder的實現(xiàn)機(jī)制厕吉。?

ProcessState從名字可以看出這應(yīng)該是一個保存進(jìn)程狀態(tài)的類酱固,最好應(yīng)該用單實例的對象保存,所以ProcessState::self()得到的也就是ProcessState的一個單實例對象头朱,它的getContextObject()會繼續(xù)調(diào)用getStrongProxyForHandle(int32_t handle)返回一個IBinder?

frameworks/native/libs/binder/ProcessState.cpp

sp<IBinder>?ProcessState::getContextObject(const sp& caller)

{

? ? return getStrongProxyForHandle(0);

}

在getStrongProxyForHandle()中會根據(jù)傳入的參數(shù)handle創(chuàng)建一個BpBinder运悲,這個BpBinder會保存在一個數(shù)組mHandleToObject中,下次再用同樣的handle請求時不會再重新創(chuàng)建髓窜。由于我們傳入的handle=0扇苞,這里創(chuàng)建的BpBinder也就相當(dāng)于第0號BpBinder欺殿。?

之后的javaObjectForIBinder()會將C++的BpBinder對象封裝成Java的BinderProxy對象并返回寄纵。所以BinderInternal.getContextObject()得到的是一個BinderProxy對象,并關(guān)聯(lián)了native層的第0號BpBinder脖苏。

ServiceManagerNative.asInterface(BinderInternal.getContextObject());

相當(dāng)于

ServiceManagerNative.asInterface(new BinderProxy());

ServiceManagerNative.asInterface()又做了些什么呢程拭??

frameworks/base/core/java/android/os/ServiceManagerNative.java

static public IServiceManager asInterface(IBinder obj)

{

? ? ...? ?

? ? return new ServiceManagerProxy(obj);

}

這里會將BinderProxy再封裝成一個ServiceManagerProxy(),所以getIServiceManager()得到的其實是一個ServiceManagerProxy棍潘,但是底層指向的是一個BpBinder(0)恃鞋。?

ServiceManagerProxy、BinderProxy以及BpBinder都是代理模式中的proxy端亦歉,真正的實現(xiàn)應(yīng)該在對應(yīng)的native端恤浪。我們接著看。?

addService()和getService()在代理端的實現(xiàn)應(yīng)該是在ServiceManagerProxy()里:

public IBinder getService(String name) throws RemoteException {

? ? Parcel data = Parcel.obtain();

? ? Parcel reply = Parcel.obtain();

? ? data.writeInterfaceToken(IServiceManager.descriptor);

? ? data.writeString(name);

? ? mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);

? ? IBinder binder = reply.readStrongBinder();

? ? reply.recycle();

? ? data.recycle();

? ? return binder;

}

...

public void addService(String name, IBinder service, boolean allowIsolated)

? ? ? ? throws RemoteException {

? ? Parcel data = Parcel.obtain();

? ? Parcel reply = Parcel.obtain();

? ? data.writeInterfaceToken(IServiceManager.descriptor);

? ? data.writeString(name);

? ? data.writeStrongBinder(service);

? ? data.writeInt(allowIsolated ? 1 : 0);

? ? mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);

? ? reply.recycle();

? ? data.recycle();

}

從上面兩個方法的實現(xiàn)可以看到肴楷,首先是創(chuàng)建了兩個可序列化的Parcel?data水由、reply,傳入的參數(shù)被放到了data里赛蔫,data砂客、reply又一起傳給了mRemote.transact(),之后又從reply里讀取結(jié)果呵恢。addService()的實現(xiàn)里還通過data.writeStrongBinder(service)寫入了一個IBinder的實例鞠值。同時注意到getService()和addService()里面調(diào)用mRemote.transact()傳遞的第一個參數(shù)分別為GET_SERVICE_TRANSACTION?和?ADD_SERVICE_TRANSACTION?,我們可以在IServiceManager里看到這是兩個int值渗钉,分別為1和3?

frameworks/base/core/java/android/os/IServiceManager.java

int GET_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION; //值為1

int CHECK_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+1;

int ADD_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+2;

mRemote就是BinderProxy彤恶,真正的實現(xiàn)是C++里的BpBinder?

frameworks/native/libs/binder/BpBinder.cpp

status_t BpBinder::transact(

? ? ? ? uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{

? ? // Once a binder has died, it will never come back to life.

? ? if (mAlive) {

? ? ? ? status_t status = IPCThreadState::self()->transact(

? ? ? ? ? ? mHandle, code, data, reply, flags);

? ? ? ? if (status == DEAD_OBJECT) mAlive = 0;

? ? ? ? return status;

? ? }

? ? return DEAD_OBJECT;

}

IPCThreadState里的transact會將proxy端的請求通過binder機(jī)制寫入到一塊共享內(nèi)存里,然后會有一個native端從共享內(nèi)存里讀出請求鳄橘,并執(zhí)行相應(yīng)的操作粤剧。那么這個native端在哪里呢?是不是ServiceManagerNative呢挥唠?但是ServiceManagerNative只是一個抽象類抵恋,我們并沒有找到繼承自它的子類。實際上ServiceManagerNative只是架構(gòu)方面的一個抽象定義宝磨,并沒有真正的一個實現(xiàn)弧关,真正實現(xiàn)ServiceManager?的native端功能的是在native層的service_manager.c中盅安。?

servicemanager是底層的一個獨(dú)立進(jìn)程,主要的實現(xiàn)代碼就在service_manager.c中世囊。?

frameworks/native/cmds/servicemanager/binder.h

enum {

? ? /* Must match definitions in IBinder.h and IServiceManager.h */

? ? PING_TRANSACTION? = B_PACK_CHARS('_','P','N','G'),

? ? SVC_MGR_GET_SERVICE = 1,

? ? SVC_MGR_CHECK_SERVICE,

? ? SVC_MGR_ADD_SERVICE,

? ? SVC_MGR_LIST_SERVICES,

};

frameworks/native/cmds/servicemanager/service_manager.c

#include "binder.h"

...

int svcmgr_handler(struct binder_state *bs,

? ? ? ? ? ? ? ? ? struct binder_transaction_data *txn,

? ? ? ? ? ? ? ? ? struct binder_io *msg,

? ? ? ? ? ? ? ? ? struct binder_io *reply)

{

? ? ...

? ? switch(txn->code) {

? ? case SVC_MGR_GET_SERVICE:

? ? case SVC_MGR_CHECK_SERVICE:

? ? ? ? s = bio_get_string16(msg, &len);

? ? ? ? if (s == NULL) {

? ? ? ? ? ? return -1;

? ? ? ? }

? ? ? ? handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);

? ? ? ? if (!handle)

? ? ? ? ? ? break;

? ? ? ? bio_put_ref(reply, handle);

? ? ? ? return 0;

? ? case SVC_MGR_ADD_SERVICE:

? ? ? ? s = bio_get_string16(msg, &len);

? ? ? ? if (s == NULL) {

? ? ? ? ? ? return -1;

? ? ? ? }

? ? ? ? handle = bio_get_ref(msg);

? ? ? ? allow_isolated = bio_get_uint32(msg) ? 1 : 0;

? ? ? ? if (do_add_service(bs, s, len, handle, txn->sender_euid,

? ? ? ? ? ? allow_isolated, txn->sender_pid))

? ? ? ? ? ? return -1;

? ? ? ? break;

? ? ? ? ...

? ? }

}

service_manager.c的svcmgr_handler函數(shù)就是監(jiān)聽代理端請求命令的txn->code就是mRemote.transact()里傳過來的第一個參數(shù)别瞭。SVC_MGR_GET_SERVICE和SVC_MGR_ADD_SERVICE是在頭文件binder.h里定義的,它們的值與IServiceManager.java里定義的一致株憾,也是1和3蝙寨。?

我們先看SVC_MGR_ADD_SERVICE的響應(yīng):

首先通過s = bio_get_string16(msg, &len)獲得了service的名稱,

然后通過handle = bio_get_ref(msg)獲得了一個handle嗤瞎,這個handle就是我們之前通過writeStrongBinder寫入的IBinder墙歪,

最后通過do_add_service()添加注冊service

do_add_service()的實現(xiàn)如下:

int do_add_service(struct binder_state *bs,

? ? ? ? ? ? ? ? ? const uint16_t *s, size_t len,

? ? ? ? ? ? ? ? ? uint32_t handle, uid_t uid, int allow_isolated,

? ? ? ? ? ? ? ? ? pid_t spid)

{

? ? struct svcinfo *si;

? ? si = find_svc(s, len);

? ? if (si) {

? ? ? ? if (si->handle) {

? ? ? ? ? ? ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",

? ? ? ? ? ? ? ? str8(s, len), handle, uid);

? ? ? ? ? ? svcinfo_death(bs, si);

? ? ? ? }

? ? ? ? si->handle = handle;

? ? } else {

? ? ? ? si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));

? ? ? ? si->handle = handle;

? ? ? ? si->len = len;

? ? ? ? memcpy(si->name, s, (len + 1) * sizeof(uint16_t));

? ? ? ? si->name[len] = '\0';

? ? ? ? si->death.func = (void*) svcinfo_death;

? ? ? ? si->death.ptr = si;

? ? ? ? si->allow_isolated = allow_isolated;

? ? ? ? si->next = svclist;

? ? ? ? svclist = si;

? ? }

? ? ...

}

struct svcinfo *find_svc(const uint16_t *s16, size_t len)

{

? ? struct svcinfo *si;

? ? for (si = svclist; si; si = si->next) {

? ? ? ? if ((len == si->len) &&

? ? ? ? ? ? !memcmp(s16, si->name, len * sizeof(uint16_t))) {

? ? ? ? ? ? return si;

? ? ? ? }

? ? }

? ? return NULL;

}

首先聲明了一個struct svcinfo *si

通過find_svc(s, len)查找一下同樣名稱的service之前是不是注冊過,防止重復(fù)注冊贝奇。find_svc()的實現(xiàn)里可以看到是通過遍歷一個svclist鏈表來查重的虹菲,svclist鏈表就是用來保存所有注冊過的service的

如果確認(rèn)沒有重復(fù)注冊service,就重新構(gòu)造一個svcinfo添加到svclist鏈表的頭部掉瞳。

我們再看SVC_MGR_GET_SERVICE的響應(yīng)毕源,主要是通過do_find_service()查找到對應(yīng)的service,并通過bio_put_ref(reply, handle)將查找到的handle返回陕习。do_find_service()的實現(xiàn)主要也是通過find_svc()去svclist鏈表中查找

uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid)

{

? ? struct svcinfo *si = find_svc(s, len);

? ? ...

? ? return si->handle;

}

通過上面的流程梳理我們最終了解到:

1. 每個System Service通過調(diào)用ServiceManager.addService()將自己的名字以及IBinder引用保存到servicemanager進(jìn)程的一個鏈表里

2. 每個使用該System Service的進(jìn)程通過調(diào)用ServiceManager.getService()從servicemanager進(jìn)程獲得該System Service對應(yīng)的IBinder霎褐,就可以與該System Service進(jìn)行通信了

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市该镣,隨后出現(xiàn)的幾起案子冻璃,更是在濱河造成了極大的恐慌,老刑警劉巖拌牲,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件俱饿,死亡現(xiàn)場離奇詭異,居然都是意外死亡塌忽,警方通過查閱死者的電腦和手機(jī)拍埠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來土居,“玉大人枣购,你說我怎么就攤上這事〔烈” “怎么了棉圈?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長眷蜓。 經(jīng)常有香客問我分瘾,道長,這世上最難降的妖魔是什么吁系? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任德召,我火速辦了婚禮白魂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘上岗。我一直安慰自己福荸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布肴掷。 她就那樣靜靜地躺著敬锐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪呆瞻。 梳的紋絲不亂的頭發(fā)上台夺,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天,我揣著相機(jī)與錄音栋烤,去河邊找鬼谒养。 笑死挺狰,一個胖子當(dāng)著我的面吹牛明郭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播丰泊,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼薯定,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了瞳购?” 一聲冷哼從身側(cè)響起话侄,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎学赛,沒想到半個月后年堆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡盏浇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年变丧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绢掰。...
    茶點(diǎn)故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡痒蓬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出滴劲,到底是詐尸還是另有隱情攻晒,我是刑警寧澤班挖,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站萧芙,受9級特大地震影響乙嘀,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜破喻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一虎谢、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧曹质,春花似錦婴噩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至宅静,卻和暖如春章蚣,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背姨夹。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工纤垂, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人磷账。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓峭沦,卻偏偏與公主長得像,于是被迫代替她去往敵國和親逃糟。 傳聞我的和親對象是個殘疾皇子吼鱼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容