進(jìn)程間通信基本原理
進(jìn)程間通信原理
Binder是什么帮非?
IPC(Inter-Process Communication 進(jìn)程間通信)通信機(jī)制
什么時候需要用到進(jìn)程間通信刮便?
WebView訪問,圖片加載(下載)蓄诽,推送薛训,雙進(jìn)程守護(hù)
系統(tǒng)進(jìn)程(獲取輸入法服務(wù),鬧鐘服務(wù)仑氛,攝相頭服務(wù)乙埃,電話等)
為什么要多進(jìn)程?
每個進(jìn)程的內(nèi)存是有限制的锯岖,在主進(jìn)程中進(jìn)行圖片加載介袜、下載內(nèi)存容易耗盡產(chǎn)生OOM, 而且下載機(jī)制很容易出錯出吹,出錯也會影響主進(jìn)程遇伞。
進(jìn)程間通信為什么要用到Binder機(jī)制?
內(nèi)存劃分
進(jìn)程間的用戶空間是進(jìn)程隔離的趋箩,內(nèi)核空間是共享空間赃额。一般32位系統(tǒng)加派, 內(nèi)核空間為1G叫确,用戶空間為3G。一個進(jìn)程空間4G芍锦。
用戶空間可以通過內(nèi)核空間進(jìn)行訪問竹勉。
Binder的作用和使用場景
Binder作用就是來實(shí)現(xiàn)進(jìn)程之間通過內(nèi)核空間實(shí)現(xiàn)通信的。
安卓增加Binder的原因
Binder與傳統(tǒng)IPC對比
Binder | 共享內(nèi)存 | Socket | |
---|---|---|---|
性能 | 需要拷貝一次 | 無需拷貝 | 需要拷貝兩次 |
特點(diǎn) | 基于C/S 架構(gòu) 易用性高 | 控制復(fù)雜娄琉,易用性差 | 基于C/S 架構(gòu) 作為一款通用接口次乓,其傳輸效率低,開銷大 |
安全性 | 為每個APP分配UID 同時支持實(shí)名和匿名 | 依賴上層協(xié)議 訪問接入點(diǎn)是開放的 不安全 | 依賴上層協(xié)議 訪問接入點(diǎn)是開放的 不安全 |
性能
Binder只需要拷貝一次孽水;共享內(nèi)存無需拷貝票腰;Socket需要拷貝兩次
特點(diǎn)
Binder基于C/S架構(gòu),易用性高女气;共享內(nèi)存控制復(fù)雜杏慰,易用性差;Socket基于C/S架構(gòu)作為一款通用接口,傳輸效率低缘滥,開銷大
安全性
Binder 為每個APP分配 UID同時支持實(shí)名和匿名轰胁;共享內(nèi)存依賴上層協(xié)議,訪問接入點(diǎn)是開放的朝扼,不安全赃阀;Socket 依賴上層協(xié)議,訪問接入點(diǎn)是開放的擎颖,不安全
傳統(tǒng) IPC 傳輸數(shù)據(jù)
- 用戶空間發(fā)送數(shù)據(jù)
- 通過系統(tǒng)調(diào)用copy_from_user()將數(shù)據(jù)從用戶空間copy到內(nèi)核緩存區(qū)(第1次copy)
- 另一個進(jìn)程中:通過調(diào)用copy_from_user()將數(shù)據(jù)從內(nèi)核緩存空間copy到用戶空間(第2次copy)
- 接收數(shù)據(jù)
Binder 傳輸數(shù)據(jù)
- 用戶空間發(fā)送數(shù)據(jù)
- 通過系統(tǒng)調(diào)用copy_from_user()將數(shù)據(jù)從用戶空間copy到內(nèi)核緩存區(qū)
- 因?yàn)榇嬖谟成潢P(guān)系(mmap內(nèi)存映射將一個文件或者其它對象映射進(jìn)內(nèi)存)榛斯,所以實(shí)現(xiàn)了跨進(jìn)程通信
(內(nèi)核緩存區(qū)和S端(接收端)的數(shù)據(jù)接收緩存區(qū) 映射同一塊物理空間)
Binder源碼分析
AIDL
AIDL: (Android Interface Definition Language) Android接口定義語言
每個服務(wù)都有個aidl與之對應(yīng)。
Proxy:發(fā)送數(shù)據(jù)(客戶端)
Stub:接收數(shù)據(jù)(服務(wù)端)
客戶端:
在ServiceConnection中
獲取aidl對象的方法(XXXAidl是定義的AIDL)
XXXAidl.Stub.asInterface(service);
asInterface跳轉(zhuǎn)到了Stub中的asInterface方法
Stub繼承了Binder并實(shí)現(xiàn)了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<com.lis.binder_learn.Person> _result = this.getPersonList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
asInterface方法中queryLocalInterface是Binder.java中實(shí)現(xiàn)
public @Nullable IInterface queryLocalInterface(@NonNull String descriptor) {
if (mDescriptor != null && mDescriptor.equals(descriptor)) {
return mOwner;
}
return null;
}
在Stub的構(gòu)造方法中,將自身和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
但是客戶端這里是不相等的肖抱,因?yàn)榭头藳]有調(diào)用Stub的構(gòu)造承當(dāng),這里的傳入的descriptor是個空异旧。
(這一塊是在服務(wù)端進(jìn)行傳入的Stub)
客服端不會始化Stub不傳descriptor意述,服務(wù)端會初始化Stub傳descriptor。
這里的查詢比較是因?yàn)椋?/strong>Activity和Service有可能是同一進(jìn)程當(dāng)中的吮蛹,如果是同一進(jìn)程就不需要進(jìn)行binder進(jìn)行傳輸了荤崇。
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);
這里如果是同一進(jìn)程就直接返回aidl,如果不是同一進(jìn)程就返回了Proxy。
mAidl = Aidl.Stub.asInterface(service);
這里客戶端就拿到了proxy(mAidl)
mAidl.addPerson(new Person("張三", 1));
調(diào)用mAidl的方法潮针,就進(jìn)了Proxy中的方法中
Proxy是個實(shí)體類實(shí)現(xiàn)了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<com.lis.binder_learn.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.lis.binder_learn.Person> _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就是發(fā)送到服務(wù)端的數(shù)據(jù)
_reply就是服務(wù)端返回的數(shù)據(jù)
@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();
}
}
這里做了個數(shù)據(jù)的校驗(yàn)
_data.writeInterfaceToken(DESCRIPTOR);
通過mRemote.transact方法术荤,將數(shù)據(jù)發(fā)送給服務(wù)端,這時客戶端線程掛起每篷,直到服務(wù)端數(shù)據(jù)返回瓣戚。這里的flags=0表示,客戶端和服務(wù)端可以想到通信焦读,1的話代表客戶端發(fā)到服務(wù)端子库,服務(wù)端不能返回。
Stub.TRANSACTION_addPerson:因?yàn)榭蛻舳撕头?wù)端的AIDL是一樣的矗晃,所以方法順序是一樣的仑嗅。這里傳入方法順序數(shù),就可以知道調(diào)用的哪個方法(整型)
boolean _status = mRemote.transact(Stub.TRANSACTION_addPerson, _data, _reply, 0);
transact方法在Binder.java中张症,調(diào)用 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;
}
這里會到服務(wù)端的Stub#onTransact方法
服務(wù)端:
@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<com.lis.binder_learn.Person> _result = this.getPersonList();
reply.writeNoException();
reply.writeTypedList(_result);
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
根據(jù)code 找到調(diào)用的哪個方法case TRANSACTION_addPerson
data.enforceInterface(descriptor);
這里根據(jù)descriptor進(jìn)行校驗(yàn)
this.addPerson(_arg0);
這里的addPerson調(diào)用的是Service中實(shí)現(xiàn)的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<Person> getPersonList() throws RemoteException {
Log.e("AidlService", "getPersonList.size: "+persons.size());
return persons;
}
};
AIDL時序圖:
最后通過_reply進(jìn)行數(shù)據(jù)返回
如何獲得另一個進(jìn)程的對象
bindService中都 做了些什么仓技?
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
最后調(diào)用了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<IActivityManager> gDefault = new Singleton<IActivityManager>() {
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把我們調(diào)用的服務(wù)的IBinder返回俗他。(這個IBinder就是AMS服務(wù))
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是調(diào)用的真正的服務(wù)Service(這里使用的AMS服務(wù))
public final class ActivityManagerService extends ActivityManagerNative
ActivityManagerService#bindService ====>ActivityManagerService#bindServiceLocked
-
ActivityServices#bringUpServiceLocked()
進(jìn)程狀態(tài)的1,2
-
ActivityServices#requestServiceBindingLocked(s, b.intent, callerFg, true);
進(jìn)程狀態(tài)的3兆衅,4
A進(jìn)程訪問B進(jìn)程時的幾種狀態(tài)
bringUpServiceLocked()
2. app存在地沮,但是Service沒創(chuàng)建
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創(chuàng)建了
if (app != null && app.thread != null) ` 代表B進(jìn)程已經(jīng)啟動
realStartServiceLocked(r, app, execInFg);
啟動服務(wù)
realStartServiceLocked中
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
這里的app是應(yīng)用進(jìn)程颜价,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);
}
進(jìn)到了Handler
case CREATE_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
創(chuàng)建服務(wù)的方法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 創(chuàng)建了我們的服務(wù)(通過類加載器,反射創(chuàng)建)
調(diào)用service生命周期诉濒,保存服務(wù)
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault());
service.onCreate();
mServices.put(data.token, service);
1. 進(jìn)程沒有啟動
app沒有創(chuàng)建
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;
}
}
進(jìn)入到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);
創(chuàng)建進(jìn)程
requestServiceBindingLocked
綁定服務(wù):
requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind)
綁定與否 和rebind有關(guān)周伦,走的同一個方法
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;
}
調(diào)用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是調(diào)用的是AidlService中的onBind()返回的binder
public class AidlService extends Service {
private ArrayList<Person> 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);==>調(diào)用到客戶端的onServiceConnected()
參數(shù)就是服務(wù)端的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<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
if (map != null) {
sd = map.get(c);
}
if (sd == null) {
sd = new ServiceDispatcher(c, context, handler, flags);
if (map == null) {
map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
mServices.put(context, map);
}
map.put(c, sd);
} else {
sd.validate(context, handler);
}
return sd.getIServiceConnection();
}
}
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<LoadedApk.ServiceDispatcher> mDispatcher;
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
public void connected(ComponentName name, IBinder service) throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service);
}
}
}
上面的c.conn.connected就是調(diào)用的InnerConnection#connected方法未荒,
而這個方法又調(diào)用了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);
}
這里就調(diào)到了connection的方法专挪。
所以上面c.conn.connected(r.name, service)就是調(diào)用的ServiceConnection的onServiceConnected方法。
如何進(jìn)行通信的
總結(jié)
PS:進(jìn)程知識補(bǔ)充
進(jìn)程分為:
- 前臺進(jìn)程
- 可見進(jìn)程
- 服務(wù)進(jìn)程
- 后臺進(jìn)程
- 空進(jìn)程
前臺進(jìn)程:
有一個Activity
- ? 正在交互
有一個Service
- 綁定到正在交互的Activity
- “前臺運(yùn)行”片排,startForeground()
- 正在執(zhí)行生命周期回調(diào)onCreate()
有一個BroadcastReceiver
- 正在執(zhí)行onReceive()
可見進(jìn)程:
有一個Activity
- 不在交互寨腔,但仍可見
有一個Service
- 綁定到可見Activity
服務(wù)進(jìn)程:
- 普通Service
故而對耗時的比如上傳等,新建一個Service比在Activity新建一個線程好的多率寡。
后臺進(jìn)程:
- 所有Activity都對用戶不可見
會被保存在LRU列表中迫卢,即最近查看的最晚被終止
空進(jìn)程:
系統(tǒng)有時候會使用空進(jìn)程做為緩存,以縮短下一次在其中運(yùn)行組建所需的啟動時間
多進(jìn)程的特性
- 不同的內(nèi)存空間冶共,數(shù)據(jù)無法共享
- 需要謹(jǐn)慎處理代碼中的線程同步
- 需要提防多進(jìn)程并發(fā)導(dǎo)致的文件鎖和數(shù)據(jù)庫鎖時效的問題
具體問題:
1. 靜態(tài)成員和單例模式完全失效
2. 線程同步機(jī)制失效
3. SharedPreferences可靠性下降
4. Application會多次重建
如何判斷進(jìn)程的優(yōu)先級
通過oom_adj 值乾蛤,判斷進(jìn)程的優(yōu)先級
不同手機(jī)的oom_adj 值 可能不一樣
進(jìn)程間通信方式
線程間通信
- 共享內(nèi)存
- 文件、數(shù)據(jù)庫
- Handler
- Java里的wait notify notifyAll
在非UI線程中更新UI
- Activity.runOnUiThread(Runnable)
- View.post(Runnable)
- View.postDelayed(Runnable,long)
- handler
- AsyncTask