IPC进程间通信原理分析

分析源码前先布置例子代码

一. 服务端 进程:

  1. 定义一个 AIDL 接口
    interface UserAidl {
        String getUserName();
        String getPassword();
    }
  2. 创建一个服务,让客户端绑定这个服务然后获取 服务端返回的 IBinder,也就是 mBinder
    public class MessageService extends Service {
    
        private final UserAidl.Stub mBinder = new UserAidl.Stub() {
            @Override
            public String getUserName() throws RemoteException {
                return "ytempest";
            }
    
            @Override
            public String getPassword() throws RemoteException {
                return "1234567";
            }
        };
        
        @Override
        public IBinder onBind(Intent intent) {
            return mBinder;
        }
    }
  3. 在 AndroidManifest.xml 配置这个服务,然后添加一个 action,让客户端可以隐式绑定这个服务端;启动这个服务,服务端的布置到这里
    <service android:name=".service.MessageService" >
    	<intent-filter>
    		<action android:name="com.ytempest.aidl.useraidl" />
    		<category android:name="android.intent.category.DEFAULT" />
    	</intent-filter>
    </service>
     

二. 客户端 进程

  1. 定义一个和 服务端一样的 AIDL 接口(注意:这个AIDL接口要和服务端的AIDL包名一直,不然会GG)
    interface UserAidl {
        String getUserName();
        String getPassword();
    }
  2. 创建 绑定服务端服务需要的 ServiceConnection
    private UserAidl mUserAidl;
    private ServiceConnection mServiceConn = new ServiceConnection() {
    	// 绑定服务成功的时候调用
    	@Override
    	public void onServiceConnected(ComponentName name, IBinder service) {
    		// 这个 IBinder 就是服务端 MessageService服务中 onBind() 方法返回的 mBinder
    		mUserAidl = UserAidl.Stub.asInterface(service);
    	}
    	// 断开绑定服务的时候调用
    	@Override
    	public void onServiceDisconnected(ComponentName name) {
    		mUserAidl = null;
    	}
    };
  3. 然后绑定 服务端的服务以获取 服务端的 IBinder
    Intent intent = new Intent();
    // 指向有该 action 的服务
    intent.setAction("com.ytempest.aidl.useraidl");
    // 设置 目的App包
    intent.setPackage("com.ytempest.aidltest");
    boolean bind = bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE);
  4. 获取 服务端服务返回的数据
    if (mUserAidl != null) {
    	String userName = null;
    	String password = null;
    	try {
    		userName = mUserAidl.getUserName();
    		password = mUserAidl.getPassword();
    	} catch (RemoteException e) {
    		e.printStackTrace();
    	}
    }

进程布置完毕,现在开始看源码,看源码的时候记住

  1. 客户端的是怎么绑定服务端的服务的 
  2. 客户端的 ServiceConnection 对象传到哪里去了 
  3. 在哪里获取到了服务端的 IBinder的
  4. 绑定服务端的服务后,mServiceConn 中的 onServiceConnected 方法是就如何获取到 服务端返回的 mBinder的

1.  点击 MainActivity 的 bindService() 方法最终找到的是 ContextWrapper 类的抽象方法,查看这个类的实现类 ContextImpl 类

★  ContextImpl 类 bindService() 方法源码
 

@Override
public boolean bindService(Intent service, ServiceConnection conn,
		int flags) {
	warnIfCallingFromSystemProcess();
	return bindServiceCommon(service, conn, flags, Process.myUserHandle());
}

★  ContextImpl 类 bindServiceCommon() 方法源码

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
		UserHandle user) {
	...
	IServiceConnection sd;
	if (mPackageInfo != null) {
		// mPackageInfo 是 LoadedApk对象,
		sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
				mMainThread.getHandler(), flags);
	}
	try {
		...
		int res = ActivityManagerNative.getDefault().bindService(
			mMainThread.getApplicationThread(), getActivityToken(),
			service, service.resolveTypeIfNeeded(getContentResolver()),
			sd, flags, user.getIdentifier());
		...
	} catch (RemoteException e) {
		return false;
	}
}

问题①:mPackageInfo.getServiceDispatcher 方法做了什么?返回的是什么?

问题②:ActivityManagerNative.getDefault() 方法返回的是什么?

解答①:

mPackageInfo是一个 LoadedApk类,调用 getServiceDispatcher() 方法,在这个方法中会创建一个 ServiceDispatcher对象,然后将 ServiceConnection 对象传进去了,最后调用这个类的 getIServiceConnection() 方法

 ★  LoadedApk 类 getServiceDispatcher() 方法的源代码如下:

