一 AIDL demo

1.1 服务端搭建

新建AIDL文件

// IUserCalc.aidl
package com.example.aidlserver;// Declare any non-default types here with import statementsinterface IUserCalc {String getUserName();String getUserPassword();
}

创建Service

/*** Created by hjcai on 2021/4/25.*/
public class UserService extends Service {private static final String TAG = "UserService";@Nullable@Overridepublic IBinder onBind(Intent intent) {Log.e(TAG, "onBind: ");return mBinder;}@Overridepublic boolean onUnbind(Intent intent) {Log.e(TAG, "onUnbind: ");return super.onUnbind(intent);}private final IUserCalc.Stub mBinder = new IUserCalc.Stub() {@Overridepublic String getUserName() throws RemoteException {Log.e(TAG, "getUserName: ");return "hjcai";}@Overridepublic String getUserPassword() throws RemoteException {Log.e(TAG, "getUserPassword: ");return "12341234";}};
}

在清单文件中配置service和sharedUserId

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.aidlserver"android:sharedUserId="com.id.hjcai"><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.LearnEassyJoke"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><serviceandroid:name=".UserService"android:exported="false"><intent-filter><action android:name="com.example.aidl.server" /></intent-filter></service></application></manifest>

服务端搭建完毕

1.2 客户端搭建

拷贝服务端的AIDL
创建服务端Service代理的包装类

/*** Created by hjcai on 2021/4/25.*/
class ServerServiceWrapper {private static final String TAG = "ServerServiceWrapper";private IUserCalc mCalcAidl;public static ServerServiceWrapper instance;private ServerServiceWrapper() {}public static ServerServiceWrapper getInstance() {if (instance == null) {synchronized (ServerServiceWrapper.class) {if (instance == null) {instance = new ServerServiceWrapper();}}}return instance;}public boolean bindService(Context context) {Intent intent = new Intent();intent.setAction("com.example.aidl.server");// 需要明确指明server端包名 否则抛出如下异常// Service Intent must be explicit: Intent { act=com.example.aidl.server }intent.setPackage("com.example.aidlserver");return context.bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE);}public void unbindService(Context context) {if(mCalcAidl != null){context.unbindService(mServiceConn);}}// 返回服务端的代理private ServiceConnection mServiceConn = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {Log.e(TAG, "onServiceConnected: ");mCalcAidl = IUserCalc.Stub.asInterface(service);}@Overridepublic void onServiceDisconnected(ComponentName name) {Log.e(TAG, "onServiceDisconnected: ");mCalcAidl = null;}};public String getName() {try {return mCalcAidl == null ? "" : mCalcAidl.getUserName();} catch (RemoteException e) {e.printStackTrace();}return "";}public String getPass() {try {return mCalcAidl == null ? "" : mCalcAidl.getUserPassword();} catch (RemoteException e) {e.printStackTrace();}return "";}
}

创建测试xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="bind"android:text="bind" /><Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="unBind"android:text="unbind" /><Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="getName"android:text="getName" /><Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="getPass"android:text="getPass" /></LinearLayout>

创建测试Activity

public class MainActivity extends AppCompatActivity {private static final String TAG = "MyApp";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void bind(View view) {boolean res = ServerServiceWrapper.getInstance().bindService(this);Log.e(TAG, "bind: "+res);}public void unBind(View view) {ServerServiceWrapper.getInstance().unbindService(this);Log.e(TAG, "unBind");}public void getName(View view) {String name = ServerServiceWrapper.getInstance().getName();Log.e(TAG, "getName: " + name);}public void getPass(View view) {String pass = ServerServiceWrapper.getInstance().getPass();Log.e(TAG, "getPass: " + pass);}
}

修改客户端清单文件 加入sharedUserId

android:sharedUserId="com.id.hjcai"

其中 核心类为服务端的Service 客户端的Wrapper

1.3运行效果

分别点击
bind getName getPass unBind得到运行结果:

2021-04-26 09:54:46.372 27151-27151/com.example.aidlclient E/MyApp: bind: true
2021-04-26 09:54:46.376 28183-28183/com.example.aidlserver E/UserService: onBind:
2021-04-26 09:54:46.385 27151-27151/com.example.aidlclient E/ServerServiceWrapper: onServiceConnected: 2021-04-26 09:54:51.992 28183-28225/com.example.aidlserver E/UserService: getUserName:
2021-04-26 09:54:51.992 27151-27151/com.example.aidlclient E/MyApp: getName: hjcai2021-04-26 09:54:59.618 28183-28225/com.example.aidlserver E/UserService: getUserPassword:
2021-04-26 09:54:59.619 27151-27151/com.example.aidlclient E/MyApp: getPass: 123412342021-04-26 09:55:04.601 27151-27151/com.example.aidlclient E/MyApp: unBind
2021-04-26 09:55:04.601 28183-28183/com.example.aidlserver E/UserService: onUnbind:

二 AIDL大致流程(基于API28)

2.1 分析一下大致流程

客户端调用bindService Server返回 Service对象

