一 AIDL demo
1.1 服务端搭建
新建AIDL文件
// IUserCalc.aidl
package com.example.aidlserver;
// Declare any non-default types here with import statements
interface 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
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG, "onBind: ");
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
Log.e(TAG, "onUnbind: ");
return super.onUnbind(intent);
}
private final IUserCalc.Stub mBinder = new IUserCalc.Stub() {
@Override
public String getUserName() throws RemoteException {
Log.e(TAG, "getUserName: ");
return "hjcai";
}
@Override
public 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">
<application
android: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>
<service
android: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() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e(TAG, "onServiceConnected: ");
mCalcAidl = IUserCalc.Stub.asInterface(service);
}
@Override
public 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">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="bind"
android:text="bind" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="unBind"
android:text="unbind" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="getName"
android:text="getName" />
<Button
android: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";
@Override
protected 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: hjcai
2021-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: 12341234
2021-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回调中 将存根类转换为代理类
@Override
public 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
// activity
context.bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE);
// ContextWrapper.java
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
// Context的具体实现类是ContextImpl
// ContextImpl.java
@Override
public 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, Handler
handler, 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.java
public static IActivityManager getService() {
// 结合下面的IActivityManagerSingleton赋值代码 可知getService返回的是包装好的IBinder的IActivityManager对象
return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected 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 descriptors
if (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.java
int 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.java
IApplicationThread 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.java
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;
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方法 第一个目标达成!!!!!!!!!1
IBinder binder = s.onBind(data.intent);
// 前面我们知道IActivityManager是一个接口 其实现类是ActivityManagerService
// 因此我们知道publishService具体实现在ActivityManagerService
ActivityManager.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.java
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);
}
}
// ActiveService.java
void 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.java
final IServiceConnection conn; //这东西看起来有些熟悉 我们在ContextImpl中看到过
// ContextImpl.java
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, 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.java
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) {
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.java
public abstract boolean bindService(@RequiresPermission Intent service,
@NonNull ServiceConnection conn, @BindServiceFlags int flags);
//ContextImpl.java (Context.java实现类)
@Override
public 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, Handler
handler, 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.java
public 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.java
int 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.java
IApplicationThread 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;
//跟进handleBindService
private void handleBindService(BindServiceData data) {
IBinder binder = s.onBind(data.intent);
//!!!!!!!
//第一步达成!!onBind被调用
//前面我们分析 ActivityManager.getService()返回的对象就是ActivityManagerService
ActivityManager.getService().publishService(
data.token, data.intent, binder);
}
//查看ActivityManagerService的publishService
//ActivityManagerService
public void publishService(IBinder token, Intent intent, IBinder service) {
...
mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}
}
//ActiveServices
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
c.conn.connected(r.name, service, false);
}
//想知道connected方法内容 需要知道conn的真实对象
//ConnectionRecord
final IServiceConnection conn;
//IServiceConnection在ContextImpl中出现过
IServiceConnection sd;
//它具体的赋值在
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
//LoadedApk.java
public 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.connected
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) {
...
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;
}
@Override
public 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()
{
// 关联指定接口和Binder
this.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);
}
// 跨进程case
return 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.java
public 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驱动原理吧。