前沿
上一篇文章給大家分析了一下Binder的交互流程,這篇文章分析一下上篇遺留的bindService執(zhí)行流程傅蹂,當我們調(diào)用了bindService系統(tǒng)為我們做了些什么纷闺。
首先算凿,當我們想要去綁定一個遠程service時,我們需要寫以下代碼:
Intent intent = new Intent(this,MyService.class);
bindService(intent,connection,BIND_AUTO_CREATE);
這時候我們就要進入bindService
中
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
public abstract boolean bindService(Intent service, ServiceConnection conn,
int flags);
這時候我們發(fā)現(xiàn)這個調(diào)用了mBase.bindService
.進入這個方法才發(fā)現(xiàn)是個抽象方法犁功。我去氓轰,那怎么辦,我們需要找到他真正的子類實現(xiàn)浸卦,這里就不給大家賣關子了戒努,我們真正的子類實現(xiàn)是ContextImpl
這個類,那我們?nèi)タ匆幌逻@個類中的bindService
吧镐躲。
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, Process.myUserHandle());
}
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
UserHandle user) {
IServiceConnection sd;
if (mPackageInfo != null) {
//這里先記錄以下,一會還會回來
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
mMainThread.getHandler(), flags);
}
validateServiceIntent(service);
try {
IBinder token = getActivityToken();
//省略一些代碼侍筛。
service.prepareToLeaveProcess();
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(),
service, service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, user.getIdentifier());
if (res < 0) {
throw new SecurityException(
"Not allowed to bind to service " + service);
}
return res != 0;
} catch (RemoteException e) {
return false;
}
}
這時候就會調(diào)用ActivityManagerNative.getDefault().bindService
這個ActivityManagerNative.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
去獲取了一個binder萤皂,并把這個binder返回了,是一個IActivityManager
如果大家看過很多底層代碼就會很熟悉這樣的接口類匣椰,我們通過這個接口可以猜出其子類是ActivityManagerService
裆熙。我們?nèi)ミ@個類中的bindService
一探究竟。
public int bindService(IApplicationThread caller, IBinder token,
Intent service, String resolvedType,
IServiceConnection connection, int flags, int userId) {
synchronized(this) {
return mServices.bindServiceLocked(caller, token, service, resolvedType,
connection, flags, userId);
}
}
調(diào)用了bindServiceLocked
方法
// 省略掉一些有關Activity的啟動流程禽笑,我們再后面再說
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
if (app.thread == null) {
throw new RemoteException();
}
requestServiceBindingsLocked(r, execInFg);
}
最后會調(diào)用requestServiceBindingsLocked
方法
private final boolean requestServiceBindingLocked(ServiceRecord r,
IntentBindRecord i, boolean execInFg, boolean rebind) {
if (r.app == null || r.app.thread == null) {
// If service is not currently running, can't yet bind.
return false;
}
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
bumpServiceExecutingLocked(r, execInFg, "bind");
r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.repProcState);
if (!rebind) {
i.requested = true;
}
i.hasBound = true;
i.doRebind = false;
} catch (RemoteException e) {
if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
return false;
}
}
return true;
}
這里我們看r.app.thread.scheduleBindService
這個方法入录,但是你又會問,點不進去啊佳镜,這個scheduleBindService
在哪里呢僚稿。我們進到ProcessRecord
里面看一下
final class ProcessRecord {
private final BatteryStatsImpl mBatteryStats; // where to collect runtime statistics
final ApplicationInfo info; // all about the first app in the process
final boolean isolated; // true if this is a special isolated process
final int uid; // uid of process; may be different from 'info' if isolated
final int userId; // user of process.
final String processName; // name of the process
// List of packages running in the process
final ArrayMap<String, ProcessStats.ProcessState> pkgList
= new ArrayMap<String, ProcessStats.ProcessState>();
IApplicationThread thread;
發(fā)現(xiàn)又是一個IApplicationThread
那我們的實現(xiàn)類是是就可以猜出是ApplicationThread
這個類呢,其實這樣想我們是對的蟀伸,但是在這里你是找不到這個類的蚀同,我在開始找的時候也很頭疼,找了半天發(fā)現(xiàn)不是我所想的那樣啊掏。這里的ApplicationThread
是一個內(nèi)部類蠢络,它在ActivityThread
中。讓我們繼續(xù)走剛剛的方吧迟蜜。
public final void scheduleBindService(IBinder token, Intent intent,
boolean rebind, int processState) {
updateProcessState(processState, false);
BindServiceData s = new BindServiceData();
s.token = token;
s.intent = intent;
s.rebind = rebind;
Binder.getCallingPid());
sendMessage(H.BIND_SERVICE, s);
}
這里通過H 發(fā)送了一個BIND_SERVICE
消息
case BIND_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
handleBindService((BindServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
調(diào)用了handleBindService
方法
private void handleBindService(BindServiceData data) {
//從記錄中獲取一個service對象刹孔,每次啟動Service,系統(tǒng)都會記錄到mServices中
Service s = mServices.get(data.token);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
try {
//判斷service是否未綁定過了
if (!data.rebind) {
//沒有綁定需要走onBind
IBinder binder = s.onBind(data.intent);
ActivityManagerNative.getDefault().publishService(
data.token, data.intent, binder);
} else {
//綁定過需要走onRebind
s.onRebind(data.intent);
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, 0, 0, 0);
}
ensureJitEnabled();
} catch (RemoteException ex) {
}
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to bind to service " + s
+ " with " + data.intent + ": " + e.toString(), e);
}
}
}
}
這里會判斷是否已經(jīng)綁定過了娜睛,如果未綁定就回調(diào)onBind方法髓霞,綁定過了就會回調(diào)onRebingd方法。最后會調(diào)用publishService
方法微姊,我們在前面見過這個類酸茴,而且知道他的子類是ActivityManagerService
,那我們?nèi)ダ锩婵纯窗伞?/p>
public void publishService(IBinder token, Intent intent, IBinder service) {
synchronized(this) {
mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}
}
調(diào)用了publishServiceLocked
這里我們只貼關鍵代碼
for (int conni=r.connections.size()-1; conni>=0; conni--) {
ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
for (int i=0; i<clist.size(); i++) {
ConnectionRecord c = clist.get(i);
if (!filter.equals(c.binding.intent.intent)) {
if (DEBUG_SERVICE) Slog.v(
TAG, "Not publishing to: " + c);
if (DEBUG_SERVICE) Slog.v(
TAG, "Bound intent: " + c.binding.intent.intent);
if (DEBUG_SERVICE) Slog.v(
TAG, "Published intent: " + intent);
continue;
}
if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
try {
c.conn.connected(r.name, service);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + r.name +
" to connection " + c.conn.asBinder() +
" (in " + c.binding.client.processName + ")", e);
}
}
}
這時候就會去ConnectionRecord list中去查找,找到就開始調(diào)用c.conn.connected(r.name, service)
兢交,那這個conn又是什么呢薪捍,我們點進去看一下。
final class ConnectionRecord {
final IServiceConnection conn;
是不是感覺很熟悉,那我們按照以前的套路去查一下ServiceConnection
這個類吧酪穿,但是你會失望的發(fā)現(xiàn)他還是個接口凳干,那咋辦,還記得我在上面有個地方說一會還會回來看這里的地方么被济。我們?nèi)タ纯础?/p>
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
mMainThread.getHandler(), flags);
}
發(fā)現(xiàn)進入到了LoadedApk
中的getServiceDispatcher
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Handler handler, int flags) {
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
ArrayMap<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 ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
mServices.put(context, map);
}
map.put(c, sd);
} else {
sd.validate(context, handler);
}
return sd.getIServiceConnection();
}
}
這里把LoadedApk.ServiceDispatcher
放進了一個map中救赐,這里就是我們上面要找的那個conn
,讓我們看一下這個類的實現(xiàn)吧。
private static class InnerConnection extends IServiceConnection.Stub {
final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
public void connected(ComponentName name, IBinder service) throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service);
}
}
}
public void connected(ComponentName name, IBinder service) {
doConnected(name, service);
}
public void doConnected(ComponentName name, IBinder service) {
if (service != null) {
mConnection.onServiceConnected(name, service);
}
}
經(jīng)過一連串的方法調(diào)用只磷,終于看到了我們認識的方法mConnection.onServiceConnected(name, service);
最后會吧IBinder回調(diào)到我們的客戶端经磅。到這里bindService的流程就完了。
UML圖如下:
喜歡的請大家點贊哦钮追!不對的地方請留言指出预厌,謝謝。