原文出處——>[Android應用程序綁定服務(bindService)的過程源代碼分析](http://blog.csdn.net/luoshengyang/article/details/6745181)
Android應用程序組件Service與Activity一樣,既可以在新的進程中啟動,也可以在應用程序進程內部啟動;前面我們已經分析了在新的進程中啟動Service的過程,本文將要介紹在應用程序內部綁定Service的過程,這是一種在應用程序進程內部啟動Service的方法。
在前面一篇文章Android進程間通信(IPC)機制Binder簡要介紹和學習計劃中,我們就曾經提到,在Android系統中,每一個應用程序都是由一些Activity和Service組成的,一般Service運行在獨立的進程中,而Activity有可能運行在同一個進程中,也有可能運行在不同的進程中;在接下來的文章中,Android系統在新進程中啟動自定義服務過程(startService)的原理分析一文介紹了在新的進程中啟動Service的過程,Android應用程序啟動過程源代碼分析一文介紹了在新的進程中啟動Activity的過程,而Android應用程序內部啟動Activity過程(startActivity)的源代碼分析一文則介紹了在應用程序進程內部啟動Activity的過程;本文接過最后一棒,繼續介紹在應用程序進程內部啟動Service的過程,這種過程又可以稱在應用程序進程內部綁定服務(bindService)的過程,這樣,讀者應該就可以對Android應用程序啟動Activity和Service有一個充分的認識了。
這里仍然是按照老規矩,通過具體的例子來分析Android應用程序綁定Service的過程,而所使用的例子便是前面我們在介紹Android系統廣播機制的一篇文章Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃中所開發的應用程序Broadcast了。
我們先簡單回顧一下這個應用程序實例綁定Service的過程。在這個應用程序的MainActivity的onCreate函數中,會調用bindService來綁定一個計數器服務CounterService,這里綁定的意思其實就是在MainActivity內部獲得CounterService的接口,所以,這個過程的第一步就是要把CounterService啟動起來。當CounterService的onCreate函數被調用起來了,就說明CounterService已經啟動起來了,接下來系統還要調用CounterService的onBind函數,跟CounterService要一個Binder對象,這個Binder對象是在CounterService內部自定義的CounterBinder類的一個實例,它繼承于Binder類,里面實現一個getService函數,用來返回外部的CounterService接口。系統得到這個Binder對象之后,就會調用MainActivity在bindService函數里面傳過來的ServiceConnection實例的onServiceConnected函數,并把這個Binder對象以參數的形式傳到onServiceConnected函數里面,于是,MainActivity就可以調用這個Binder對象的getService函數來獲得CounterService的接口了。
這個過程比較復雜,但總體來說,思路還是比較清晰的,整個調用過程為MainActivity.bindService->CounterService.onCreate->CounterService.onBind->MainActivity.ServiceConnection.onServiceConnection->CounterService.CounterBinder.getService。下面,我們就先用一個序列圖來總體描述這個服務綁定的過程,然后就具體分析每一個步驟。

**Step 1. ContextWrapper.bindService**
這個函數定義在frameworks/base/core/java/android/content/ContextWrapper.java文件中:
~~~
public class ContextWrapper extends Context {
Context mBase;
......
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
......
}
~~~
這里的mBase是一個ContextImpl實例變量,于是就調用ContextImpl的bindService函數來進一步處理。
**Step 2. ContextImpl.bindServi**ce
這個函數定義在frameworks/base/core/java/android/app/ContextImpl.java文件中:
~~~
class ContextImpl extends Context {
......
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
IServiceConnection sd;
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
mMainThread.getHandler(), flags);
} else {
......
}
try {
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(),
service, service.resolveTypeIfNeeded(getContentResolver()),
sd, flags);
......
return res != 0;
} catch (RemoteException e) {
return false;
}
}
......
}
~~~
這里的mMainThread是一個ActivityThread實例,通過它的getHandler函數可以獲得一個Handler對象,有了這個Handler對象后,就可以把消息分發到ActivityThread所在的線程消息隊列中去了,后面我們將會看到這個用法,現在我們暫時不關注,只要知道這里從ActivityThread處獲得了一個Handler并且保存在下面要介紹的ServiceDispatcher中去就可以了。
我們先看一下ActivityThread.getHandler的實現,然后再回到這里的bindService函數來。
**Step 3. ActivityThread.getHandler**
這個函數定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:
~~~
public final class ActivityThread {
......
final H mH = new H();
......
private final class H extends Handler {
......
public void handleMessage(Message msg) {
......
}
......
}
......
final Handler getHandler() {
return mH;
}
......
}
~~~
這里返回的Handler是在ActivityThread類內部從Handler類繼承下來的一個H類實例變量。
回到Step 2中的ContextImpl.bindService函數中,獲得了這個Handler對象后,就調用mPackageInfo.getServiceDispatcher函數來獲得一個IServiceConnection接口,這里的mPackageInfo的類型是LoadedApk,我們來看看它的getServiceDispatcher函數的實現,然后再回到ContextImpl.bindService函數來。
**Step 4. LoadedApk.getServiceDispatcher**
這個函數定義在frameworks/base/core/java/android/app/LoadedApk.java文件中:
~~~
final class LoadedApk {
......
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Handler handler, int flags) {
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
HashMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
if (map != null) {
sd = map.get(c);
}
if (sd == null) {
sd = new ServiceDispatcher(c, context, handler, flags);
if (map == null) {
map = new HashMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
mServices.put(context, map);
}
map.put(c, sd);
} else {
sd.validate(context, handler);
}
return sd.getIServiceConnection();
}
}
......
static final class ServiceDispatcher {
private final ServiceDispatcher.InnerConnection mIServiceConnection;
private final ServiceConnection mConnection;
private final Handler mActivityThread;
......
private static class InnerConnection extends IServiceConnection.Stub {
final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
......
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
......
}
......
ServiceDispatcher(ServiceConnection conn,
Context context, Handler activityThread, int flags) {
mIServiceConnection = new InnerConnection(this);
mConnection = conn;
mActivityThread = activityThread;
......
}
......
IServiceConnection getIServiceConnection() {
return mIServiceConnection;
}
......
}
......
}
~~~
在getServiceDispatcher函數中,傳進來的參數context是一個MainActivity實例,先以它為Key值在mServices中查看一下,是不是已經存在相應的ServiceDispatcher實例,如果有了,就不用創建了,直接取出來。在我們這個情景中,需要創建一個新的ServiceDispatcher。在創建新的ServiceDispatcher實例的過程中,將上面傳下來ServiceConnection參數c和Hanlder參數保存在了ServiceDispatcher實例的內部,并且創建了一個InnerConnection對象,這是一個Binder對象,一會是要傳遞給ActivityManagerService的,ActivityManagerServic后續就是要通過這個Binder對象和ServiceConnection通信的。
函數getServiceDispatcher最后就是返回了一個InnerConnection對象給ContextImpl.bindService函數。回到ContextImpl.bindService函數中,它接著就要調用ActivityManagerService的遠程接口來進一步處理了。
**Step 5. ActivityManagerService.bindService**
這個函數定義在frameworks/base/core/java/android/app/ActivityManagerNative.java文件中:
~~~
class ActivityManagerProxy implements IActivityManager
{
......
public int bindService(IApplicationThread caller, IBinder token,
Intent service, String resolvedType, IServiceConnection connection,
int flags) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeStrongBinder(token);
service.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(connection.asBinder());
data.writeInt(flags);
mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
data.recycle();
reply.recycle();
return res;
}
......
}
~~~
這個函數通過Binder驅動程序就進入到ActivityManagerService的bindService函數去了。
**Step 6. ActivityManagerService.bindService**
這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
~~~
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
public int bindService(IApplicationThread caller, IBinder token,
Intent service, String resolvedType,
IServiceConnection connection, int flags) {
......
synchronized(this) {
......
final ProcessRecord callerApp = getRecordForAppLocked(caller);
......
ActivityRecord activity = null;
if (token != null) {
int aindex = mMainStack.indexOfTokenLocked(token);
......
activity = (ActivityRecord)mMainStack.mHistory.get(aindex);
}
......
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType,
Binder.getCallingPid(), Binder.getCallingUid());
......
ServiceRecord s = res.record;
final long origId = Binder.clearCallingIdentity();
......
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent);
IBinder binder = connection.asBinder();
ArrayList<ConnectionRecord> clist = s.connections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
s.connections.put(binder, clist);
}
clist.add(c);
b.connections.add(c);
if (activity != null) {
if (activity.connections == null) {
activity.connections = new HashSet<ConnectionRecord>();
}
activity.connections.add(c);
}
b.client.connections.add(c);
clist = mServiceConnections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
mServiceConnections.put(binder, clist);
}
clist.add(c);
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
......
if (!bringUpServiceLocked(s, service.getFlags(), false)) {
return 0;
}
}
......
}
return 1;
}
......
}
~~~
函數首先根據傳進來的參數token是MainActivity在ActivityManagerService里面的一個令牌,通過這個令牌就可以將這個代表MainActivity的ActivityRecord取回來了。
接著通過retrieveServiceLocked函數,得到一個ServiceRecord,這個ServiceReocrd描述的是一個Service對象,這里就是CounterService了,這是根據傳進來的參數service的內容獲得的。回憶一下在MainActivity.onCreate函數綁定服務的語句:
~~~
Intent bindIntent = new Intent(MainActivity.this, CounterService.class);
bindService(bindIntent, serviceConnection, Context.BIND_AUTO_CREATE);
~~~
這里的參數service,就是上面的bindIntent了,它里面設置了CounterService類的信息(CounterService.class),因此,這里可以通過它來把CounterService的信息取出來,并且保存在ServiceRecord對象s中。
接下來,就是把傳進來的參數connection封裝成一個ConnectionRecord對象。注意,這里的參數connection是一個Binder對象,它的類型是LoadedApk.ServiceDispatcher.InnerConnection,是在Step 4中創建的,后續ActivityManagerService就是要通過它來告訴MainActivity,CounterService已經啟動起來了,因此,這里要把這個ConnectionRecord變量c保存下來,它保在在好幾個地方,都是為了后面要用時方便地取回來的,這里就不仔細去研究了,只要知道ActivityManagerService要使用它時就可以方便地把它取出來就可以了,具體后面我們再分析。
最后,傳進來的參數flags的位Context.BIND_AUTO_CREATE為1(參見上面MainActivity.onCreate函數調用bindService函數時設置的參數),因此,這里會調用bringUpServiceLocked函數進一步處理。
**Step 7. ActivityManagerService.bringUpServiceLocked**
這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
~~~
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
private final boolean bringUpServiceLocked(ServiceRecord r,
int intentFlags, boolean whileRestarting) {
......
final String appName = r.processName;
ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
if (app != null && app.thread != null) {
try {
realStartServiceLocked(r, app);
return true;
} catch (RemoteException e) {
......
}
}
// Not running -- get it started, and enqueue this service record
// to be executed when the app comes up.
if (startProcessLocked(appName, r.appInfo, true, intentFlags,
"service", r.name, false) == null) {
......
}
......
}
......
}
~~~
回憶在Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃中一文中,我們沒有在程序的AndroidManifest.xml配置文件中設置CounterService的process屬性值,因此,它默認就為application標簽的process屬性值,而application標簽的process屬性值也沒有設置,于是,它們就默認為應用程序的包名了,即這里的appName的值為"shy.luo.broadcast"。接下來根據appName和應用程序的uid值獲得一個ProcessRecord記錄,由于之前在啟動MainActivity的時候,已經根據這個appName和uid值創建了一個ProcessReocrd對象(具體可以參考Android應用程序啟動過程源代碼分析一文),因此,這里取回來的app和app.thread均不為null,于是,就執行realStartServiceLocked函數來執行下一步操作了。
如果這里得到的ProcessRecord變量app為null,又是什么情況呢?在這種情況下,就會執行后面的startProcessLocked函數來創建一個新的進程,然后在這個新的進程中啟動這個Service了,具體可以參考前面一篇文章Android系統在新進程中啟動自定義服務過程(startService)的原理分析。
**Step 8. ActivityManagerService.realStartServiceLocked**
這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
~~~
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app) throws RemoteException {
......
r.app = app;
......
app.services.add(r);
......
try {
......
app.thread.scheduleCreateService(r, r.serviceInfo);
......
} finally {
......
}
requestServiceBindingsLocked(r);
......
}
......
}
~~~
這個函數執行了兩個操作,一個是操作是調用app.thread.scheduleCreateService函數來在應用程序進程內部啟動CounterService,這個操作會導致CounterService的onCreate函數被調用;另一個操作是調用requestServiceBindingsLocked函數來向CounterService要一個Binder對象,這個操作會導致CounterService的onBind函數被調用。
這里,我們先沿著app.thread.scheduleCreateService這個路徑分析下去,然后再回過頭來分析requestServiceBindingsLocked的調用過程。這里的app.thread是一個Binder對象的遠程接口,類型為ApplicationThreadProxy。每一個Android應用程序進程里面都有一個ActivtyThread對象和一個ApplicationThread對象,其中是ApplicationThread對象是ActivityThread對象的一個成員變量,是ActivityThread與ActivityManagerService之間用來執行進程間通信的,具體可以參考Android應用程序啟動過程源代碼分析一文。
**Step 9. ApplicationThreadProxy.scheduleCreateService**
這個函數定義在frameworks/base/core/java/android/app/ApplicationThreadNative.java文件中:
~~~
class ApplicationThreadProxy implements IApplicationThread {
......
public final void scheduleCreateService(IBinder token, ServiceInfo info)
throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(token);
info.writeToParcel(data, 0);
mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
}
......
}
~~~
這里通過Binder驅動程序就進入到ApplicationThread的scheduleCreateService函數去了。
**Step 10. ApplicationThread.scheduleCreateService**
這個函數定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:
~~~
public final class ActivityThread {
......
private final class ApplicationThread extends ApplicationThreadNative {
......
public final void scheduleCreateService(IBinder token,
ServiceInfo info) {
CreateServiceData s = new CreateServiceData();
s.token = token;
s.info = info;
queueOrSendMessage(H.CREATE_SERVICE, s);
}
......
}
......
}
~~~
這里它執行的操作就是調用ActivityThread的queueOrSendMessage函數把一個H.CREATE_SERVICE類型的消息放到ActivityThread的消息隊列中去。
**Step 11. ActivityThread.queueOrSendMessage**
這個函數定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:
~~~
public final class ActivityThread {
......
// if the thread hasn't started yet, we don't have the handler, so just
// save the messages until we're ready.
private final void queueOrSendMessage(int what, Object obj) {
queueOrSendMessage(what, obj, 0, 0);
}
private final void queueOrSendMessage(int what, Object obj, int arg1) {
queueOrSendMessage(what, obj, arg1, 0);
}
private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
synchronized (this) {
......
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
mH.sendMessage(msg);
}
}
......
}
~~~
這個消息最終是通過mH.sendMessage發送出去的,這里的mH是一個在ActivityThread內部定義的一個類,繼承于Hanlder類,用于處理消息的。
**Step 12. H.sendMessage**
由于H類繼承于Handler類,因此,這里實際執行的Handler.sendMessage函數,這個函數定義在frameworks/base/core/java/android/os/Handler.java文件,這里我們就不看了,有興趣的讀者可以自己研究一下,調用了這個函數之后,這個消息就真正地進入到ActivityThread的消息隊列去了,最終這個消息由H.handleMessage函數來處理,這個函數定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:
~~~
public final class ActivityThread {
......
private final class H extends Handler {
......
public void handleMessage(Message msg) {
......
switch (msg.what) {
......
case CREATE_SERVICE:
handleCreateService((CreateServiceData)msg.obj);
break;
......
}
}
}
......
}
~~~
這個消息最終由ActivityThread的handleCreateService函數來處理。
**Step 13. ActivityThread.handleCreateService**
這個函數定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:
~~~
public final class ActivityThread {
......
private final void handleCreateService(CreateServiceData data) {
......
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo);
Service service = null;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {
......
}
try {
......
ContextImpl context = new ContextImpl();
context.init(packageInfo, null, this);
Application app = packageInfo.makeApplication(false, mInstrumentation);
context.setOuterContext(service);
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault());
service.onCreate();
mServices.put(data.token, service);
......
} catch (Exception e) {
......
}
}
......
}
~~~
這個函數的工作就是把CounterService類加載到內存中來,然后調用它的onCreate函數。
**Step 14. CounterService.onCreate**
這個函數定義在Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃中一文中所介紹的應用程序Broadcast的工程目錄下的src/shy/luo/broadcast/CounterService.java文件中:
~~~
public class CounterService extends Service implements ICounterService {
......
@Override
public void onCreate() {
super.onCreate();
Log.i(LOG_TAG, "Counter Service Created.");
}
......
}
~~~
這樣,CounterService就啟動起來了。
至此,應用程序綁定服務過程中的第一步MainActivity.bindService->CounterService.onCreate就完成了。
這一步完成之后,我們還要回到Step 8中去,執行下一個操作,即調用ActivityManagerService.requestServiceBindingsLocked函數,這個調用是用來執行CounterService的onBind函數的。
**Step 15. ActivityManagerService.requestServiceBindingsLocked**
這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
~~~
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
private final void requestServiceBindingsLocked(ServiceRecord r) {
Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();
while (bindings.hasNext()) {
IntentBindRecord i = bindings.next();
if (!requestServiceBindingLocked(r, i, false)) {
break;
}
}
}
private final boolean requestServiceBindingLocked(ServiceRecord r,
IntentBindRecord i, boolean rebind) {
......
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
......
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
......
} catch (RemoteException e) {
......
}
}
return true;
}
......
}
~~~
這里的參數r就是我們在前面的Step 6中創建的ServiceRecord了,它代表剛才已經啟動了的CounterService。函數requestServiceBindingsLocked調用了requestServiceBindingLocked函數來處理綁定服務的操作,而函數requestServiceBindingLocked又調用了app.thread.scheduleBindService函數執行操作,前面我們已經介紹過app.thread,它是一個Binder對象的遠程接口,類型是ApplicationThreadProxy。
**Step 16. ApplicationThreadProxy.scheduleBindService**
這個函數定義在frameworks/base/core/java/android/app/ApplicationThreadNative.java文件中:
~~~
class ApplicationThreadProxy implements IApplicationThread {
......
public final void scheduleBindService(IBinder token, Intent intent, boolean rebind)
throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(token);
intent.writeToParcel(data, 0);
data.writeInt(rebind ? 1 : 0);
mRemote.transact(SCHEDULE_BIND_SERVICE_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
}
......
}
~~~
這里通過Binder驅動程序就進入到ApplicationThread的scheduleBindService函數去了。
**Step 17. ApplicationThread.scheduleBindService**
這個函數定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:
~~~
public final class ActivityThread {
......
public final void scheduleBindService(IBinder token, Intent intent,
boolean rebind) {
BindServiceData s = new BindServiceData();
s.token = token;
s.intent = intent;
s.rebind = rebind;
queueOrSendMessage(H.BIND_SERVICE, s);
}
......
}
~~~
這里像上面的Step 11一樣,調用ActivityThread.queueOrSendMessage函數來發送消息。
**Step 18. ActivityThread.queueOrSendMessage**
參考上面的Step 11,不過這里的消息類型是H.BIND_SERVICE。
**Step 19. H.sendMessage**
參考上面的Step 12,不過這里最終在H.handleMessage函數中,要處理的消息類型是H.BIND_SERVICE:
~~~
public final class ActivityThread {
......
private final class H extends Handler {
......
public void handleMessage(Message msg) {
......
switch (msg.what) {
......
case BIND_SERVICE:
handleBindService((BindServiceData)msg.obj);
break;
......
}
}
}
......
}
~~~
這里調用ActivityThread.handleBindService函數來進一步處理。
**Step 20. ActivityThread.handleBindService**
這個函數定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:
~~~
public final class ActivityThread {
......
private final void handleBindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
try {
if (!data.rebind) {
IBinder binder = s.onBind(data.intent);
ActivityManagerNative.getDefault().publishService(
data.token, data.intent, binder);
} else {
......
}
......
} catch (RemoteException ex) {
}
} catch (Exception e) {
......
}
}
}
......
}
~~~
在前面的Step 13執行ActivityThread.handleCreateService函數中,已經將這個CounterService實例保存在mServices中,因此,這里首先通過data.token值將它取回來,保存在本地變量s中,接著執行了兩個操作,一個操作是調用s.onBind,即CounterService.onBind獲得一個Binder對象,另一個操作就是把這個Binder對象傳遞給ActivityManagerService。
我們先看CounterService.onBind操作,然后再回到ActivityThread.handleBindService函數中來。
**Step 21. CounterService.onBind**
這個函數定義在Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃中一文中所介紹的應用程序Broadcast的工程目錄下的src/shy/luo/broadcast/CounterService.java文件中:
~~~
public class CounterService extends Service implements ICounterService {
......
private final IBinder binder = new CounterBinder();
public class CounterBinder extends Binder {
public CounterService getService() {
return CounterService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return binder;
}
......
}
~~~
這里的onBind函數返回一個是CounterBinder類型的Binder對象,它里面實現一個成員函數getService,用于返回CounterService接口。
至此,應用程序綁定服務過程中的第二步CounterService.onBind就完成了。
回到ActivityThread.handleBindService函數中,獲得了這個CounterBinder對象后,就調用ActivityManagerProxy.publishService來通知MainActivity,CounterService已經連接好了。
**Step 22. ActivityManagerProxy.publishService**
這個函數定義在frameworks/base/core/java/android/app/ActivityManagerNative.java文件中:
~~~
class ActivityManagerProxy implements IActivityManager
{
......
public void publishService(IBinder token,
Intent intent, IBinder service) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(token);
intent.writeToParcel(data, 0);
data.writeStrongBinder(service);
mRemote.transact(PUBLISH_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
......
}
~~~
這里通過Binder驅動程序就進入到ActivityManagerService的publishService函數中去了。
**Step 23. ActivityManagerService.publishService**
這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:
~~~
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
public void publishService(IBinder token, Intent intent, IBinder service) {
......
synchronized(this) {
......
ServiceRecord r = (ServiceRecord)token;
......
......
if (r != null) {
Intent.FilterComparison filter
= new Intent.FilterComparison(intent);
IntentBindRecord b = r.bindings.get(filter);
if (b != null && !b.received) {
b.binder = service;
b.requested = true;
b.received = true;
if (r.connections.size() > 0) {
Iterator<ArrayList<ConnectionRecord>> it
= r.connections.values().iterator();
while (it.hasNext()) {
ArrayList<ConnectionRecord> clist = it.next();
for (int i=0; i<clist.size(); i++) {
ConnectionRecord c = clist.get(i);
......
try {
c.conn.connected(r.name, service);
} catch (Exception e) {
......
}
}
}
}
}
......
}
}
}
......
}
~~~
這里傳進來的參數token是一個ServiceRecord對象,它是在上面的Step 6中創建的,代表CounterService這個Service。在Step 6中,我們曾經把一個ConnectionRecord放在ServiceRecord.connections列表中:
~~~
ServiceRecord s = res.record;
......
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent);
IBinder binder = connection.asBinder();
ArrayList<ConnectionRecord> clist = s.connections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
s.connections.put(binder, clist);
}
~~~
因此,這里可以從r.connections中將這個ConnectionRecord取出來:
~~~
Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();
while (it.hasNext()) {
ArrayList<ConnectionRecord> clist = it.next();
for (int i=0; i<clist.size(); i++) {
ConnectionRecord c = clist.get(i);
......
try {
c.conn.connected(r.name, service);
} catch (Exception e) {
......
}
}
}
~~~
每一個ConnectionRecord里面都有一個成員變量conn,它的類型是IServiceConnection,是一個Binder對象的遠程接口,這個Binder對象又是什么呢?這就是我們在Step
4中創建的LoadedApk.ServiceDispatcher.InnerConnection對象了。因此,這里執行c.conn.connected函數后就會進入到LoadedApk.ServiceDispatcher.InnerConnection.connected函數中去了。
**Step 24. InnerConnection.connected**
這個函數定義在frameworks/base/core/java/android/app/LoadedApk.java文件中:
~~~
final class LoadedApk {
......
static final class ServiceDispatcher {
......
private static class InnerConnection extends IServiceConnection.Stub {
......
public void connected(ComponentName name, IBinder service) throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service);
}
}
......
}
......
}
......
}
~~~
這里它將操作轉發給ServiceDispatcher.connected函數。
**Step 25. ServiceDispatcher.connected**
這個函數定義在frameworks/base/core/java/android/app/LoadedApk.java文件中:
~~~
final class LoadedApk {
......
static final class ServiceDispatcher {
......
public void connected(ComponentName name, IBinder service) {
if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0));
} else {
......
}
}
......
}
......
}
~~~
我們在前面Step 4中說到,這里的mActivityThread是一個Handler實例,它是通過ActivityThread.getHandler函數得到的,因此,調用它的post函數后,就會把一個消息放到ActivityThread的消息隊列中去了。
**Step 26. H.post**
由于H類繼承于Handler類,因此,這里實際執行的Handler.post函數,這個函數定義在frameworks/base/core/java/android/os/Handler.java文件,這里我們就不看了,有興趣的讀者可以自己研究一下,調用了這個函數之后,這個消息就真正地進入到ActivityThread的消息隊列去了,與sendMessage把消息放在消息隊列不一樣的地方是,post方式發送的消息不是由這個Handler的handleMessage函數來處理的,而是由post的參數Runnable的run函數來處理的。這里傳給post的參數是一個RunConnection類型的參數,它繼承了Runnable類,因此,最終會調用RunConnection.run函數來處理這個消息。
**Step 27. RunConnection.run**
這個函數定義在frameworks/base/core/java/android/app/LoadedApk.java文件中:
~~~
final class LoadedApk {
......
static final class ServiceDispatcher {
......
private final class RunConnection implements Runnable {
......
public void run() {
if (mCommand == 0) {
doConnected(mName, mService);
} else if (mCommand == 1) {
......
}
}
......
}
......
}
......
}
~~~
這里的mCommand值為0,于是就執行ServiceDispatcher.doConnected函數來進一步操作了。
**Step 28. ServiceDispatcher.doConnected**
這個函數定義在frameworks/base/core/java/android/app/LoadedApk.java文件中:
~~~
final class LoadedApk {
......
static final class ServiceDispatcher {
......
public void doConnected(ComponentName name, IBinder service) {
......
// If there is a new service, it is now connected.
if (service != null) {
mConnection.onServiceConnected(name, service);
}
}
......
}
......
}
~~~
這里主要就是執行成員變量mConnection的onServiceConnected函數,這里的mConnection變量的類型的ServiceConnection,它是在前面的Step 4中設置好的,這個ServiceConnection實例是MainActivity類內部創建的,在調用bindService函數時保存在LoadedApk.ServiceDispatcher類中,用它來換取一個IServiceConnection對象,傳給ActivityManagerService。
**Step 29. ServiceConnection.onServiceConnected**
這個函數定義在Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃中一文中所介紹的應用程序Broadcast的工程目錄下的src/shy/luo/broadcast/MainActivity.java文件中:
~~~
public class MainActivity extends Activity implements OnClickListener {
......
private ServiceConnection serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
counterService = ((CounterService.CounterBinder)service).getService();
Log.i(LOG_TAG, "Counter Service Connected");
}
......
};
......
}
~~~
這里傳進來的參數service是一個Binder對象,就是前面在Step 21中從CounterService那里得到的ConterBinder對象,因此,這里可以把它強制轉換為CounterBinder引用,然后調用它的getService函數。
至此,應用程序綁定服務過程中的第三步MainActivity.ServiceConnection.onServiceConnection就完成了。
**Step 30. CounterBinder.getService**
這個函數定義在Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃中一文中所介紹的應用程序Broadcast的工程目錄下的src/shy/luo/broadcast/CounterService.java文件中:
~~~
public class CounterService extends Service implements ICounterService {
......
public class CounterBinder extends Binder {
public CounterService getService() {
return CounterService.this;
}
}
......
}
~~~
這里就把CounterService接口返回給MainActivity了。
至此,應用程序綁定服務過程中的第四步CounterService.CounterBinder.getService就完成了。
這樣,Android應用程序綁定服務(bindService)的過程的源代碼分析就完成了,總結一下這個過程:
1. Step 1 - Step 14,MainActivity調用bindService函數通知ActivityManagerService,它要啟動CounterService這個服務,ActivityManagerService于是在MainActivity所在的進程內部把CounterService啟動起來,并且調用它的onCreate函數;
2. Step 15 - Step 21,ActivityManagerService把CounterService啟動起來后,繼續調用CounterService的onBind函數,要求CounterService返回一個Binder對象給它;
3. Step 22 - Step 29,ActivityManagerService從CounterService處得到這個Binder對象后,就把它傳給MainActivity,即把這個Binder對象作為參數傳遞給MainActivity內部定義的ServiceConnection對象的onServiceConnected函數;
4. Step 30,MainActivity內部定義的ServiceConnection對象的onServiceConnected函數在得到這個Binder對象后,就通過它的getService成同函數獲得CounterService接口。
- 前言
- Android組件設計思想
- Android源代碼開發和調試環境搭建
- Android源代碼下載和編譯
- Android源代碼情景分析法
- Android源代碼調試分析法
- 手把手教你為手機編譯ROM
- 在Ubuntu上下載、編譯和安裝Android最新源代碼
- 在Ubuntu上下載、編譯和安裝Android最新內核源代碼(Linux Kernel)
- 如何單獨編譯Android源代碼中的模塊
- 在Ubuntu上為Android系統編寫Linux內核驅動程序
- 在Ubuntu上為Android系統內置C可執行程序測試Linux內核驅動程序
- 在Ubuntu上為Android增加硬件抽象層(HAL)模塊訪問Linux內核驅動程序
- 在Ubuntu為Android硬件抽象層(HAL)模塊編寫JNI方法提供Java訪問硬件服務接口
- 在Ubuntu上為Android系統的Application Frameworks層增加硬件訪問服務
- 在Ubuntu上為Android系統內置Java應用程序測試Application Frameworks層的硬件服務
- Android源代碼倉庫及其管理工具Repo分析
- Android編譯系統簡要介紹和學習計劃
- Android編譯系統環境初始化過程分析
- Android源代碼編譯命令m/mm/mmm/make分析
- Android系統鏡像文件的打包過程分析
- 從CM刷機過程和原理分析Android系統結構
- Android系統架構概述
- Android系統整體架構
- android專用驅動
- Android硬件抽象層HAL
- Android應用程序組件
- Android應用程序框架
- Android用戶界面架構
- Android虛擬機之Dalvik虛擬機
- Android硬件抽象層
- Android硬件抽象層(HAL)概要介紹和學習計劃
- Android專用驅動
- Android Logger驅動系統
- Android日志系統驅動程序Logger源代碼分析
- Android應用程序框架層和系統運行庫層日志系統源代碼分析
- Android日志系統Logcat源代碼簡要分析
- Android Binder驅動系統
- Android進程間通信(IPC)機制Binder簡要介紹和學習計劃
- 淺談Service Manager成為Android進程間通信(IPC)機制Binder守護進程之路
- 淺談Android系統進程間通信(IPC)機制Binder中的Server和Client獲得Service Manager接口之路
- Android系統進程間通信(IPC)機制Binder中的Server啟動過程源代碼分析
- Android系統進程間通信(IPC)機制Binder中的Client獲得Server遠程接口過程源代碼分析
- Android系統進程間通信Binder機制在應用程序框架層的Java接口源代碼分析
- Android Ashmem驅動系統
- Android系統匿名共享內存Ashmem(Anonymous Shared Memory)簡要介紹和學習計劃
- Android系統匿名共享內存Ashmem(Anonymous Shared Memory)驅動程序源代碼分析
- Android系統匿名共享內存Ashmem(Anonymous Shared Memory)在進程間共享的原理分析
- Android系統匿名共享內存(Anonymous Shared Memory)C++調用接口分析
- Android應用程序進程管理
- Android應用程序進程啟動過程的源代碼分析
- Android系統進程Zygote啟動過程的源代碼分析
- Android系統默認Home應用程序(Launcher)的啟動過程源代碼分析
- Android應用程序消息機制
- Android應用程序消息處理機制(Looper、Handler)分析
- Android應用程序線程消息循環模型分析
- Android應用程序輸入事件分發和處理機制
- Android應用程序鍵盤(Keyboard)消息處理機制分析
- Android應用程序UI架構
- Android系統的開機畫面顯示過程分析
- Android幀緩沖區(Frame Buffer)硬件抽象層(HAL)模塊Gralloc的實現原理分析
- SurfaceFlinger
- Android系統Surface機制的SurfaceFlinger服務
- SurfaceFlinger服務簡要介紹和學習計劃
- 啟動過程分析
- 對幀緩沖區(Frame Buffer)的管理分析
- 線程模型分析
- 渲染應用程序UI的過程分析
- Android應用程序與SurfaceFlinger服務的關系
- 概述和學習計劃
- 連接過程分析
- 共享UI元數據(SharedClient)的創建過程分析
- 創建Surface的過程分析
- 渲染Surface的過程分析
- Android應用程序窗口(Activity)
- 實現框架簡要介紹和學習計劃
- 運行上下文環境(Context)的創建過程分析
- 窗口對象(Window)的創建過程分析
- 視圖對象(View)的創建過程分析
- 與WindowManagerService服務的連接過程分析
- 繪圖表面(Surface)的創建過程分析
- 測量(Measure)、布局(Layout)和繪制(Draw)過程分析
- WindowManagerService
- WindowManagerService的簡要介紹和學習計劃
- 計算Activity窗口大小的過程分析
- 對窗口的組織方式分析
- 對輸入法窗口(Input Method Window)的管理分析
- 對壁紙窗口(Wallpaper Window)的管理分析
- 計算窗口Z軸位置的過程分析
- 顯示Activity組件的啟動窗口(Starting Window)的過程分析
- 切換Activity窗口(App Transition)的過程分析
- 顯示窗口動畫的原理分析
- Android控件TextView的實現原理分析
- Android視圖SurfaceView的實現原理分析
- Android應用程序UI硬件加速渲染
- 簡要介紹和學習計劃
- 環境初始化過程分析
- 預加載資源地圖集服務(Asset Atlas Service)分析
- Display List構建過程分析
- Display List渲染過程分析
- 動畫執行過程分析
- Android應用程序資源管理框架
- Android資源管理框架(Asset Manager)
- Asset Manager 簡要介紹和學習計劃
- 編譯和打包過程分析
- Asset Manager的創建過程分析
- 查找過程分析
- Dalvik虛擬機和ART虛擬機
- Dalvik虛擬機
- Dalvik虛擬機簡要介紹和學習計劃
- Dalvik虛擬機的啟動過程分析
- Dalvik虛擬機的運行過程分析
- Dalvik虛擬機JNI方法的注冊過程分析
- Dalvik虛擬機進程和線程的創建過程分析
- Dalvik虛擬機垃圾收集機制簡要介紹和學習計劃
- Dalvik虛擬機Java堆創建過程分析
- Dalvik虛擬機為新創建對象分配內存的過程分析
- Dalvik虛擬機垃圾收集(GC)過程分析
- ART虛擬機
- Android ART運行時無縫替換Dalvik虛擬機的過程分析
- Android運行時ART簡要介紹和學習計劃
- Android運行時ART加載OAT文件的過程分析
- Android運行時ART加載類和方法的過程分析
- Android運行時ART執行類方法的過程分析
- ART運行時垃圾收集機制簡要介紹和學習計劃
- ART運行時Java堆創建過程分析
- ART運行時為新創建對象分配內存的過程分析
- ART運行時垃圾收集(GC)過程分析
- ART運行時Compacting GC簡要介紹和學習計劃
- ART運行時Compacting GC堆創建過程分析
- ART運行時Compacting GC為新創建對象分配內存的過程分析
- ART運行時Semi-Space(SS)和Generational Semi-Space(GSS)GC執行過程分析
- ART運行時Mark-Compact( MC)GC執行過程分析
- ART運行時Foreground GC和Background GC切換過程分析
- Android安全機制
- SEAndroid安全機制簡要介紹和學習計劃
- SEAndroid安全機制框架分析
- SEAndroid安全機制中的文件安全上下文關聯分析
- SEAndroid安全機制中的進程安全上下文關聯分析
- SEAndroid安全機制對Android屬性訪問的保護分析
- SEAndroid安全機制對Binder IPC的保護分析
- 從NDK在非Root手機上的調試原理探討Android的安全機制
- APK防反編譯
- Android視頻硬解穩定性問題探討和處理
- Android系統的智能指針(輕量級指針、強指針和弱指針)的實現原理分析
- Android應用程序安裝過程源代碼分析
- Android應用程序啟動過程源代碼分析
- 四大組件源代碼分析
- Activity
- Android應用程序的Activity啟動過程簡要介紹和學習計劃
- Android應用程序內部啟動Activity過程(startActivity)的源代碼分析
- 解開Android應用程序組件Activity的"singleTask"之謎
- Android應用程序在新的進程中啟動新的Activity的方法和過程分析
- Service
- Android應用程序綁定服務(bindService)的過程源代碼分析
- ContentProvider
- Android應用程序組件Content Provider簡要介紹和學習計劃
- Android應用程序組件Content Provider應用實例
- Android應用程序組件Content Provider的啟動過程源代碼分析
- Android應用程序組件Content Provider在應用程序之間共享數據的原理分析
- Android應用程序組件Content Provider的共享數據更新通知機制分析
- BroadcastReceiver
- Android系統中的廣播(Broadcast)機制簡要介紹和學習計劃
- Android應用程序注冊廣播接收器(registerReceiver)的過程分析
- Android應用程序發送廣播(sendBroadcast)的過程分析