Android中的IPC方式——Binder(三)

Android中的IPC方式——Binder(一)
Android中的IPC方式——Binder(二)
基于Android5.1.1分析,因为API26以后底层相关代码变动。

在client 中 通过bindservice来启动,来看下bindservice源码。
其具体是在
/frameworks/base/core/java/android/app/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,
    UserHandle user) {
    ...
    int res = ActivityManagerNative.getDefault().bindService(
    mMainThread.getApplicationThread(), getActivityToken(),
    service, service.resolveTypeIfNeeded(getContentResolver()),
    sd, flags, user.getIdentifier());
    ...
}

/frameworks/base/core/java/android/app/ActivityManagerNative.java

public abstract class ActivityManagerNative extends Binder implements IActivityManager{
    /**
    *  //最终返回的还是一个ActivityManagerProxy对象
    */
    static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        //这里面的Binder类型的obj参数会作为ActivityManagerProxy的成员变量保存为mRemote成员变量,负责进行IPC通信
        return new ActivityManagerProxy(obj);
    }

    /**
    *  //从类声明上,我们可以看到ActivityManagerNative是Binder的一个子类,而且实现了IActivityManager接口
    */
    static public IActivityManager getDefault() {
        return gDefault.get();
    }
    //通过单例模式获取一个IActivityManager对象,这个对象通过asInterface(b)获得 
    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;
        }
    };

}

/frameworks/base/core/java/android/app/IActivityManager.java

public interface IActivityManager extends IInterface {
    ...
    public int bindService(IApplicationThread caller, IBinder token, Intent service, String resolvedType,IServiceConnection connection, int flags, int userId) throws RemoteException;
    public boolean unbindService(IServiceConnection connection) throws RemoteException;
    ...
}

ActivityManagerNative.getDefault()获得IActivityManager,IActivitymanager继承于IInterface,这个结构是不是跟我们之前看的IStudentManager很像,那么IActivityManager.bindservice(),应该由它的静态内部类Proxy来实现。但是IActivityManager内部类并没有,其实是通过其他类来实现同样功能只是名称换了。这个类就是ActivityManagerNative。

public abstract class ActivityManagerNative extends Binder implements IActivityManager{
    ...
    @Override
        public boolean onTransact(int code, Parcel data, Parcel reply, int flags)throws RemoteException {
        switch (code) {
            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();
                int userId = data.readInt();
                IServiceConnection conn = IServiceConnection.Stub.asInterface(b);
                int res = bindService(app, token, service, resolvedType, conn, fl, userId);
                reply.writeNoException();
                reply.writeInt(res);
                return true;

            }
    }
    ...
    
    
    class ActivityManagerProxy implements IActivityManager{
        ...
        public ActivityManagerProxy(IBinder remote){
            mRemote = remote;
        }
        public IBinder asBinder()
        {
            return mRemote;
        }
        ...
        
    public int bindService(IApplicationThread caller, IBinder token,
Intent service, String resolvedType, IServiceConnection connection,int flags, 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.writeInt(userId);
            mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
            reply.readException();
            int res = reply.readInt();
            data.recycle();
            reply.recycle();
            return res;
    }
}

可以看到ActivityManagerNative继承Binder实现IActivityManager,ActivityManagerNative就相当于Stub。
ActivityManagerProxy就是Proxy。

通过调用到的mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);调用到Stub中的onTranact(),而Stub的具体实现类则是Activity'ManagerService,最后就是在ActivityManagerService中的bindservice()

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    
    final ActiveServices mServices;
    public int bindService(IApplicationThread caller, IBinder token,Intent service, String resolvedType,IServiceConnection connection, int flags, int userId) {
        
        enforceNotIsolatedCaller("bindService");

        // Refuse possible leaked file descriptors
        if (service != null && service.hasFileDescriptors() == true) {
         throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        synchronized(this) {
            return mServices.bindServiceLocked(caller, token, service, resolvedType,
            connection, flags, userId);
        }
    }
}

bindservice主要分为四种情况

  • server整个进程都没有启动
  • server进程启动了,但是里面的service没有创建
  • server进程启动了,里面的service也创建了,但是没有绑定过,回调onBind()
  • server进程启动了,里面的service创建了,也被绑定过,回调onRebind()

/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

public final class ActiveServices {
    ...
    int bindServiceLocked(IApplicationThread caller, IBinder token,Intent service,  String resolvedType,IServiceConnection connection, int flags, int userId) {
        ...
        if ((flags&Context.BIND_AUTO_CREATE) != 0) {
            s.lastActivity = SystemClock.uptimeMillis();
            if (bringUpServiceLocked(s, service.getFlags(), callerFg, false) != null) {
                return 0;
            }
        }
        ...
        //进程启动service也创建的情况下并且绑定了, 回调onRebind()  
        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);
            } 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);
        }
        ...
    }
    ...
    //server整个进程都没有启动,server进程启动了,但是里面的service没有创建  
    private final String bringUpServiceLocked(ServiceRecord r,int intentFlags,              boolean execInFg, boolean whileRestarting) {
        
        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) {//进程启动了service没有创建
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } 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.
            }
        }
        //进程未启动的情况
        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;
            }
        }
    }
    
    private final void realStartServiceLocked(ServiceRecord r,
        ProcessRecord app, boolean execInFg) throws RemoteException {
        ...
          app.thread.scheduleCreateService(r, r.serviceInfo,                                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
        ...
    }
}