    public IBinder onBind(Intent intent) {Log.e(TAG, "onBind: ");return mBinder;//服务端返回了存根(stub)类}private final IUserCalc.Stub mBinder = new IUserCalc.Stub() {...}

客户端onServiceConnected回调中 将存根类转换为代理类

        @Overridepublic void onServiceConnected(ComponentName name, IBinder service) {Log.e(TAG, "onServiceConnected: ");mCalcAidl = IUserCalc.Stub.asInterface(service);}

接着客户端可以通过代理Service类调用远程service的方法

下面分析具体的流程

2.2 调用bindService后 Server端执行onBind 之后 Client端执行onServiceConnected

2021-04-26 09:54:46.372 27151-27151/com.example.aidlclient E/MyApp: bind: true
2021-04-26 09:54:46.376 28183-28183/com.example.aidlserver E/UserService: onBind:
2021-04-26 09:54:46.385 27151-27151/com.example.aidlclient E/ServerServiceWrapper: onServiceConnected:

从client的bindService到server的onBind

 // activitycontext.bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE);// ContextWrapper.java@Overridepublic boolean bindService(Intent service, ServiceConnection conn,int flags) {return mBase.bindService(service, conn, flags);}// Context的具体实现类是ContextImpl// ContextImpl.java@Overridepublic boolean bindService(Intent service, ServiceConnection conn,int flags) {warnIfCallingFromSystemProcess();return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser());}private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handlerhandler, UserHandle user) {// Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.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 {IBinder token = getActivityToken();if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null&& mPackageInfo.getApplicationInfo().targetSdkVersion< android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {flags |= BIND_WAIVE_PRIORITY;}service.prepareToLeaveProcess(this);// 以下是重点// 结合ActivityManager的代码分析 可知ActivityManager.getService()得到是IActivityManager对象// 那么需要找到IActivityManager的bindService具体实现类int res = ActivityManager.getService().bindService(mMainThread.getApplicationThread(), getActivityToken(), service,service.resolveTypeIfNeeded(getContentResolver()),sd, flags, getOpPackageName(), user.getIdentifier());if (res < 0) {throw new SecurityException("Not allowed to bind to service " + service);}return res != 0;} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}// ActivityManager.javapublic static IActivityManager getService() {// 结合下面的IActivityManagerSingleton赋值代码 可知getService返回的是包装好的IBinder的IActivityManager对象return IActivityManagerSingleton.get();}private static final Singleton<IActivityManager> IActivityManagerSingleton =new Singleton<IActivityManager>() {@Overrideprotected IActivityManager create() {final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);final IActivityManager am = IActivityManager.Stub.asInterface(b);return am;}};// IActivityManager是一个接口 其实现类是ActivityManagerService 查找具体的bindService方法public int bindService(IApplicationThread caller, IBinder token, Intent service,String resolvedType, IServiceConnection connection, int flags, String callingPackage,int userId) throws TransactionTooLargeException {enforceNotIsolatedCaller("bindService");// Refuse possible leaked file descriptorsif (service != null && service.hasFileDescriptors() == true) {throw new IllegalArgumentException("File descriptors passed in Intent");}if (callingPackage == null) {throw new IllegalArgumentException("callingPackage cannot be null");}synchronized(this) {// 重点return mServices.bindServiceLocked(caller, token, service,resolvedType, connection, flags, callingPackage, userId);}}// bindServiceLocked方法内容颇多 我们只关注代码最后一部分// ActiveServices.javaint bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,String resolvedType, final IServiceConnection connection, int flags,String callingPackage, final int userId) throws TransactionTooLargeException {...if (s.app != null && b.intent.received) {// Service is already running, so we can immediately// publish the connection.try {c.conn.connected(s.name, b.intent.binder, false);} catch (Exception e) {Slog.w(TAG, "Failure sending service " + s.shortName+ " to connection " + c.conn.asBinder()+ " (in " + c.binding.client.processName + ")", e);}// If this is the first app connected back to this binding,// and the service had previously asked to be told when// rebound, then do so.if (b.intent.apps.size() == 1 && b.intent.doRebind) {// 重点在这requestServiceBindingLocked(s, b.intent, callerFg, true);}} else if (!b.intent.requested) {// 重点在这requestServiceBindingLocked(s, b.intent, callerFg, false);}...}private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,boolean execInFg, boolean rebind) throws TransactionTooLargeException {if (r.app == null || r.app.thread == null) {// If service is not currently running, can't yet bind.return false;}if (DEBUG_SERVICE) Slog.d(TAG_SERVICE, "requestBind " + i + ": requested=" + i.requested+ " rebind=" + rebind);if ((!i.requested || rebind) && i.apps.size() > 0) {try {bumpServiceExecutingLocked(r, execInFg, "bind");r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);// 重点!//scheduleBindService无法点进去看,那么看看thread是什么r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,r.app.repProcState);if (!rebind) {i.requested = true;}i.hasBound = true;i.doRebind = false;} catch (TransactionTooLargeException e) {// Keep the executeNesting count accurate.if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r, e);final boolean inDestroying = mDestroyingServices.contains(r);serviceDoneExecutingLocked(r, inDestroying, inDestroying);throw e;} catch (RemoteException e) {if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r);// Keep the executeNesting count accurate.final boolean inDestroying = mDestroyingServices.contains(r);serviceDoneExecutingLocked(r, inDestroying, inDestroying);return false;}}return true;}// 我们经过 ServiceRecord 在ProcessRecord发现thread的真面目ProcessRecord app;  // ProcessRecord.javaIApplicationThread thread;  // the actual proc...  may be null only if// 'persistent' is true (in which case we// are in the process of launching the app)// IApplicationThread的实现类是ApplicationThread ApplicationThread又是ActivityThread的内部类// 因此我们找到ActivityThread 打开后找到ApplicationThread 再查看ApplicationThread的scheduleBindService方法// ActivityThread.javapublic 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;if (DEBUG_SERVICE)Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="+ Binder.getCallingUid() + " pid=" + Binder.getCallingPid());// 重点 发送handler消息sendMessage(H.BIND_SERVICE, s);}public void handleMessage(Message msg) {switch (msg.what) {...case BIND_SERVICE:Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");handleBindService((BindServiceData)msg.obj);Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);break;...}}private void handleBindService(BindServiceData data) {Service s = mServices.get(data.token);if (DEBUG_SERVICE)Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);if (s != null) {try {data.intent.setExtrasClassLoader(s.getClassLoader());data.intent.prepareToEnterProcess();try {if (!data.rebind) {// 重点 调用了Service的onBind方法 第一个目标达成!!!!!!!!!1IBinder binder = s.onBind(data.intent);// 前面我们知道IActivityManager是一个接口 其实现类是ActivityManagerService// 因此我们知道publishService具体实现在ActivityManagerServiceActivityManager.getService().publishService(data.token, data.intent, binder);} else {s.onRebind(data.intent);ActivityManager.getService().serviceDoneExecuting(data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);}ensureJitEnabled();} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}} catch (Exception e) {if (!mInstrumentation.onException(s, e)) {throw new RuntimeException("Unable to bind to service " + s+ " with " + data.intent + ": " + e.toString(), e);}}}}// ActivityManagerService.javapublic void publishService(IBinder token, Intent intent, IBinder service) {// Refuse possible leaked file descriptorsif (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);}}// ActiveService.javavoid publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {final long origId = Binder.clearCallingIdentity();try {if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "PUBLISHING " + r+ " " + intent + ": " + service);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)) {if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Not publishing to: " + c);if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bound intent: " + c.binding.intent.intent);if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Published intent: " + intent);continue;}if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Publishing to: " + c);try {// 重点 我们需要知道connected方法的实现// 需要查看conn的具体定义c.conn.connected(r.name, service, false);} catch (Exception e) {Slog.w(TAG, "Failure sending service " + r.name +" to connection " + c.conn.asBinder() +" (in " + c.binding.client.processName + ")", e);}}}}serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);}} finally {Binder.restoreCallingIdentity(origId);}}// ConnectionRecord.javafinal IServiceConnection conn; //这东西看起来有些熟悉 我们在ContextImpl中看到过// ContextImpl.javaprivate boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handlerhandler, UserHandle user) {// Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.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");}...}// LoadedApk.javapublic 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) {if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);sd = map.get(c);}if (sd == null) {sd = new ServiceDispatcher(c, context, handler, flags);if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);if (map == null) {map = new ArrayMap<>();mServices.put(context, map);}map.put(c, sd);} else {sd.validate(context, handler);}return sd.getIServiceConnection();// 查看sd对象类型}}IServiceConnection getIServiceConnection() {// sd 是IServiceConnection类型return mIServiceConnection;}// 继续查看mIServiceConnection的定义// 最终发现 c.conn.connected(r.name, service, false);中的connn是InnerConnection对象private final ServiceDispatcher.InnerConnection mIServiceConnection;// 我们继续看connected的方法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, boolean dead)throws RemoteException {LoadedApk.ServiceDispatcher sd = mDispatcher.get();if (sd != null) {sd.connected(name, service, dead);}}}public void connected(ComponentName name, IBinder service, boolean dead) {if (mActivityThread != null) {// 这里最终也会调用doConnected方法mActivityThread.post(new RunConnection(name, service, 0, dead));} else {doConnected(name, service, dead);}}public void doConnected(ComponentName name, IBinder service, boolean dead) {ServiceDispatcher.ConnectionInfo old;ServiceDispatcher.ConnectionInfo info;synchronized (this) {if (mForgotten) {// We unbound before receiving the connection; ignore// any connection received.return;}old = mActiveConnections.get(name);if (old != null && old.binder == service) {// Huh, already have this one.  Oh well!return;}if (service != null) {// A new service is being connected... set it all up.info = new ConnectionInfo();info.binder = service;info.deathMonitor = new DeathMonitor(name, service);try {service.linkToDeath(info.deathMonitor, 0);mActiveConnections.put(name, info);} catch (RemoteException e) {// This service was dead before we got it...  just// don't do anything with it.mActiveConnections.remove(name);return;}} else {// The named service is being disconnected... clean up.mActiveConnections.remove(name);}if (old != null) {old.binder.unlinkToDeath(old.deathMonitor, 0);}}// If there was an old service, it is now disconnected.if (old != null) {mConnection.onServiceDisconnected(name);}if (dead) {mConnection.onBindingDied(name);}// If there is a new viable service, it is now connected.if (service != null) {// 被调用!!!mConnection.onServiceConnected(name, service);} else {// The binding machinery worked, but the remote returned null from onBind().mConnection.onNullBinding(name);}}

小结一下调用顺序:

    //Context.javapublic abstract boolean bindService(@RequiresPermission Intent service,@NonNull ServiceConnection conn, @BindServiceFlags int flags);//ContextImpl.java (Context.java实现类)@Overridepublic boolean bindService(Intent service, ServiceConnection conn,int flags) {warnIfCallingFromSystemProcess();return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser());}private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handlerhandler, UserHandle user) {...int res = ActivityManager.getService().bindService(mMainThread.getApplicationThread(), getActivityToken(), service,service.resolveTypeIfNeeded(getContentResolver()),sd, flags, getOpPackageName(), user.getIdentifier());}//需要知道ActivityManager.getService()返回的对象 才能知道调用谁的bindService方法//ActivityManager.java public static IActivityManager getService() {return IActivityManagerSingleton.get();}//问题转换为需要知道IActivityManager的实现类 才能知道调用谁的bindService方法//IActivityManager是一个接口 其实现类是ActivityManagerService//ActivityManagerService.javapublic int bindService(IApplicationThread caller, IBinder token, Intent service,String resolvedType, IServiceConnection connection, int flags, String callingPackage,int userId) throws TransactionTooLargeException {...return mServices.bindServiceLocked(caller, token, service,resolvedType, connection, flags, callingPackage, userId);}//AvtiveServices.javaint bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,String resolvedType, final IServiceConnection connection, int flags,String callingPackage, final int userId) throws TransactionTooLargeException {...if (b.intent.apps.size() == 1 && b.intent.doRebind) {requestServiceBindingLocked(s, b.intent, callerFg, true);}} else if (!b.intent.requested) {requestServiceBindingLocked(s, b.intent, callerFg, false);}}private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,boolean execInFg, boolean rebind) throws TransactionTooLargeException {...r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,r.app.repProcState);}// 想知道scheduleBindService的实现 要知道thread是什么ProcessRecord app;  //app的定义//跟进ProcessRecord 查到thread的定义//ProcessRecord.javaIApplicationThread thread;//IApplicationThread的实现类是ApplicationThread ApplicationThread又是ActivityThread的内部类//因此我需要从ActivityThread内找出ApplicationThread 并查看其中的scheduleBindService方法public final void scheduleBindService(IBinder token, Intent intent,boolean rebind, int processState) {...sendMessage(H.BIND_SERVICE, s);}//在ActivityThread中查找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;//跟进handleBindServiceprivate void handleBindService(BindServiceData data) {IBinder binder = s.onBind(data.intent);//!!!!!!!//第一步达成!!onBind被调用//前面我们分析 ActivityManager.getService()返回的对象就是ActivityManagerServiceActivityManager.getService().publishService(data.token, data.intent, binder);}//查看ActivityManagerService的publishService//ActivityManagerServicepublic void publishService(IBinder token, Intent intent, IBinder service) {...mServices.publishServiceLocked((ServiceRecord)token, intent, service);}}//ActiveServicesvoid publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {c.conn.connected(r.name, service, false);}//想知道connected方法内容 需要知道conn的真实对象//ConnectionRecordfinal IServiceConnection conn;//IServiceConnection在ContextImpl中出现过IServiceConnection sd;//它具体的赋值在sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);//LoadedApk.javapublic final IServiceConnection getServiceDispatcher(ServiceConnection c,Context context, Handler handler, int flags) {...return sd.getIServiceConnection();}IServiceConnection getIServiceConnection() {return mIServiceConnection;}mIServiceConnection = new InnerConnection(this);//破案了 mPackageInfo.getServiceDispatcher返回的类型是InnerConnection//conn的类型其实是InnerConnection 查看InnerConnection.connectedpublic void connected(ComponentName name, IBinder service, boolean dead)throws RemoteException {LoadedApk.ServiceDispatcher sd = mDispatcher.get();if (sd != null) {sd.connected(name, service, dead);}}public void connected(ComponentName name, IBinder service, boolean dead) {if (mActivityThread != null) {//最终也会调用doConnected方法mActivityThread.post(new RunConnection(name, service, 0, dead));} else {doConnected(name, service, dead);}}public void doConnected(ComponentName name, IBinder service, boolean dead) {...mConnection.onServiceConnected(name, service);}

至此我们知道了客户端调用bindService 服务端onBind 客户端onServiceConnected调用的顺序了
简单来说客户端的具体信息在调用bindService时被存储在ContextImpl的connection中 后面通过 ActivityManagerService查询service并进行bind操作,完了又通过ActivityManagerService告知客户端绑定成功与否,告知是通过connection进行通知的

2.3 IUserCalc.java

在进一步分析之前我们先看一下Android Studio根据IUserCalc.aidl为我们生成的IUserCalc.java的大致内容

/** This file is auto-generated.  DO NOT MODIFY.*/
package com.example.aidlserver;
// Declare any non-default types here with import statements
public interface IUserCalc extends android.os.IInterface
{/** Default implementation for IUserCalc. */public static class Default implements com.example.aidlserver.IUserCalc{@Override public java.lang.String getUserName() throws android.os.RemoteException{return null;}@Override public java.lang.String getUserPassword() throws android.os.RemoteException{return null;}@Overridepublic android.os.IBinder asBinder() {return null;}}// end Default/** Local-side IPC implementation stub class. *//*** 本地跨进程IPC实现 存根类* 包含几个静态变量(多用于识别调用端 调用的是哪个方法)* 几个方法 和一个静态内部类*/// 内部类 Stub,继承了Binder,所以Stub就是一个Binder类 同时实现了IUserCalc 因此需要实现两个方法getUserName getUserPassword// 具体实现在Stub内部类 Proxy中public static abstract class Stub extends android.os.Binder implements com.example.aidlserver.IUserCalc{// Binder唯一标识,一般用当前aidl的完整包名+类名表示private static final java.lang.String DESCRIPTOR = "com.example.aidlserver.IUserCalc";/** Construct the stub at attach it to the interface. */public Stub(){// 关联指定接口和Binderthis.attachInterface(this, DESCRIPTOR);//this代表接口  DESCRIPTOR代表Binder}/*** Cast an IBinder object into an com.example.aidlserver.IUserCalc interface,* generating a proxy if needed.** 将IBinder转化为com.example.aidlserver.IUserCalc的接口对象* 代码分析:如果客户端和服务端同进程,则返回服务端的Stub对象本身 否则返回封装后的Stub.Proxy对象*/public static com.example.aidlserver.IUserCalc asInterface(android.os.IBinder obj){if ((obj==null)) {return null;}// 尝试从本地实现接口接收binder对象,如果得到的是null,你就需要从服务器端得到Binder对象,来转化成客户端所需的AIDL对象,即需要实例化proxy类来通过transact方法收集回调android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin!=null)&&(iin instanceof com.example.aidlserver.IUserCalc))) {// 无需跨进程return ((com.example.aidlserver.IUserCalc)iin);}// 跨进程casereturn new com.example.aidlserver.IUserCalc.Stub.Proxy(obj);}//返回当前binder对象@Override public android.os.IBinder asBinder(){return this;}// 运行在服务器端// onTransact只有当客户端和服务端不在同一个进程时才会调用// code代表请求类型 data中存放请求的参数,之后执行指定方法,// reply是服务器返回的结果,flags标明是否有返回值,0为有(双向),1为没有(单向),// 执行完毕向reply写入结果,如果有的话,return值代表返回成功或失败// 方法运行在服务端的binder线程池,客户端请求后通过底层代码将请求封装后交由该方法处理@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException{java.lang.String descriptor = DESCRIPTOR;switch (code){case INTERFACE_TRANSACTION:{reply.writeString(descriptor);return true;}case TRANSACTION_getUserName:{data.enforceInterface(descriptor);java.lang.String _result = this.getUserName();reply.writeNoException();reply.writeString(_result);return true;}case TRANSACTION_getUserPassword:{data.enforceInterface(descriptor);java.lang.String _result = this.getUserPassword();reply.writeNoException();reply.writeString(_result);return true;}default:{return super.onTransact(code, data, reply, flags);}}}//代理类private static class Proxy implements com.example.aidlserver.IUserCalc{private android.os.IBinder mRemote;Proxy(android.os.IBinder remote){mRemote = remote;}@Override public android.os.IBinder asBinder(){return mRemote;}public java.lang.String getInterfaceDescriptor(){return DESCRIPTOR;}//运行在客户端,运行步骤如下//1创建输入型参数data和输出型参数reply,注意他们都是parcel类型的//2创建返回值对象result(如果有的话)//3将参数写入data(如果有参数)//4调用transact发起远程请求,接着当前线程挂起//5远程服务端的onTransact调用并返回结果//6挂起的线程继续执行,从reply中取出返回结果result(如果有的话),并返回result@Override public java.lang.String getUserName() throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();java.lang.String _result;try {_data.writeInterfaceToken(DESCRIPTOR);boolean _status = mRemote.transact(Stub.TRANSACTION_getUserName, _data, _reply, 0);if (!_status && getDefaultImpl() != null) {return getDefaultImpl().getUserName();}_reply.readException();_result = _reply.readString();}finally {_reply.recycle();_data.recycle();}return _result;}//执行过程和getUserName一样 只不过调用方法的参数不一样@Override public java.lang.String getUserPassword() throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();java.lang.String _result;try {_data.writeInterfaceToken(DESCRIPTOR);boolean _status = mRemote.transact(Stub.TRANSACTION_getUserPassword, _data, _reply, 0);if (!_status && getDefaultImpl() != null) {return getDefaultImpl().getUserPassword();}_reply.readException();_result = _reply.readString();}finally {_reply.recycle();_data.recycle();}return _result;}public static com.example.aidlserver.IUserCalc sDefaultImpl;}// 两个int值,用于标记调用的是哪个接口 如果IUserCalc有多个方法 这里会增加静态int值static final int TRANSACTION_getUserName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);static final int TRANSACTION_getUserPassword = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);public static boolean setDefaultImpl(com.example.aidlserver.IUserCalc impl) {// Only one user of this interface can use this function// at a time. This is a heuristic to detect if two different// users in the same process use this function.if (Stub.Proxy.sDefaultImpl != null) {throw new IllegalStateException("setDefaultImpl() called twice");}if (impl != null) {Stub.Proxy.sDefaultImpl = impl;return true;}return false;}public static com.example.aidlserver.IUserCalc getDefaultImpl() {return Stub.Proxy.sDefaultImpl;}}// 接口里定义的两个方法public java.lang.String getUserName() throws android.os.RemoteException;public java.lang.String getUserPassword() throws android.os.RemoteException;
}

下面我们就继续分析客户端调用getName的调用过程

2.4 调用接口分析

2021-04-26 09:54:51.992 28183-28225/com.example.aidlserver E/UserService: getUserName:
2021-04-26 09:54:51.992 27151-27151/com.example.aidlclient E/MyApp: getName: hjcai
   mCalcAidl.getUserName();//Android studio根据AIDL生成的java文件@Override public java.lang.String getUserName() throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();java.lang.String _result;try {_data.writeInterfaceToken(DESCRIPTOR);// 走这里 这里会挂起当前线程 等待远程的回复boolean _status = mRemote.transact(Stub.TRANSACTION_getUserName, _data, _reply, 0);if (!_status && getDefaultImpl() != null) {return getDefaultImpl().getUserName();}_reply.readException();_result = _reply.readString();}finally {_reply.recycle();_data.recycle();}return _result;}// Binder.javapublic final boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply,int flags) throws RemoteException {if (false) Log.v("Binder", "Transact: " + code + " to " + this);if (data != null) {data.setDataPosition(0);}// 走这里 调用远程Server端的onTransact方法boolean r = onTransact(code, data, reply, flags);if (reply != null) {reply.setDataPosition(0);}return r;}//调用远程端的onTransact方法 根据传进的code(方法名标记)调用对应的方法 写入reply 返回@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException{java.lang.String descriptor = DESCRIPTOR;switch (code){case INTERFACE_TRANSACTION:{reply.writeString(descriptor);return true;}case TRANSACTION_getUserName:{data.enforceInterface(descriptor);java.lang.String _result = this.getUserName();//这里调用远程Service的方法reply.writeNoException();reply.writeString(_result);return true;}case TRANSACTION_getUserPassword:{data.enforceInterface(descriptor);java.lang.String _result = this.getUserPassword();reply.writeNoException();reply.writeString(_result);return true;}default:{return super.onTransact(code, data, reply, flags);}}}// 之前客户端Proxy执行到这里在等待boolean _status = mRemote.transact(Stub.TRANSACTION_getUserName, _data, _reply, 0);// 服务端onTransact执行完毕后 这里可以继续执行了 得到服务端的返回

AIDL是使用binder的一个经典案例 binder本身是Android的一个非常重要的跨进程通信机制,它远比我们目前看到的复杂得多,比如它还设计ServiceManager binder.c等,比如binder的数据传输大小是有限制的,这次是跟着视频分析出来这些调用步骤的,更深入的还没有能力分析,希望以后有机会再分享更底层的binder驱动原理吧。

红橙Darren视频笔记 从AIDL Demo分析Android源码走向相关推荐

  1. 红橙Darren视频笔记 ViewGroup事件分发分析 基于API27

    本节目标,通过案例,先看程序运行结果,然后跟踪源码,理解为什么会有这样的输出,继而理解view group的分发机制,感觉和证明题很像呢. 考虑以下程序的运行结果: case1: public cla ...

  2. 红橙Darren视频笔记 Behavior的工作原理源码分析

    主要coordinatorlayout的代码来自coordinatorlayout-1.0.0-sources.jar 本文从源码介绍 CoordinatorLayout 的 behavior 怎么工 ...

  3. 红橙Darren视频笔记 UML图简介

    整体架构复制自红橙原视频的课堂笔记 因为他这一课没有博客,所以没有转载链接,CSDN没有转载地址是无法作为转载类型的文章发表的,暂时标记为原创 参考链接 https://blog.csdn.net/r ...

  4. 红橙Darren视频笔记 代理模式 动态代理和静态代理

    红橙Darren视频笔记 代理模式 动态代理和静态代理(Android API 25) 关于代理模式我之前有过相关的介绍: https://blog.csdn.net/u011109881/artic ...

  5. 红橙Darren视频笔记 类加载机制(API28) 自己写个热修复 查看源码网站

    第一部分 类加载机制 一个Activity是如何被Android虚拟机找到的? 在之前的文章 红橙Darren视频笔记 自定义View总集篇(https://blog.csdn.net/u011109 ...

  6. 红橙Darren视频笔记 利用阿里巴巴AndFix进行热修复

    注意 由于AndFix在2017年左右就停止更新了,在最新版本的apk上遇到很多问题,我最终也没有成功进行热修复.本节主要是学习热修复的原理 在上一篇 红橙Darren视频笔记 自己捕获异常并保存到本 ...

  7. 红橙Darren视频笔记 仿QQ侧滑效果

    这一篇没有什么新的内容 就是改写 红橙Darren视频笔记 仿酷狗侧滑效果 的侧滑的效果 1.去掉淡入淡出效果 2.加上黑色模板效果 效果: 去掉淡入淡出效果很简单 就是注释掉onScrollChan ...

  8. 读万卷书不如行万里路,行万里路不如阅人无数,阅人无数不如名师指路,名师指路不如自己去悟,自己去悟不如分析android源码深处...

    首先,作为一个已经学习android 一年多的人来说,如何选择android书籍,如何学习android 的app的开发,心中或多或少都有一些眉目,看了这本书的试读章节,真心感觉挺不错的.值得推荐,自 ...

  9. 如何快速阅读并分析Android源码

    很多时候为了解决一个问题必须先理解Android系统的运行原理,这时候就得阅读应用层框架的源码.学会阅读系统源码或者他人的代码,这是研发必备的技能之一,只有了解别人写的东西才能在他之上更好的行事,同时 ...

最新文章

  1. [CF1066C]Books Queries
  2. python 在地图上的散点图-Matplotlib中的散点图等高线
  3. ECharts Tooltip
  4. C++Addition rule of probabilities概率加法法则算法(附完整源码)
  5. Java中关于单核处理多个线程的认识与了解
  6. 云海技术u盘怎么恢复成普通盘_BITLOCKER加密中断数据无法读取恢复一例
  7. 护士计算机怎么报名,护士自考本科怎样报名
  8. (绝对官方好用,快速上手)针对grunt之前写的那篇有些乱,这次总结个清晰的...
  9. hadoop中遇到的问题
  10. SSH报错:packet_write_wait: Connection to xxx Broken pipe 解决
  11. global mapper加载高德在线地图
  12. java.lang.NoSuchMethodError: org.jaxen.dom4j.DocumentNavigator.getInstance()【可能的解决办法】
  13. 在Windows中安装配置JDK+Eclipse+Maven
  14. 树莓派(Raspberry Pi)安装五笔输入法,五笔拼音混合输入法
  15. 笔记本cpu和台式cpu有什么区别
  16. OSPF--DR与BDR
  17. 修改Odoo 8版权信息
  18. 如何设计接口测试用例?
  19. winpe如何给服务器安装系统,winpe系统安装在其他分区的详细教程
  20. 同盾李晓林:打造互联互通机制,化解数据安全保护与数据共享矛盾

热门文章

  1. iphone降级_ios14.2怎么降级到14.1_ios14.2降级14.1方法一览
  2. nacos 下线接口_《掌门教育微服务体系 Solar | 阿里巴巴 Nacos 企业级落地中篇》...
  3. 【重要】ionic和Angular的安装步骤
  4. 检测文件是否有BOM 头,并删除BOM头(php)
  5. 关于java和C语言i=i++问题描述
  6. [转载]博客园MetaWeblog使用帮助
  7. 深度学习——用向量重新组织输入数据
  8. 操作系统下代码设计与走读方法—业务线索法
  9. C语言-附加-给一个数求最大质数(完整代码)
  10. 二分查找——A-B数对(洛谷 P1102)