public final IServiceConnection getServiceDispatcher(ServiceConnection c,
                                                     Context context, Handler handler, int flags) {
    synchronized (mServices) {
        ServiceDispatcher sd = null;
        ArrayMap<ServiceConnection, ServiceDispatcher> map = mServices.get(context);
        if (map != null) {
            sd = map.get(c);
        }
        if (sd == null) {
            // 创建了一个 ServiceDispatcher对象,并将 ServiceConnection对象传进去了
            sd = new ServiceDispatcher(c, context, handler, flags);
            if (map == null) {
                map = new ArrayMap<ServiceConnection, ServiceDispatcher>();
                mServices.put(context, map);
            }
            map.put(c, sd);
        } else {
            sd.validate(context, handler);
        }
        return sd.getIServiceConnection();
    }
}

这里的问题就有:

  1. 创建了一个 ServiceDispatcher对象做了什么
    1. 将 ServiceConnection 对象传到了 ServiceDispatcher类的 mConnection 中
    2. 用一个实现了 IServiceConnection 这一个 AIDL接口的 InnerConnection 对象 实例化了 mIServiceConnection 对象,而这个对象经过一系列参数传递,最终会传递到 ActiveServices 类中的 bindServiceLocked() 方法中进行封装
       
  2. getIServiceConnection() 方法返回了什么
    返回一个 IServiceConnection 对象(InnerConnection 类向上转型得到)

(1.1) 由 ServiceDispatcher 类的构造方法可以知道,ServiceConnection 对象最终是传到了 ServiceDispatcher类的 mConnection中

 ★  LoadedApk 类的 内部类 ServiceDispatcher 的构造方法源码如下:

ServiceDispatcher(ServiceConnection conn,
                  Context context, Handler activityThread, int flags) {
    mIServiceConnection = new InnerConnection(this);
    // mConnection 也是一个 ServiceConnection 对象
    // 这个ServiceConnection对象会在 绑定成功(或失败时)调用其两个回调方法
    mConnection = conn;
    mContext = context;
    mActivityThread = activityThread;
    mLocation = new ServiceConnectionLeaked(null);
    mLocation.fillInStackTrace();
    mFlags = flags;
}

(1.2)由上可知道 创建了一个 InnerConnection 对象,并将 this 传进去保存在 mDispatcher 中,这个对象在 connect() 方法中会使用。由源码可以知道 InnerConnection 类继承了 IServiceConnection 这一个 AIDL接口,实现了这个接口的 connect() 方法

★  LoadedApk类  中的 内部类ServiceDispatcher  中的  内部类InnerConnection 源码如下:

private static class InnerConnection extends IServiceConnection.Stub {
    final WeakReference<ServiceDispatcher> mDispatcher;

    InnerConnection(ServiceDispatcher sd) {
        mDispatcher = new WeakReference<ServiceDispatcher>(sd);
    }

    public void connected(ComponentName name, IBinder service) throws RemoteException {
        ServiceDispatcher sd = mDispatcher.get();
        if (sd != null) {
            sd.connected(name, service);
        }
    }
}

解答②:

(1.1)sDefault 是一个单例,get() 方法返回一个实例

★  ActivityManagerNative 类中的 getDefault() 方法源码

static public IActivityManager getDefault() {
    return gDefault.get();
}

(1.2 可以看到 sDefault是一个单例,Singleton就是一个单例模板,通过实现 create() 方法,在这个方法中实例化单例,然后返回给 mInstance;这里通过 asInterface() 方法创建了一个对象,然后返回给了 mIstance

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;
    }
};
public abstract class Singleton<T> {
    private T mInstance;
    protected abstract T create();
    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
            return mInstance;
        }
    }
}

(1.3)get() 方法返回的是一个 IActivityManager 的接口,那我们要找到它的实现类,最终找到了 ActivityManagerService

解答

get() 方法返回的是一个 ActivityManagerService 对象,也就是说 getDefault() 方法返回的是一个 ActivityManagerService 对象


2. ActivityManagerService 类中的 bindService() 方法没有做什么

★  ActivityManagerService 类中的 bindService() 方法源码:

public int bindService(IApplicationThread caller, IBinder token,
                       Intent service, String resolvedType,
                       IServiceConnection connection, int flags, int userId) {
    enforceNotIsolatedCaller("bindService");
    ....
    synchronized(this) {
        return mServices.bindServiceLocked(caller, token, service, resolvedType,
                connection, flags, userId);
    }
}

3. mServices 是 ActiveServices对象, ActiveServices 类中的 bindServiceLocked() 方法做了什么?

解答

  1. 先获取了一个 ServiceRecord对象;
  2. 然后实例化了 一个 ConnectionRecord 对象,将 IServiceConnection 传到了ConnectionRecord 对象中的 conn 中(这个时候后面的关键);
  3. 获取客户端的 IBinder
  4. 从 ServiceRecord对象中的 connections (ArrayMap<IBinder, ArrayList<ConnectionRecord>>)中根据 客户端的IBinder 获取ConnectionRecord集合,如果ConnectionRecord集合为空,则将客户端的 IBinder缓存到 connections中;
  5. 将ConnectionRecord 对象添加 ConnectionRecord集合(也就是ArrayMap<IBinder, ArrayList<ConnectionRecord>>中的 ArrayList)中去

