主目錄見:Android高級進階知識(這是總目錄索引)
?為什么要突然講這一章呢?因為后面要開始講Framework的代碼,有太多應用到AIDL機制了。所以想在這里給大家介紹清楚這個,但是我不能保證我講的很清楚,不過希望大家自己能學懂,為后面的打下基礎,下面可能有塊硬骨頭要啃,我們上圖休息一下:
一.目標
今天講這個的原因前面已經講了,我們今天的目標就是搞懂AIDL的生成文件,然后明白調用過程,所以目標如下:
1.清楚AIDL生成文件的代碼結構;
2.從bindService的過程來了解調用過程。
二.AIDL生成文件分析
?為了分析AIDL生成文件,我們首先得來看看AIDL要怎么應用,就是怎么個寫法,我們這里還是以[LRouter]項目中的跨進程部分來講。首先我們來看看我們是怎么寫的:
1.首先要編寫aidl文件用于自動生成代碼
package com.lenovohit.lrouter_api;
import com.lenovohit.lrouter_api.core.LRouterRequest;
interface IRemoteRouterAIDL {
boolean stopRouter(String processName);
boolean checkIfLocalRouterAsync(String processName,in LRouterRequest routerRequset);
String navigation(String processName,in LRouterRequest routerRequest);
}
2.接著我們要編寫一個服務,然后把Stub綁定到這個服務上
public final class RemoteRouterService extends Service {
private static final String TAG = "RemoteRouterService";
public static final String PROCESS_NAME = "process_name";
@Override
public void onCreate() {
super.onCreate();
if (!(getApplication() instanceof LRouterAppcation)) {
throw new LRException("請檢查你的AndroidManifest.xml和applicaiton是LRouterApplicaiton");
}
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
.....
return mStub;
}
IRemoteRouterAIDL.Stub mStub = new IRemoteRouterAIDL.Stub() {
//省略實現的方法
......
};
}
3.編寫ServiceConnection在onServiceConnected得到遠程服務代理對象
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mRemoteRouterAIDL = IRemoteRouterAIDL.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
mRemoteRouterAIDL = null;
}
};
4.最后綁定服務
Intent bindRemoteRouterServiceIntent = new Intent(mLRouterAppcation,RemoteRouterService.class);
bindRemoteRouterServiceIntent.putExtra(RemoteRouterService.PROCESS_NAME,processName);
mLRouterAppcation.bindService(bindRemoteRouterServiceIntent,mServiceConnection, BIND_AUTO_CREATE);
到這里我們的使用就已經完成了,當然有些小細節沒有說,不過沒關系,這篇不是為了講具體的使用方法的,大家應該要已經知道怎么使用了。
1.bindService
要想把這一整套流程都講清楚就得從綁定服務開始,這里不像系統服務的啟動和注冊需要ServiceManager
管理。這里我們應用的服務直接從bindService開始講就可以。我們看到前面綁定服務的時候是Application
里面的bindService()方法,但是查找的時候會發現這里面沒有這個方法,而且在基類ContextWrapper
中:
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
這里的mBase是個ContextImpl
對象,于是調用ContextImpl
的bindService方法:
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
Process.myUserHandle());
}
我們看到這里調用了bindServiceCommon()方法:
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
} else {
throw new RuntimeException("Not supported in system context");
}
validateServiceIntent(service);
try {
....
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
.....
return res != 0;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
前面的mMainThread是一個ActivityThread
對象,通過他的getHandler()方法得到一個Handler對象,有了這個Handler
對象,就可以把消息發送到ActivityThread
所在線程的消息隊列中了。然后我們看到最終會把這個handler放進ServiceDispatcher
中去。這里的mPackageInfo就是我們的LoadedApk對象,所以我們看到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();
}
}
我們看到這里主要就是將ServiceConnection
的對象,handler等傳給ServiceDispatcher對象,我們看下ServiceDispatcher
類是長啥樣的:
static final class ServiceDispatcher {
private final ServiceDispatcher.InnerConnection mIServiceConnection;
private final ServiceConnection mConnection;
private final Context mContext;
private final Handler mActivityThread;
private final ServiceConnectionLeaked mLocation;
private final int mFlags;
private RuntimeException mUnbindLocation;
private boolean mForgotten;
private static class ConnectionInfo {
IBinder binder;
IBinder.DeathRecipient deathMonitor;
}
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);
}
}
}
.......
ServiceDispatcher(ServiceConnection conn,
Context context, Handler activityThread, int flags) {
mIServiceConnection = new InnerConnection(this);
mConnection = conn;
mContext = context;
mActivityThread = activityThread;
mLocation = new ServiceConnectionLeaked(null);
mLocation.fillInStackTrace();
mFlags = flags;
}
.......
}
?我們看到ServiceDispatcher
內部還創建了一個InnerConnection
對象,這是一個Binder對象,一會是要傳遞給ActivityManagerService
的,ActivityManagerServic
后續就是要通過這個Binder對象和ServiceConnection通信的。
?函數getServiceDispatcher最后就是返回了一個InnerConnection對象給ContextImpl.bindService函數。回到ContextImpl.bindService函數中,它接著就要調用ActivityManagerService
的遠程接口來進一步處理了。接著我們程序會調用 ActivityManagerNative.getDefault().bindService()方法來訪問遠程服務:
public int bindService(IApplicationThread caller, IBinder token,
Intent service, String resolvedType, IServiceConnection connection,
int flags, String callingPackage, int userId) 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);
data.writeString(callingPackage);
data.writeInt(userId);
mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
data.recycle();
reply.recycle();
return res;
}
這個函數通過Binder驅動程序就進入到ActivityManagerService
的bindService函數去了。我們緊接著看ActivityManagerService.bindService方法:
public int bindService(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, int flags, String callingPackage,
int userId) throws TransactionTooLargeException {
......
synchronized(this) {
return mServices.bindServiceLocked(caller, token, service,
resolvedType, connection, flags, callingPackage, userId);
}
}
我們看到這個方法最后直接調用了mServices.bindServiceLocked()方法,這個mServices就是ActiveServices類:
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String callingPackage, final int userId) throws TransactionTooLargeException {
.......
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
......
ActivityRecord activity = null;
if (token != null) {
activity = ActivityRecord.isInStackLocked(token);
.......
}
int clientLabel = 0;
PendingIntent clientIntent = null;
final boolean isCallerSystem = callerApp.info.uid == Process.SYSTEM_UID;
.....
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
Binder.getCallingUid(), userId, true, callerFg, isBindExternal);
.....
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);
if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
b.client.hasAboveClient = true;
}
if ((c.flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
s.whitelistManager = true;
}
if (s.app != null) {
updateServiceClientActivitiesLocked(s.app, c, true);
}
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) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}
.........
return 1;
}
?首先傳進來的token就是Application在AcitivityManagerService中的令牌,通過token就可以將對應的ActivityRecord取回。
?接著通過retrieveServiceLocked函數,得到一個ServiceRecord,這個ServiceReocrd
描述的是一個Service對象,這個service這里就是說的我們的RemoteRouterService
對象。這是根據傳進來的參數service的內容獲得的。我們前面說的綁定服務那里可以看出:
Intent bindRemoteRouterServiceIntent = new Intent(mLRouterAppcation,RemoteRouterService.class);
bindRemoteRouterServiceIntent.putExtra(RemoteRouterService.PROCESS_NAME,processName);
mLRouterAppcation.bindService(bindRemoteRouterServiceIntent,mServiceConnection, BIND_AUTO_CREATE);
?這里的參數service,就是上面的bindIntent了,它里面設置了RemoteRouterService
類的信息(RemoteRouterService.class),因此,這里可以通過它來把RemoteRouterService
的信息取出來,并且保存在ServiceRecord對象s中。
?接下來,就是把傳進來的參數connection封裝成一個ConnectionRecord
對象。注意,這里的參數connection是一個Binder對象,它的類型是LoadedApk.ServiceDispatcher.InnerConnection,后續ActivityManagerService
就是要通過它來告訴Application,RemoteRouterService
已經啟動起來了,因此,這里要把這個ConnectionRecord
變量c保存下來,它保在在好幾個地方,都是為了后面要用時方便地取回來的,這里就不仔細去研究了,只要知道ActivityManagerService
要使用它時就可以方便地把它取出來就可以了,具體后面我們再分析。
?最后,傳進來的參數flags的位Context.BIND_AUTO_CREATE為1。最后程序會調用ActiveServices
類的bringUpServiceLocked繼續處理:
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
.......
final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
final String procName = r.processName;
ProcessRecord app;
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
.....
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
realStartServiceLocked(r, app, execInFg);
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortName, e);
}
}
} else {
app = r.isolatedProc;
}
if (app == null && !permissionsReviewRequired) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
"service", r.name, false, isolated, false)) == null) {
.......
return msg;
}
if (isolated) {
r.isolatedProc = app;
}
}
.......
return null;
}
我們如果在AndroidManifest.xml中有設置process的話,那么這里procName就會是我們設置的字符串。如果沒有的話就會默認是包名。配合這uid會獲取到ProcessRecord
對象。如果這個ProcessRecord為null的話就是說還沒有這個進程存在,所以后面會調用startProcessLocked()方法來創建一個新的進程然后在這個進程里面把這個服務啟動。不然就調用realStartServiceLocked()方法在應用程序進程中啟動應用Service,我們來看下這個方法:
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
......
r.app = app;
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
final boolean newService = app.services.add(r);
.......
boolean created = false;
try {
......
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
.....
} catch (DeadObjectException e) {
.....
} finally {
.....
}
.....
requestServiceBindingsLocked(r, execInFg);
.....
}
這個方法里面有兩個重要的方法scheduleCreateService和requestServiceBindingsLocked,這兩個方法分別是啟動服務和綁定服務(會調用Service的onBind方法)操作。
2.scheduleCreateService啟動服務
我們看到上面程序調用了 app.thread的scheduleCreateService方法,這里的app.thread是一個bind遠程對象,類型為ApplicationThreadProxy
,每一個Android應用程序進程里面都有一個ActivtyThread
對象和一個ApplicationThread
對象,其中是ApplicationThread對象是ActivityThread對象的一個成員變量,是ActivityThread
與ActivityManagerService
之間用來執行進程間通信的。所以我們看看這個ApplicationThreadProxy(這個類在ApplicationThreadNative里面)的scheduleCreateService干了什么:
public final void scheduleCreateService(IBinder token, ServiceInfo info,
CompatibilityInfo compatInfo, int processState) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(token);
info.writeToParcel(data, 0);
compatInfo.writeToParcel(data, 0);
data.writeInt(processState);
try {
mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
} catch (TransactionTooLargeException e) {
Log.e("CREATE_SERVICE", "Binder failure starting service; service=" + info);
throw e;
}
data.recycle();
}
這里通過了Bind機制就調用到了ActivityThread的scheduleCreateService函數中去了:
public final void scheduleCreateService(IBinder token,
ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
updateProcessState(processState, false);
CreateServiceData s = new CreateServiceData();
s.token = token;
s.info = info;
s.compatInfo = compatInfo;
sendMessage(H.CREATE_SERVICE, s);
}
這里可以看到主要是發送了一個消息,消息最終會調用到這個sendMessage()方法:
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
我們這個消息是發送到mH中了,這個mH又是什么呢?這里是H
類,我們看他里面的handleMessage()方法:
public void handleMessage(Message msg) {
switch (msg.what) {
....
case CREATE_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
......
}
}
我們看到這個主要就是調用handleCreateService()方法,這個方法就是創建的Service了:
private void handleCreateService(CreateServiceData data) {
unscheduleGcIdler();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {
......
try {
......
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault());
service.onCreate();
mServices.put(data.token, service);
try {
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
.....
}
}
我們看到這個方法用類加載器把service加載進內存,然后調用了service的onCreate()方法,到這里我們的服務已經啟動起來了。我們接下來看看服務的綁定。
3.requestServiceBindingsLocked 服務的綁定
?前面我們的服務已經啟動且調用了Service的onCreate方法,那么接下來綁定的過程就會調用服務的onBind()方法,那么我們接下來來看綁定的方法即ActiveServices
的requestServiceBindingsLocked:
private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
throws TransactionTooLargeException {
for (int i=r.bindings.size()-1; i>=0; i--) {
IntentBindRecord ibr = r.bindings.valueAt(i);
if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
break;
}
}
}
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
........
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
.........
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.repProcState);
........
} catch (TransactionTooLargeException e) {
.........
} catch (RemoteException e) {
.........
}
}
return true;
}
?這里傳進來的ServiceRecord
就是我們的RemoteRouterService服務,函數requestServiceBindingsLocked調用了requestServiceBindingLocked函數來處理綁定服務的操作,然后requestServiceBindingLocked方法會調用r.app.thread.scheduleBindService來綁定服務,跟上面的啟動過程類似。我們就直接跳到ActivityThread
的handleBindService來講解:
private void handleBindService(BindServiceData data) {
Service s = mServices.get(data.token);
.......
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
try {
if (!data.rebind) {
IBinder binder = s.onBind(data.intent);
ActivityManagerNative.getDefault().publishService(
data.token, data.intent, binder);
} else {
s.onRebind(data.intent);
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
ensureJitEnabled();
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} catch (Exception e) {
.......
}
}
}
?執行ActivityThread.handleCreateService函數中,已經將這個RemoteRouterService
實例保存在mServices中,因此,這里首先通過data.token值將它取回來,保存在本地變量s中,接著執行了兩個操作,一個操作是調用s.onBind,即RemoteRouterService.onBind獲得一個Binder對象,另一個操作就是把這個Binder對象傳遞給ActivityManagerService。
?到這里我們Service的onCreate和onBind都已經調用完畢,onBind返回的是我們的IRemoteRouterAIDL#Stub()
,得到這個對象之后程序就調用publishService()方法,同樣的,這里是調用ActivityManagerProxy
的publishService通知mLRouterAppcation(Application對象),Service已經啟動完畢:
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函數中去了:
public void publishService(IBinder token, Intent intent, IBinder service) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
synchronized(this) {
if (!(token instanceof ServiceRecord)) {
throw new IllegalArgumentException("Invalid service token");
}
mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}
}
我們看到這個方法里面主要是調用了mServices即ActiveServices對象,所以我們跟進ActiveServices的publishServiceLocked()方法:
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
final long origId = Binder.clearCallingIdentity();
try {
........
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;
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)) {
......
continue;
}
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Publishing to: " + c);
try {
c.conn.connected(r.name, service);
} catch (Exception e) {
.......
}
}
}
}
serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
在之前ActiveServices
的bindServiceLocked()方法的時候,我們已經將一個ConnectionRecord對象放進ServiceRecord.connections列表中了:
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);
publishServiceLocked()里面就是將這個ConnectionRecord取出來,然后調用他的connected()方法。那么這里的ConnectionRecord的conn又是什么呢?這個是我們之前ServiceDispatcher的InnerConnection對象,因此,這里執行c.conn.connected函數后就會進入到ServiceDispatcher.InnerConnection#connected
函數中去了:
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方法:
public void connected(ComponentName name, IBinder service) {
if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0));
} else {
doConnected(name, service);
}
}
這里的mActivityThread 是之前通過ActivityThread.getHandler函數得到的,因此,調用它的post函數后,就會把一個消息放到ActivityThread
的消息隊列中去了。如果不明白消息機制的建議看下Handler,MessageQueue,與Looper三者關系分析,我們最終post的消息會調用到RunConnection中的run方法:
public void run() {
if (mCommand == 0) {
doConnected(mName, mService);
} else if (mCommand == 1) {
doDeath(mName, mService);
}
}
這里的mCommand值為0,于是就執行ServiceDispatcher
的doConnected方法來進一步操作了:
public void doConnected(ComponentName name, IBinder service) {
ServiceDispatcher.ConnectionInfo old;
ServiceDispatcher.ConnectionInfo info;
synchronized (this) {
.......
// If there was an old service, it is now disconnected.
if (old != null) {
mConnection.onServiceDisconnected(name);
}
// If there is a new service, it is now connected.
if (service != null) {
mConnection.onServiceConnected(name, service);
}
}
到這里我們可以看到我們調用了mConnection的onServiceConnected()方法。這個mConnection就是我們bindService之前傳進來的ServiceConnection對象mServiceConnection:
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mRemoteRouterAIDL = IRemoteRouterAIDL.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
mRemoteRouterAIDL = null;
}
};
所以我們這里就到了onServiceConnected方法里面,我們這里調用了IRemoteRouterAIDL.Stub.asInterface(service),終于我們要開始AIDL生成的源碼的分析了。
4.asInterface
我們看到綁定完成會回調ServiceConnection的onServiceConnected方法然后會調用這個方法,這個方法在AIDL文件生成的源碼中:
public static com.lenovohit.lrouter_api.IRemoteRouterAIDL asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.lenovohit.lrouter_api.IRemoteRouterAIDL))) {
return ((com.lenovohit.lrouter_api.IRemoteRouterAIDL)iin);
}
return new com.lenovohit.lrouter_api.IRemoteRouterAIDL.Stub.Proxy(obj);
}
這個方法主要用于將服務端的Binder對象轉換成客戶端所需的AIDL接口類型的對象,這種轉換過程是區分進程的 [如果客戶端和服務端位于同一進程,那么此方法返回的就是服務端的Stub對象本身,否則返回的是系統封裝后的Stub.proxy對象]。所以如果我們客戶端要跨進程調用遠程服務的時候,我們都是通過這個proxy代理來訪問,這里舉例我們要調用stopRouter方法,我們的代理是怎么訪問的呢?
@Override public boolean stopRouter(java.lang.String processName) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
boolean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(processName);
mRemote.transact(Stub.TRANSACTION_stopRouter, _data, _reply, 0);
_reply.readException();
_result = (0!=_reply.readInt());
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
我們看到這里這個方法通過Binder機制調用遠程RemoteRouterService的stopRouter()方法,因為mRemote就是綁定服務時候傳回來的IRemoteRouterAIDL.Stub()的IBinder對象。然后服務端接受到消息的時候就會調用生成文件里面的onTransact方法里面對應的方法:
case TRANSACTION_stopRouter:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
boolean _result = this.stopRouter(_arg0);
reply.writeNoException();
reply.writeInt(((_result)?(1):(0)));
return true;
}
到這里就會調用到了RemoteRouterService
中IRemoteRouterAIDL.Stub
的stopRouter()方法了。好了到這里我們整個流程也就講完了,其實AIDL文件生成的代碼并不難,難的是要明白整個調用過程。
總結:今天講的內容還是比較多的,結合了bindService的過程來把整個AIDL生成的源代碼的流程串了起來,如果感覺比較費勁的話就只要明白這里面的幾個角色就行了,不需要整個流程明白,希望我們后面的framework之旅愉快。