进程间通信基本原理
进程间通信原理
Binder是什么?
IPC(Inter-Process Communication 进程间通信)通信机制
什么时候需要用到进程间通信?
WebView访问,图片加载(下载),推送,双进程守护
系统进程(获取输入法服务,闹钟服务,摄相头服务,电话等)
为什么要多进程?
每个进程的内存是有限制的,在主进程中进行图片加载、下载内存容易耗尽产生OOM, 而且下载机制很容易出错,出错也会影响主进程。
进程间通信为什么要用到Binder机制?
内存划分
进程间的用户空间是进程隔离的,内核空间是共享空间。一般32位系统, 内核空间为1G,用户空间为3G。一个进程空间4G。
用户空间可以通过内核空间进行访问。
Binder的作用和使用场景
Binder作用就是来实现进程之间通过内核空间实现通信的。
安卓增加Binder的原因
Binder与传统IPC对比
Binder | 共享内存 | Socket | |
---|---|---|---|
性能 | 需要拷贝一次 | 无需拷贝 | 需要拷贝两次 |
特点 | 基于C/S 架构 易用性高 | 控制复杂,易用性差 | 基于C/S 架构 作为一款通用接口,其传输效率低,开销大 |
安全性 | 为每个APP分配UID 同时支持实名和匿名 | 依赖上层协议 访问接入点是开放的 不安全 | 依赖上层协议 访问接入点是开放的 不安全 |
性能
Binder只需要拷贝一次;共享内存无需拷贝;Socket需要拷贝两次
特点
Binder基于C/S架构,易用性高;共享内存控制复杂,易用性差;Socket基于C/S架构作为一款通用接口,传输效率低,开销大
安全性
Binder 为每个APP分配 UID同时支持实名和匿名;共享内存依赖上层协议,访问接入点是开放的,不安全;Socket 依赖上层协议,访问接入点是开放的,不安全
传统 IPC 传输数据
- 用户空间发送数据
- 通过系统调用copy_from_user()将数据从用户空间copy到内核缓存区(第1次copy)
- 另一个进程中:通过调用copy_from_user()将数据从内核缓存空间copy到用户空间(第2次copy)
- 接收数据
Binder 传输数据
- 用户空间发送数据
- 通过系统调用copy_from_user()将数据从用户空间copy到内核缓存区
- 因为存在映射关系(mmap内存映射将一个文件或者其它对象映射进内存),所以实现了跨进程通信
(内核缓存区和S端(接收端)的数据接收缓存区 映射同一块物理空间)
Binder源码分析
AIDL
AIDL: (Android Interface Definition Language) Android接口定义语言
每个服务都有个aidl与之对应。
Proxy:发送数据(客户端)
Stub:接收数据(服务端)
客户端:
在ServiceConnection中
获取aidl对象的方法(XXXAidl是定义的AIDL)
XXXAidl.Stub.asInterface(service);
asInterface跳转到了Stub中的asInterface方法
Stub继承了Binder并实现了aidl接口
public static abstract class Stub extends android.os.Binder implements com.lis.binder_learn.Aidl {
private static final java.lang.String DESCRIPTOR = "com.lis.binder_learn.Aidl";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.lis.binder_learn.Aidl interface,
* generating a proxy if needed.
*/
public static com.lis.binder_learn.Aidl asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.lis.binder_learn.Aidl))) {
return ((com.lis.binder_learn.Aidl) iin);
}
return new com.lis.binder_learn.Aidl.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 {
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(descriptor);
return true;
}
case TRANSACTION_addPerson: {
data.enforceInterface(descriptor);
com.lis.binder_learn.Person _arg0;
if ((0 != data.readInt())) {
_arg0 = com.lis.binder_learn.Person.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.addPerson(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_getPersonList: {
data.enforceInterface(descriptor);
java.util.List _result = this.getPersonList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
asInterface方法中queryLocalInterface是Binder.java中实现
public @Nullable IInterface queryLocalInterface(@NonNull String descriptor) {
if (mDescriptor != null && mDescriptor.equals(descriptor)) {
return mOwner;
}
return null;
}
在Stub的构造方法中,将自身和DESCRIPTOR(com.lis.binder_learn.Aidl 全类名)传到了Binder.java中
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
public void attachInterface(@Nullable IInterface owner, @Nullable String descriptor) {
mOwner = owner;
mDescriptor = descriptor;
}
所以queryLocalInterface方法是查询保存到本地的descriptor是否相等,相等就返回了自身Aidl
但是客户端这里是不相等的,因为客服端没有调用Stub的构造承当,这里的传入的descriptor是个空。
(这一块是在服务端进行传入的Stub)
客服端不会始化Stub不传descriptor,服务端会初始化Stub传descriptor。
这里的查询比较是因为:Activity和Service有可能是同一进程当中的,如果是同一进程就不需要进行binder进行传输了。
if (((iin != null) && (iin instanceof com.lis.binder_learn.Aidl))) {
return ((com.lis.binder_learn.Aidl) iin);
}
return new com.lis.binder_learn.Aidl.Stub.Proxy(obj);
这里如果是同一进程就直接返回aidl,如果不是同一进程就返回了Proxy。
mAidl = Aidl.Stub.asInterface(service);
这里客户端就拿到了proxy(mAidl)
mAidl.addPerson(new Person("张三", 1));
调用mAidl的方法,就进了Proxy中的方法中
Proxy是个实体类实现了aidl接口
private static class Proxy implements com.lis.binder_learn.Aidl {
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.lis.binder_learn.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);
}
boolean _status = mRemote.transact(Stub.TRANSACTION_addPerson, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().addPerson(person);
return;
}
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public java.util.List getPersonList() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_getPersonList, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().getPersonList();
}
_reply.readException();
_result = _reply.createTypedArrayList(com.lis.binder_learn.Person.CREATOR);
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
public static com.lis.binder_learn.Aidl sDefaultImpl;
}
_data就是发送到服务端的数据
_reply就是服务端返回的数据
@Override
public void addPerson(com.lis.binder_learn.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);
}
boolean _status = mRemote.transact(Stub.TRANSACTION_addPerson, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().addPerson(person);
return;
}
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
这里做了个数据的校验
_data.writeInterfaceToken(DESCRIPTOR);
通过mRemote.transact方法,将数据发送给服务端,这时客户端线程挂起,直到服务端数据返回。这里的flags=0表示,客户端和服务端可以想到通信,1的话代表客户端发到服务端,服务端不能返回。
Stub.TRANSACTION_addPerson:因为客户端和服务端的AIDL是一样的,所以方法顺序是一样的。这里传入方法顺序数,就可以知道调用的哪个方法(整型)
boolean _status = mRemote.transact(Stub.TRANSACTION_addPerson, _data, _reply, 0);
transact方法在Binder.java中,调用 onTransact
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);
}
boolean r = onTransact(code, data, reply, flags);
if (reply != null) {
reply.setDataPosition(0);
}
return r;
}
这里会到服务端的Stub#onTransact方法
服务端:
@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_addPerson: {
data.enforceInterface(descriptor);
com.lis.binder_learn.Person _arg0;
if ((0 != data.readInt())) {
_arg0 = com.lis.binder_learn.Person.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.addPerson(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_getPersonList: {
data.enforceInterface(descriptor);
java.util.List _result = this.getPersonList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
根据code 找到调用的哪个方法case TRANSACTION_addPerson
data.enforceInterface(descriptor);
这里根据descriptor进行校验
this.addPerson(_arg0);
这里的addPerson调用的是Service中实现的Stub()中addPerson方法
private IBinder mIBinder = new Aidl.Stub() {
@Override
public void addPerson(Person person) throws RemoteException {
persons.add(person);
Log.e("AidlService", "persons.size: "+persons.size());
}
@Override
public List getPersonList() throws RemoteException {
Log.e("AidlService", "getPersonList.size: "+persons.size());
return persons;
}
};
AIDL时序图:
最后通过_reply进行数据返回
如何获得另一个进程的对象
bindService中都 做了些什么?
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
最后调用了ContextImpl.bindService
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null,
getUser());
}
bindServiceCommon
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
String instanceName, Handler handler, Executor executor, UserHandle user) {
// Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (handler != null && executor != null) {
throw new IllegalArgumentException("Handler and Executor both supplied");
}
if (mPackageInfo != null) {
if (executor != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags);
} else {
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);
int res = ActivityManager.getService().bindIsolatedService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, instanceName, 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();
}
}
//基于23的代码
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
static public IActivityManager getDefault() {
return gDefault.get();
}
public interface IActivityManager extends IInterface
IActivityManager继承自IInterface
public interface IInterface
{
/**
* Retrieve the Binder object associated with this interface.
* You must use this instead of a plain cast, so that proxy objects
* can return the correct result.
*/
public IBinder asBinder();
}
这样,IActivityManager=AIDL接口
private static final Singleton gDefault = new Singleton() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
IBinder b = ServiceManager.getService("activity");
这里ServiceManager把我们调用的服务的IBinder返回。(这个IBinder就是AMS服务)
IActivityManager am = asInterface(b);
通过asInterface 返回 ,这里的am就是Proxy
就是ActivityManagerNative.getDefault()
这里返回一个Proxy对象
asInterface会跑到Stub中去
public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
/**
* Cast a Binder object into an activity manager interface, generating
* a proxy if needed.
*/
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ActivityManagerProxy(obj);
}
...
所以ActivityManagerNative 就是Stub
即:ActivityManagerNative== Stub
ActivityManagerNative$ActivityManagerProxy == Proxy
ActivityManagerProxy #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;
}
mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
跳到ActivityManagerNative#onTransact方法
case BIND_SERVICE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
IBinder token = data.readStrongBinder();
Intent service = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
b = data.readStrongBinder();
int fl = data.readInt();
String callingPackage = data.readString();
int userId = data.readInt();
IServiceConnection conn = IServiceConnection.Stub.asInterface(b);
int res = bindService(app, token, service, resolvedType, conn, fl,
callingPackage, userId);
reply.writeNoException();
reply.writeInt(res);
return true;
}
bindService(app, token, service, resolvedType, conn, fl,callingPackage, userId);
这里的bindService是调用的真正的服务Service(这里使用的AMS服务)
public final class ActivityManagerService extends ActivityManagerNative
ActivityManagerService#bindService ====>ActivityManagerService#bindServiceLocked
-
ActivityServices#bringUpServiceLocked()
进程状态的1,2
-
ActivityServices#requestServiceBindingLocked(s, b.intent, callerFg, true);
进程状态的3,4
A进程访问B进程时的几种状态
bringUpServiceLocked()
2. app存在,但是Service没创建
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
+ " app=" + app);
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);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
}
app创建了
if (app != null && app.thread != null) ` 代表B进程已经启动
realStartServiceLocked(r, app, execInFg);
启动服务
realStartServiceLocked中
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
这里的app是应用进程,thread是ApplicationThread(ActivityThread#ApplicationThread)
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);
}
进到了Handler
case CREATE_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
创建服务的方法handleCreateService
private void handleCreateService(CreateServiceData data) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
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) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to instantiate service " + data.info.name
+ ": " + e.toString(), e);
}
}
try {
if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
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) {
// nothing to do.
}
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to create service " + data.info.name
+ ": " + e.toString(), e);
}
}
}
service = (Service) cl.loadClass(data.info.name).newInstance();
--->AidlService 创建了我们的服务(通过类加载器,反射创建)
调用service生命周期,保存服务
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault());
service.onCreate();
mServices.put(data.token, service);
1. 进程没有启动
app没有创建
if (app == null) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
"service", r.name, false, isolated, false)) == null) {
String msg = "Unable to launch app "
+ r.appInfo.packageName + "/"
+ r.appInfo.uid + " for service "
+ r.intent.getIntent() + ": process is bad";
Slog.w(TAG, msg);
bringDownServiceLocked(r);
return msg;
}
if (isolated) {
r.isolatedProc = app;
}
}
进入到startProcessLocked中的
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);
创建进程
requestServiceBindingLocked
绑定服务:
requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind)
绑定与否 和rebind有关,走的同一个方法
try {
bumpServiceExecutingLocked(r, execInFg, "bind");
r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.repProcState);
if (!rebind) {
i.requested = true;
}
i.hasBound = true;
i.doRebind = false;
}
调用scheduleBindService方法==》ActivityThread#scheduleBindService
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());
sendMessage(H.BIND_SERVICE, s);
}
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) {
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) {
}
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to bind to service " + s
+ " with " + data.intent + ": " + e.toString(), e);
}
}
}
}
IBinder binder = s.onBind(data.intent);
binder是调用的是AidlService中的onBind()返回的binder
public class AidlService extends Service {
private ArrayList persons;
@Nullable
@Override
public IBinder onBind(Intent intent) {
persons = new ArrayList<>();
Log.e("AidlService", "success onBind");
return mIBinder;
}
...
}
ActivityManagerNative.getDefault().publishService(
data.token, data.intent, binder);
ActivityManagerNative.getDefault()==>Proxy==>AMS中的publishService
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.publishServiceLocked((ServiceRecord)token, intent, service);
publishServiceLocked中
try {
c.conn.connected(r.name, service);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + r.name +
" to connection " + c.conn.asBinder() +
" (in " + c.binding.client.processName + ")", e);
}
c.conn.connected(r.name, service);==>调用到客户端的onServiceConnected()
参数就是服务端的IBinder
ConnectionRecord c
IServiceConnection conn
客户端:
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
bindService时传入了ServiceConnection-->ContextImp#bindServiceCommon
IServiceConnection sd;
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
mMainThread.getHandler(), flags);
}
这里传入了conn
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Handler handler, int flags) {
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
ArrayMap 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();
mServices.put(context, map);
}
map.put(c, sd);
} else {
sd.validate(context, handler);
}
return sd.getIServiceConnection();
}
}
sd = new ServiceDispatcher(c, context, handler, flags);
这里传入了ServiceConnection,最后从sd.getIServiceConnection() 返回IServiceConnection
IServiceConnection getIServiceConnection() {
return mIServiceConnection;
}
private final ServiceDispatcher.InnerConnection mIServiceConnection;
这里返回的是个InnerConnection对象
private static class InnerConnection extends IServiceConnection.Stub {
final WeakReference mDispatcher;
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference(sd);
}
public void connected(ComponentName name, IBinder service) throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service);
}
}
}
上面的c.conn.connected就是调用的InnerConnection#connected方法,
而这个方法又调用了sd.connected
public void connected(ComponentName name, IBinder service) {
if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0));
} else {
doConnected(name, service);
}
}
public void doConnected(ComponentName name, IBinder service) {
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.
mDied = false;
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 not disconnected.
if (old != null) {
mConnection.onServiceDisconnected(name);
}
// If there is a new service, it is now connected.
if (service != null) {
mConnection.onServiceConnected(name, service);
}
}
// If there was an old service, it is not disconnected.
if (old != null) {
mConnection.onServiceDisconnected(name);
}
// If there is a new service, it is now connected.
if (service != null) {
mConnection.onServiceConnected(name, service);
}
这里就调到了connection的方法。
所以上面c.conn.connected(r.name, service)就是调用的ServiceConnection的onServiceConnected方法。
如何进行通信的
总结
PS:进程知识补充
进程分为:
- 前台进程
- 可见进程
- 服务进程
- 后台进程
- 空进程
前台进程:
有一个Activity
- 正在交互
有一个Service
- 绑定到正在交互的Activity
- “前台运行”,startForeground()
- 正在执行生命周期回调onCreate()
有一个BroadcastReceiver
- 正在执行onReceive()
可见进程:
有一个Activity
- 不在交互,但仍可见
有一个Service
- 绑定到可见Activity
服务进程:
- 普通Service
故而对耗时的比如上传等,新建一个Service比在Activity新建一个线程好的多。
后台进程:
- 所有Activity都对用户不可见
会被保存在LRU列表中,即最近查看的最晚被终止
空进程:
系统有时候会使用空进程做为缓存,以缩短下一次在其中运行组建所需的启动时间
多进程的特性
- 不同的内存空间,数据无法共享
- 需要谨慎处理代码中的线程同步
- 需要提防多进程并发导致的文件锁和数据库锁时效的问题
具体问题:
1. 静态成员和单例模式完全失效
2. 线程同步机制失效
3. SharedPreferences可靠性下降
4. Application会多次重建
如何判断进程的优先级
通过oom_adj 值,判断进程的优先级
不同手机的oom_adj 值 可能不一样
进程间通信方式
线程间通信
- 共享内存
- 文件、数据库
- Handler
- Java里的wait notify notifyAll
在非UI线程中更新UI
- Activity.runOnUiThread(Runnable)
- View.post(Runnable)
- View.postDelayed(Runnable,long)
- handler
- AsyncTask