★  ActiveServices 类中的 bindServiceLocked() 方法源码如下:

int bindServiceLocked(IApplicationThread caller, IBinder token,
                      Intent service, String resolvedType,
                      IServiceConnection connection, int flags, int userId) {
    ...
    ServiceRecord s = res.record;
    try {
        ...
        AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
        ConnectionRecord c = new ConnectionRecord(b, activity,
                connection, flags, clientLabel, clientIntent);
        // 将我们客户端的 ServiceConnection(只是经过一系列封装
        // 成了 InnerConnection而已,本质不变),转换成IBinder
        IBinder binder = connection.asBinder();
        // 重点重点:这里从 s的 connections中根据我们获取 ConnectionRecord集合,但是第一次肯定获取不到,因为没有缓存
        ArrayList<ConnectionRecord> clist = s.connections.get(binder);
        if (clist == null) {
            // 当 clist为空,则实例化一个ConnectionRecord集合,然后
            // 将我们客户端的IBinder作为key,ConnectionRecord集合作为值缓存到 ServiceRecord中的 connections(Map)中
            clist = new ArrayList<ConnectionRecord>();
            s.connections.put(binder, clist);
        }
        clist.add(c);
        b.connections.add(c);
        if (activity != null) {
            if (activity.connections == null) {
                activity.connections = new HashSet<ConnectionRecord>();
            }
            activity.connections.add(c);
        }
        b.client.connections.add(c);
        if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
            b.client.hasAboveClient = true;
        }
        if (s.app != null) {
            updateServiceClientActivitiesLocked(s.app, c, true);
        }
        clist = mServiceConnections.get(binder);
        if (clist == null) {
            clist = new ArrayList<ConnectionRecord>();
            mServiceConnections.put(binder, clist);
        }
        clist.add(c);
        if ((flags&Context.BIND_AUTO_CREATE) != 0) {
            s.lastActivity = SystemClock.uptimeMillis();
            if (bringUpServiceLocked(s, service.getFlags(), callerFg, false) != null) {
                return 0;
            }
        }
    }
    ....
    if (s.app != null && b.intent.received) {
        try {
            c.conn.connected(s.name, b.intent.binder);
        } catch (Exception e) {
            ...
        }
        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);
    }
}

第 2 步详解 --> 源码:

ConnectionRecord(AppBindRecord _binding, ActivityRecord _activity,
                 IServiceConnection _conn, int _flags,
                 int _clientLabel, PendingIntent _clientIntent) {
    binding = _binding;
    activity = _activity;
    conn = _conn;
    flags = _flags;
    clientLabel = _clientLabel;
    clientIntent = _clientIntent;
}

4. ActiveServices 类中的 bindServiceLocked() 方法会调用 requestServiceBindingLocked() 方法:

★  ActiveServices 类的 requestServiceBindingLocked() 方法的源码如下:

private final boolean requestServiceBindingLocked(ServiceRecord r,
                                                  IntentBindRecord i, boolean execInFg, boolean rebind) {
    ....
    if ((!i.requested || rebind) && i.apps.size() > 0) {
        try {
            bumpServiceExecutingLocked(r, execInFg, "bind");
            r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
            r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                    r.app.repProcState);
            ...
        } catch (RemoteException e) {
            if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
            return false;
        }
    }
    return true;
}

分析:

r:ServiceRecord 类

app: ProcessRecord 对象

thread: IApplicationThread 接口对象 

那么要找到 scheduleBindService() 方法是谁调用的 就要找到 IApplicationThread 接口的实现类,我们找到了 ApplicationThreadNative 类,我们要找到这个类的实现类,这个实现类就是 ActivityThread 类的内部类 ApplicationThread 类

