Binder
-
Binder是什么?
进程间通讯机制Binder 共享内存 Socket 性能 需要拷贝一次 无需拷贝 需要拷贝两次 特点 基于C/S 架构易用性高 控制复杂,易用性差 (同一块空间,修改了数据了之后,可能导致数据不同步,数据的同步机制可能会导致死锁等问题,开销大) 基于C/S 架构作为一款通用接口,其传输效率低,开销大 安全性 为每个APP分配UID 依赖上层协议<br />访问接入点是开放的 依赖上层协议<br />访问接入点是开放的
-
什么时候需要用到进程间通信
项目比较大型的时候
-
为什么要多进程?
虚拟机分配给各个进程的内存是有限制的,如果需要用到内存消耗大的功能的时候,主进程的容量会耗尽,容易导致OOMs
AIDL使用
定义一个AIDL文件,IPersonAidl.aidl,系统会编译生成IPersonAidl.java
interface ILeoAidl {
void addPerson(in Person person);
List<Person> getPersonList();
}
- 客户端获取AIDL的遥控器
//获取aidl对象的方法
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//IPersonAidl为定义IPersonAidl.aidl文件自动生成的java文件
iPersonAidl = IPersonAidl.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
iPersonAidl = null;
}
};
客户端:
分析生成的IPersonAidl.java中Proxy的方法,用来发送数据给服务端
private static class Proxy implements com.xx.leo_service.ILeoAidl {
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;
}
@Override
public void addPerson(com.xx.leo_service.Person person) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((person != null)) {
_data.writeInt(1);
person.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_addPerson, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public java.util.List<com.xx.leo_service.Person> getPersonList() throws android.os.RemoteException {
//发送到服务端的数据
android.os.Parcel _data = android.os.Parcel.obtain();
// 服务端返回的数据
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List<com.xx.leo_service.Person> _result;
try {
//校验是否是当前服务
_data.writeInterfaceToken(DESCRIPTOR);
//然后服务端就会调用onTransact()
mRemote.transact(Stub.TRANSACTION_getPersonList, _data, _reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(com.xx.leo_service.Person.CREATOR);
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
Binder#transact
public class Binder{
/**
* Default implementation rewinds the parcels and calls onTransact. On
* the remote side, transact calls into the binder to do the IPC.
*/
public final boolean transact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
if (false) Log.v("Binder", "Transact: " + code + " to " + this);
if (data != null) {
data.setDataPosition(0);
}
//会调用onTransact()
boolean r = onTransact(code, data, reply, flags);
if (reply != null) {
reply.setDataPosition(0);
}
return r;
}
}
服务端:
public class PersonService extends Service {
public IBinder onBind(Intent intent) {
persons = new ArrayList<>();
Log.e("LeoPersonServiceService", "success onBind");
return iBinder;
}
private IBinder iBinder = new IPersonAidl.Stub() {
@Override
public void addPerson(Person person) throws RemoteException {
persons.add(person);
}
@Override
public List<Person> getPersonList() throws RemoteException {
return persons;
}
};
}
public static abstract class Stub extends android.os.Binder implements com.xx.leo_service.IPersonAidl {
private static final java.lang.String DESCRIPTOR = "com.xx.leo_service.IPersonAidl";
/**
* 服务端Service中new Stub的时候会设置一个DESCRIPTOR
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
public static com.xx.leo_service.ILeoAidl asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
//先去查询DESCRIPTOR是否设置,如果是客户端,服务端在同一个进程,DESCRIPTOR是有值的,就能直接拿到这个服务端实例,而不需要通过Proxy,也就是通过binder去中转数据
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.xx.leo_service.IPersonAidl))) {
return ((com.xx.leo_service.IPersonAidl) iin);
}
return new com.xx.leo_service.IPersonAidl.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply,
int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_addPerson: {
data.enforceInterface(DESCRIPTOR);
com.xx.leo_service.Person _arg0;
if ((0 != data.readInt())) {
_arg0 = com.xx.leo_service.Person.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.addPerson(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_getPersonList: {
data.enforceInterface(DESCRIPTOR);
java.util.List<com.xx.leo_service.Person> _result = this.getPersonList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
那我们的客户端是如何与服务端进行通讯的呢,首先我们需要先绑定服务端Service
public class MainActivity extends Activity{
private void bindService() {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.xx.leo_service", "com.xx.leo_service.AidlService"));
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
}
ContextImpl#bindService
private class ContextImpl extend Context{
public boolean bindService( Intent service, int flags, Executor executor, ServiceConnection conn) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, null, null, executor, getUser());
}
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, String instanceName, Handler handler, Executor executor, UserHandle user) {
//...
//ActivityManager.getService()返回远程服务的代理对象:IActivityManager
int res =ActivityManager.getService().bindIsolatedService(mMainThread.getApplicationThread(), getActivityToken(), service,service.resolveTypeIfNeeded(getContentResolver()),sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
}
}
ActivityManager#getService()
public class ActivityManager{
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
// b是服务端返回的IBinder对象
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
//能看出IActivityManager是一个aidl类,am就是上面例子中的aidl对象中的Proxy:客户端,
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
}
那上面的ServiceManager.getService(Context.ACTIVITY_SERVICE)获取到的是什么对象呢?其实就是ActivityManagerService,会在ActivityManagerService#setSystemProcess方法中添加进来
ActivityManagerService#setSystemProcess
//继承自IActivityManager.Stub,说明ActivityManagerService是服务端的实现类
public class ActivityManagerService extends IActivityManager.Stub{
public void setSystemProcess() {
//将ActivityManagerService添加到ServiceManager中
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);
ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
ServiceManager.addService("meminfo", new MemBinder(this), /* allowIsolated= */ false,
DUMP_FLAG_PRIORITY_HIGH);
ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
ServiceManager.addService("dbinfo", new DbBinder(this));
if (MONITOR_CPU_USAGE) {
ServiceManager.addService("cpuinfo", new CpuBinder(this),
/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
}
ServiceManager.addService("permission", new PermissionController(this));
ServiceManager.addService("processinfo", new ProcessInfoService(this));
}
}
ActivityManager#getService()
返回的类型是 IActivityManager
类型,拿到远程服务的Binder
对象,其中IActivityManager.Stub.asInterface(b)
就是拿到远程服务的代理对象:IActivityManager
,通过代理对象调用远程的方法,是应用进程与服务进程通信的媒介,IActivityManager#bindIsolatedService
最终会调用到ActivityManagerService#bindIsolatedService
ActivityManagerService#bindIsolatedService
public int bindIsolatedService(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, int flags, String instanceName,
String callingPackage, int userId) throws TransactionTooLargeException {
//...省略
synchronized(this) {
return mServices.bindServiceLocked(caller, token, service,
resolvedType, connection, flags, instanceName, callingPackage, userId);
}
}
ActivityServices#bindServiceLocked
public class ActivityServices{
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String callingPackage, final int userId) {
//...省略
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent,
callerApp.uid, callerApp.processName, callingPackage);
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
//注释1:调用bringUpServiceLocked,创建服务,具体看1.1
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}
if (s.app != null && b.intent.received) {
// Service is already running, so we can immediately
// publish the connection.
try {
// 具体看2.1 -- c.conn => IServiceConnection.java ,最终会调用到客户端new ServiceConnection的onServiceConnected方法,将服务端的自己创建的IBinder对象传递过去
//b.intent.binder = 从服务端获取的binder对象
c.conn.connected(s.name, b.intent.binder, false);
}
//如果已经绑定过了,requestServiceBindingLocked最后一个参数(rebind)为true
if (b.intent.apps.size() == 1 && b.intent.doRebind) {
//注释3: -- 具体看3.1 调用requestServiceBindingLocked
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
//如果没有绑定过最后一个参数为false
} else if (!b.intent.requested) {
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
}
1.1ActivityServices#bringUpServiceLocked
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired) {
//...省略
ProcessRecord app
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
//app.thread => ApplicationThread,因为一个进程启动就会走ActivityThread的main方法,会创建ApplicationThread,如果app.thread不为空,说明已经创建了另一个进程,app服务端Service已经启动了,b进程已经启动了,直接绑定服务就行了realStartServiceLocked
if (app != null && app.thread != null) {
app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
//调用realStartServiceLocked,具体看1.2
realStartServiceLocked(r, app, execInFg);
return null;
}
}
//1.3 如果进程B未启动,调用startProcessLocked,启动一个进程,
if (app == null && !permissionsReviewRequired) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingType, r.name, false, isolated, false)) == null) {
bringDownServiceLocked(r);
return msg;
}
if (isolated) {
r.isolatedProc = app;
}
}
}
1.2ActivityServices#realStartServiceLocked
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg){
//...省略
//1.2.1 app.thread = ApplicationThread,调用ApplicationThread的scheduleCreateService方法,创建service
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
}
1.3ActivityManagerService#startProcessLocked
//开启一个进程
private boolean startProcessLocked(...){
final String entryPoint = "android.app.ActivityThread";
startProcess(entryPoint,...);
}
private ProcessStartResult startProcess(){
final ProcessStartResult startResult;
if (hostingType.equals("webview_service")) {
startResult = startWebView(entryPoint,...);
} else {
//通过ZygoteProcess启动一个进程 entryPoint = "android.app.ActivityThread"
startResult = Process.start(entryPoint,..);
}
}
1.2.1ApplicationThread#scheduleCreateService
public final void scheduleCreateService(IBinder token,
ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
CreateServiceData s = new CreateServiceData();
//发送一个CREATE_SERVICE消息,会在ActivityThread.H中处理
sendMessage(H.CREATE_SERVICE, s);
}
class H extends Handler {
public void handleMessage(Message msg) {
case CREATE_SERVICE:
//接收到CREATE_SERVICE消息后,创建服务
handleCreateService((CreateServiceData)msg.obj);
break;
}
private void handleCreateService(CreateServiceData data) {
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
java.lang.ClassLoader cl = packageInfo.getClassLoader();
//反射创建service
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
Application app = packageInfo.makeApplication(false, mInstrumentation);
//调用service的attach(),onCreate()
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
service.onCreate();
mServices.put(data.token, service);
}
}
2.1 IServiceConnection#connected
IServiceConnection
是一个aidl的类,那么这个实现类是如何创建的呢,回到客户端中ServiceConnection
通过bindService传递,会将ServiceConnection
转化为IServiceConnection
public class MainActivity extends Activity{
public void onCreate(){
//传递自己创建的connection到bindService()中
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
}
ContextImpl#bindServiceCommon
final @NonNull LoadedApk mPackageInfo;
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
IServiceConnection sd;
if (mPackageInfo != null) {
//sd就是上面2.1步骤用到的c.conn,将自己创建的ServiceConnection通过LoadedApk#getServiceDispatcher(conn)得到,那我们看一下sd的创建过程
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
} else {
throw new RuntimeException("Not supported in system context");
}
}
LoadedApk#getServiceDispatcher()
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Handler handler, int flags) {
LoadedApk.ServiceDispatcher sd = null;
if (sd == null) {
//创建ServiceDispatcher,将ServiceConnection当做参数传递
sd = new ServiceDispatcher(c, context, handler, flags);
} else {
sd.validate(context, handler);
}
//返回IServiceConnection
return sd.getIServiceConnection();
}
ServiceDispatcher的类结构,查看IServiceConnection的创建过程,ServiceDispatcher
是LoadApk
的内部类
static final class ServiceDispatcher{
ServiceDispatcher(ServiceConnection conn,
Context context, Handler activityThread, int flags) {
//IServiceConnection = InnerConnection
mIServiceConnection = new InnerConnection(this);
//mConnection = 我们自己创建的ServiceConnection
mConnection = conn;
}
IServiceConnection getIServiceConnection() {
//返回IServiceConnection,也就是构造方法中创建的InnerConnection,所以上边c.conn.connected,就是调用
//LoadApk#InnerConnection.connected()
return mIServiceConnection;
}
}
InnerConnection#connected
//InnerConnection继承了IServiceConnection.Stub,说明这个InnerConnection相当于服务端实现
private static class InnerConnection extends IServiceConnection.Stub {
public void connected(ComponentName name, IBinder service, boolean dead){
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
//调用了LoadedApk.ServiceDispatcher#connected
sd.connected(name, service, dead);
}
}
}
LoadedApk.ServiceDispatcher#connected
public void connected(ComponentName name, IBinder service, boolean dead) {
if (mActivityThread != null) {
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 (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);
}
//mConnection=>构造方法传递的ServiceConnection,所以最终会调用我们自己创建的ServiceConnection的onServiceConnected方法,并将IBinder对象传递
if (service != null) {
mConnection.onServiceConnected(name, service);
} else {
// The binding machinery worked, but the remote returned null from onBind().
mConnection.onNullBinding(name);
}
}
3.1ActivityServices#requestServiceBindingLocked
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 ((!i.requested || rebind) && i.apps.size() > 0) {
try {
bumpServiceExecutingLocked(r, execInFg, "bind");
r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
//rebind==true,调用Application#scheduleBindService,绑定服务
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.repProcState);
if (!rebind) {
i.requested = true;
}
i.hasBound = true;
i.doRebind = false;
}
}
return true;
}
Application#scheduleBindService
public final void scheduleBindService(IBinder token, Intent intent,
boolean rebind, int processState) {
BindServiceData s = new BindServiceData();
//发送一个BIND_SERVICE消息,会在ActivityThread.H处理,会绑定服务
sendMessage(H.BIND_SERVICE, s);
}
public class ActivityThread{
public void handleMessage(Message msg) {
case BIND_SERVICE:
//接收到BIND_SERVICE消息后,绑定服务
handleBindService((BindServiceData)msg.obj);
break;
}
private void handleBindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (s != null) {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
if (!data.rebind) {
//调用我们自己创建的xxxService的onBind方法,onBind中会返回我们自己创建的 IBinder iBinder = new ILeoAidl.Stub()
IBinder binder = s.onBind(data.intent);
//调用ActivityManagerService当中的publishService方法
ActivityManager.getService().publishService(data.token, data.intent, binder);
} else {
s.onRebind(data.intent);
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
}
}
ActivityManagerService#publishService
public void publishService(IBinder token, Intent intent, IBinder service) {
synchronized(this) {
//调用ActiveServicecs的publishServiceLocked方法
mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}
}
ActiveServicecs#publishServiceLocked
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
if (r != null) {
Intent.FilterComparison filter
= new Intent.FilterComparison(intent);
IntentBindRecord b = r.bindings.get(filter);
if (b != null && !b.received) {
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);
// c.conn => IServiceConnection.java ,上面分析了最终会调用到客户端new ServiceConnection的onServiceConnected方法,将服务端的自己创建的IBinder对象传递过去
c.conn.connected(r.name, service, false);
}
}
}
serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
}
}
最后附上一张时序图
BindService.jpg
网友评论