对应的上述四种情况

  • server整个进程都没有启动
    bindServiceLocked()->bringUpServiceLocked() 通过mAm.startProcessLocked()启动进程,bringDownServiceLocked(r);来启动服务。

  • server进程启动了,但是里面的service没有创建
    bindServiceLocked()->bringUpServiceLocked()->realStartServiceLocked(r, app, execInFg);后续跟一下

  • server进程启动了,里面的service也创建了,但是没有绑定过,回调onBind()

    bindServiceLocked()->requestServiceBindingLocked(s, b.intent, callerFg, false);

  • server进程启动了,里面的service创建了,也被绑定过,回调onRebind()
    bindServiceLocked()->requestServiceBindingLocked(s, b.intent, callerFg, true);

第一种情况没什么好说的,看一下第二种情况,从上面代码看到realStartServiceLocked()调用了scheduleCreateService()

/frameworks/base/core/java/android/app/ActivityThread.java

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);
}
 public void handleMessage(Message msg) {
     ...
    case CREATE_SERVICE:
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");
        handleCreateService((CreateServiceData)msg.obj);
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        break;
    ...
 }
 private void handleCreateService(CreateServiceData data) {
     ...
     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);
            }
        }
    ...

 }

这里可以看到最后通过反射来创建service。

第三、四种情况,都是调用的从ActiveService中requestServiceBindingLocked()只是最后一个参数不一样。

/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

private final boolean requestServiceBindingLocked(ServiceRecord r,
        IntentBindRecord i, boolean execInFg, boolean rebind) {
    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);
            r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                    r.app.repProcState);
            if (!rebind) {
                i.requested = true;
            }
            i.hasBound = true;
            i.doRebind = false;
        } catch (RemoteException e) {
            if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
            return false;
        }
    }
    return true;
}

发现跟调用到ActivityThread.javascheduleBindService()

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);
}

public void handleMessage(Message msg) {
     ...
 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);
                }
            }
        }
    }

最后调用handleBindService()首先从mServices在这个map去取服务,服务不为空后,根据flag来判断调用onBind()还是 onReind(),s.onBind(data.intent)返回Binder。这个可以根据前面aidl使用的部分,service在OnBind()方法需要返回一个IBineder,而这个IBinder是 IStudentManager.Stub,由Service实现。

/frameworks/base/services/core/java/com/android/server/am/ActiveServices.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);
    }
}

/frameworks/base/services/core/java/com/android/server/am/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);
    }
}

/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
    ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
    ConnectionRecord c = clist.get(i);
    ...
    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);
    }
    ....
}

到这里可以看到我们在service实现的onBind方法返回的 IBinder对象通过publishService()->publishServiceLocked()传递。

ConnectionRecord.java

final class ConnectionRecord {
    final AppBindRecord binding;    // The application/service binding.
    final ActivityRecord activity;  // If non-null, the owning activity.
    final IServiceConnection conn; 
    ...
}

c.conn.connected(r.name, service);传递的service 就是我们刚刚的IBinder,c.conn最终指的是IServiceConnection,具体实现为

/frameworks/base/core/java/android/app/LoadedApk.javaLoadedApk.ServiceDispatcher.InnerConnection

static final class ServiceDispatcher {
 ...
    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);
            }
        }
    }
...
public void connected(ComponentName name, IBinder service) {
        if (mActivityThread != null) {
            mActivityThread.post(new RunConnection(name, service, 0));
        } else {
            doConnected(name, service);
        }
    }
}  

private final class RunConnection implements Runnable {
    RunConnection(ComponentName name, IBinder service, int command) {
        mName = name;
        mService = service;
        mCommand = command;
    }

    public void run() {
        if (mCommand == 0) {
            doConnected(mName, mService);
        } else if (mCommand == 1) {
            doDeath(mName, mService);
        }
    }

    final ComponentName mName;
    final IBinder mService;
    final int mCommand;
}

public void doConnected(ComponentName name, IBinder 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);
    }
}

mActivityThread.post(new RunConnection(name, service, 0));在RunConnection的run方法中调用了doConnected方法,doConnected()中调用了onServiceDisconnected()onServiceConnected()

这个就是由我们client端创建serviceConnetion时需要实现的方法。这样最终在客户端的onServiceConnected()获取了由service实现的IBinder。

整个的流程走完了,在我们刚刚分析中无论是AMS 还是 后面的IService 基本上都看到了类似 Binder的 方式。

AIDL接口 Stub Proxy Stub实现类
IStudentManager.aidl IStudentManager.Stub IStudentManager.Proxy StudentManagerService
IActivityManager ActivityManagerNative ActivityManagerProxy ActivityManagerService

在我们的实际项目中会使用到非常多的系统服务,这时候也是需要进行进程间通信,他们都存在不同的进程中,如果都通过aidl方式来调用就会很繁琐。所以Android给我提供了ServiceManager来统一管理。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,980评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,422评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,130评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,553评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,408评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,326评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,720评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,373评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,678评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,722评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,486评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,335评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,738评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,283评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,692评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,893评论 2 335

推荐阅读更多精彩内容