public abstract class ApplicationThreadNative extends Binder
implements IApplicationThread
private class ApplicationThread extends ApplicationThreadNative {

5. 最终会调用到 ActivityThread 的内部类 ApplicationThread 中的 scheduleBindService() 方法,这个方法会安排连接服务端的服务

★  ActivityThread 类的内部类 ApplicationThread 类的 scheduleBindService() 方法的源码

// 将传过来的第一个 ServiceRecord对象 向上转型为 IBinder
// 由此可以知道我们客户端的 ServiceConnection 经过一系列的封装,最终会封装成一个 IBinder对象,然后用于与服务端进程间通信
public final void scheduleBindService(IBinder token, Intent intent,
                                      boolean rebind, int processState) {
    updateProcessState(processState, false);
    // 存储和 客户端的IBinder 和 intent
    BindServiceData s = new BindServiceData();
    // 将 IBinder 对象存到 token中
    s.token = token;
    s.intent = intent;
    s.rebind = rebind;
    ....
    sendMessage(H.BIND_SERVICE, s);
}

分析

这里会发送 消息 给 H(H 继承了 Handler类,H.BIND_SERVICE 是该类的一个静态常量)进行处理,那么找到 这个 H,在 handleMessage() 方法中对 发送过来的 s对象(BindServiceData对象)进行了处理

case BIND_SERVICE:
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
    handleBindService((BindServiceData)msg.obj);
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    break;

6. 通信的交接点:就是在 handleBindService() 方法中获取到服务端的IBinder,然后返回给客户端

★  ActivityThread 类的内部类 H 中的 handleBindService() 方法源码如下:

private void handleBindService(BindServiceData data) {
    // 这个根据我们的客户端的IBinder获取我们绑定的 service,也就是 MessageService
    Service s = mServices.get(data.token);
    ....
    if (s != null) {
        try {
            data.intent.setExtrasClassLoader(s.getClassLoader());
            data.intent.prepareToEnterProcess();
            try {
                if (!data.rebind) {
                    // 这里就调用了MessageService服务的 onBind() 方法获取服务返回的IBinder
                    IBinder binder = s.onBind(data.intent);
                    // 这里就会将从 MessageService 获取的 IBinder公开出去,然后其他进程能够获取到
                    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) {
            }
        }...
    }
}

7. 由第 1 点分析可以知道  ActivityManagerNative.getDefault() 方法返回的是一个 ActivityManagerService 对象,查看该类的 publishService() 方法

★  ActivityManagerService 类的 publishService() 方法源码如下:

public void publishService(IBinder token, Intent intent, IBinder service) {
    ....
    synchronized(this) {
        if (!(token instanceof ServiceRecord)) {
            throw new IllegalArgumentException("Invalid service token");
        }
        mServices.publishServiceLocked((ServiceRecord)token, intent, service);
    }
}

8. mServices 是 ActivityServices 类,在调用 publishServiceLocked() 方法前将 我们客户端的 IBinder 转型为了 ServiceRecord类了(重点)

★  ActivityServices 类的 publishServiceLocked() 方法源码如下:

void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
    try {
        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--) {
                    // 在这里获取我们文章第 3 步存储到 ServiceRecord中 connections中的 ConnectionRecord集合
                    ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
                    for (int i=0; i<clist.size(); i++) {
                        // 获取封装了 IServiceConnection的 ConnectionRecord对象
                        ConnectionRecord c = clist.get(i);
                        if (!filter.equals(c.binding.intent.intent)) {
                            if (DEBUG_SERVICE) Slog.v(
                                    TAG, "Not publishing to: " + c);
                            if (DEBUG_SERVICE) Slog.v(
                                    TAG, "Bound intent: " + c.binding.intent.intent);
                            if (DEBUG_SERVICE) Slog.v(
                                    TAG, "Published intent: " + intent);
                            continue;
                        }
                        if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
                        try {
                            // c:ConnectionRecord对象
                            // conn:ConnectionRecord对象中的 IServiceConnection接口对象(这个
                            // 对象我们在第 3 步把我们客户端的IServiceConnection传进去了)
                            // connected() 方法:这个方法其实就会调用我们第 1 步创建的 InnerConnection对象中的 connected()方法
                            // 参数:service是服务端返回的 IBinder
                            c.conn.connected(r.name, service);
                        } catch (Exception e) {
                            ....
                        }
                    }
                }
            }
            serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
        }
    } finally {
        Binder.restoreCallingIdentity(origId);
    }
}

9. c.conn.connected() 方法会调用 InnerConnection 内部类的 connected() 方法

★  LoadedApk类  中的 内部类ServiceDispatcher  中的  内部类InnerConnection 的 connected() 方法源码如下:

public void connected(ComponentName name, IBinder service) throws RemoteException {
    ServiceDispatcher sd = mDispatcher.get();
    if (sd != null) {
        // sd 是一个ServiceDispatcher(外部类)对象
        sd.connected(name, service);
    }
}

10. 最终 ServiceDispatcher 类中的 connected() 方法会调用 本类的 doConnected() 方法

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) {
    ConnectionInfo old;
    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 (old != null) {
        // 这个 mConnection对象就是我们客户端绑定服务传进来的 ServiceConnection
        mConnection.onServiceDisconnected(name);
    }
    // 如果客户端绑定了一个新的 service则会被执行这个方法
    if (service != null) {
        mConnection.onServiceConnected(name, service);
    }
}

猜你喜欢

转载自blog.csdn.net/myTempest/article/details/78682427