一个需要进行Binder通信的Client一般通过bindService()来启动Service。

bindService(it, mServiceConnection, Service.BIND_AUTO_CREATE);

binderService()的实现在ContextWrapper中,

frameworks/base/core/java/android/app/ContextImpl.java    @Override    public boolean bindService(Intent service, ServiceConnection conn,                                                                                                                                                  int flags) {        //如果是系统进程,发出警告        warnIfCallingFromSystemProcess();        return bindServiceCommon(service, conn, flags, Process.myUserHandle());}......    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,            UserHandle user) {        IServiceConnection sd;        ......        if (mPackageInfo != null) {            // 获取IServiceConnection对象            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),                    mMainThread.getHandler(), flags);        } else {            throw new RuntimeException("Not supported in system context");        }        // 验证service有效性        validateServiceIntent(service);        try {                   ......            // 准备离开应用程序            service.prepareToLeaveProcess();            // 调用ActivityManagerProxy的bindService()            int res = ActivityManagerNative.getDefault().bindService(                mMainThread.getApplicationThread(), getActivityToken(),                service, service.resolveTypeIfNeeded(getContentResolver()),                sd, flags, user.getIdentifier());            ......        }    }

其中,getServiceDispatcher()返回一个IServiceConnection对象,它为一个Binder实体,将负责与ServiceConnection通信。

frameworks/base/core/java/android/app/LoadedApk.java    public final IServiceConnection getServiceDispatcher(ServiceConnection c,            Context context, Handler handler, int flags) {        synchronized (mServices) {            LoadedApk.ServiceDispatcher sd = null;            // 获取map,map存储ServiceConnection与ServiceDispatcher的映射            ArrayMap map = mServices.get(context);            if (map != null) {                sd = map.get(c);            }            // 如果map中没有c映射,新建一个插入到mServices和map中            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);            }            // 返回mIServiceConnection,InnerConnection对象            return sd.getIServiceConnection();        }    }

接着看bindService。通过ActivityManagerNative.getDefault()获得了ActivityManagerProxy, 它的bindService()就是发起一个Binder调用。调用的远端为system_server的ActivityManagerService。

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

mServices为ActiveServices的对象。

frameworks/base/services/core/java/com/android/server/am/ActiveServices.java    int bindServiceLocked(IApplicationThread caller, IBinder token,            Intent service, String resolvedType,            IServiceConnection connection, int flags, int userId) {        ......        // 查找发起bindSevice应用在AMS中的记录        final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);        ......        if (callerApp.info.uid == Process.SYSTEM_UID) {            // 当应用为system进程时            ......        }        ......        final boolean callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;        // 根据Intent查找相应的服务        ServiceLookupResult res =            retrieveServiceLocked(service, resolvedType,                    Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg);        ......        ServiceRecord s = res.record;        final long origId = Binder.clearCallingIdentity();        try {            // 取消服务的restart机制            if (unscheduleServiceRestartLocked(s, callerApp.info.uid, false)) {                if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "                        + s);            }            if ((flags&Context.BIND_AUTO_CREATE) != 0) {                // 更新服务最后活跃时间                s.lastActivity = SystemClock.uptimeMillis();                if (!s.hasAutoCreateConnections()) {                    // 如果是第一次连接,设置bind                    // This is the first binding, let the tracker know.                    ProcessStats.ServiceState stracker = s.getTracker();                    if (stracker != null) {                        stracker.setBound(true, mAm.mProcessStats.getMemFactorLocked(),                                s.lastActivity);                    }                }            }            mAm.startAssociationLocked(callerApp.uid, callerApp.processName,                    s.appInfo.uid, s.name, s.processName);            // 创建AppBindRecord,关联应用与服务            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);            // 创建ConnectionRecord,记录bind信息            ConnectionRecord c = new ConnectionRecord(b, activity,                    connection, flags, clientLabel, clientIntent);            // 转换interface到binder            IBinder binder = connection.asBinder();            ArrayList clist = s.connections.get(binder);            if (clist == null) {                clist = new ArrayList();                s.connections.put(binder, clist);            }            // 将新的Connection加入到ServiceRecord和AppBindRecord中            clist.add(c);            b.connections.add(c);            if (activity != null) {                // 当由activity发起bind时,将Connection加入到ActivityRecord                if (activity.connections == null) {                    activity.connections = new HashSet();                }                activity.connections.add(c);            }            // 将新的Connection加入到AppBindRecord的client中            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);            }            // 将新的Connection加入到service connections映射表中            clist = mServiceConnections.get(binder);            if (clist == null) {                clist = new ArrayList();                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) {                // 如果service已经运行,声明已连接,回调到应用的onServiceConnected                try {                    c.conn.connected(s.name, b.intent.binder);                    ......                }                // 如果第一个连接的应用重新bind时执行onRebind                if (b.intent.apps.size() == 1 && b.intent.doRebind) {                    requestServiceBindingLocked(s, b.intent, callerFg, true);                }            } else if (!b.intent.requested) {                // 执行onBind                requestServiceBindingLocked(s, b.intent, callerFg, false);            }            getServiceMap(s.userId).ensureNotStartingBackground(s);        } finally {            Binder.restoreCallingIdentity(origId);        }        return 1;    }

上述的流程中有两个对connection的描述,需要区分一下。一个是传参进入的IServiceConnection对象,它实质上时一个Binder,由bindService发起端创建。应用创建一个ServiceConnection Binder,将代理传递到system_server中,这样system_server可以返回conneted和disconnected等状态。另一个connect是函数内部创建的ConnectionRecord对象。它描述了bind service的相关信息,并存储到ServiceRecord和AppBindRecord中。
Service的启动通过bringUpServiceLocked()完成。

frameworks/base/services/core/java/com/android/server/am/ActiveServices.java    private final String bringUpServiceLocked(ServiceRecord r,            int intentFlags, boolean execInFg, boolean whileRestarting) {        if (r.app != null && r.app.thread != null) {            // 如果service已经运行,直接执行onStartCommand            sendServiceArgsLocked(r, execInFg, false);            return null;        }        ......        // Service启动过程中不能停止package        try {            AppGlobals.getPackageManager().setPackageStoppedState(                    r.packageName, false, r.userId);            ......        }        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;        final String procName = r.processName;        ProcessRecord app;        if (!isolated) {            // 如果服务进程已经启动,则启动服务            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);            if (app != null && app.thread != null) {                try {                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);                    realStartServiceLocked(r, app, execInFg);                    return null;                ......        }        // 如果服务进程不存在,先创建进程,然后将服务加入队列,等待执行        if (app == null) {            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,                    "service", r.name, false, isolated, false)) == null) {            ......        }        if (!mPendingServices.contains(r)) {            mPendingServices.add(r);        }        ......        return null;    }

当服务进程不存在时,需要先创建服务进程,然后再启动进程。启动进程通过AMS的startProcessLocked来完成。startProcessLocked中通过Process.start()创建新进程。新进程启动时会执行ActivityThread的main函数,里面会调用到ActivityThread.attach。这个attach通过binder最终调用到AMS中的attachApplication,再调用ActiveServices的attachApplicationLocked,这里启动pending的service。启动还是通过realStartServiceLocked完成的。

frameworks/base/services/core/java/com/android/server/am/ActiveServices.java    private final void realStartServiceLocked(ServiceRecord r,            ProcessRecord app, boolean execInFg) throws RemoteException {        ......        r.app = app;        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();        app.services.add(r);        bumpServiceExecutingLocked(r, execInFg, "create");        mAm.updateLruProcessLocked(app, false, null);        mAm.updateOomAdjLocked();                boolean created = false;        try {            ......            mAm.ensurePackageDexOpt(r.serviceInfo.packageName);            app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);            // 启动service            app.thread.scheduleCreateService(r, r.serviceInfo,                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),                    app.repProcState);            r.postNotification();            created = true;        ......        }        // 执行service的onBind        requestServiceBindingsLocked(r, execInFg);        // 更新client状态        updateServiceClientActivitiesLocked(app, null, true);        ......        // 执行Service的onStartCommand方法        sendServiceArgsLocked(r, execInFg, true);        ......    }

app.thread为新建服务的Binder代理,运行scheduleCreateService()就远程调用到ActivityThread中。

frameworks/base/core/java/android/app/ActivityThread.javaprivate class ApplicationThread extends ApplicationThreadNative {    ......        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;            // 发送消息CREATE_SERVICE            sendMessage(H.CREATE_SERVICE, s);        }        ......}........private class H extends Handler {    ......        public void handleMessage(Message msg) {            ......                case CREATE_SERVICE:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");                    // 在handler中处理消息                    handleCreateService((CreateServiceData)msg.obj);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;            ......        }......    private void handleCreateService(CreateServiceData data) {l        // 跳过GC        unscheduleGcIdler();        LoadedApk packageInfo = getPackageInfoNoCheck(                data.info.applicationInfo, data.compatInfo);        Service service = null;        try {            // 通过反射创建service            java.lang.ClassLoader cl = packageInfo.getClassLoader();            service = (Service) cl.loadClass(data.info.name).newInstance();        ......        }        try {            // 创建context            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);            context.setOuterContext(service);            // 创建Application            Application app = packageInfo.makeApplication(false, mInstrumentation);            service.attach(context, this, data.info.name, data.token, app,                    ActivityManagerNative.getDefault());            // 调用service的onCreate方法,正式启动service            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.            }        ......        }    }

到这里,Service就已经完成启动。之后AMS会进行bindService,服务端执行bind时调用publishService来发布service,表明service已经可以使用。Bind过程最后会通过bindService最开始时传给AMS的IServiceConnection代理回调到应用进程,执行onServiceConnected()。这个Binder回调也会将新建服务的Binder代理传回去,这样应用就可以使用这个代理与服务进行通信。细节就不再继续分析,通过下面的图简单描述一下整个流程。本文只是在最简单的角度来分析bindService过程,实际代码中许多的细节都没有描述。

上图重点描述各进程之间的关系,可以看到整个Service的bind过程涉及到多个不同的Binder。

  • IActivityManager:应用进程或服务进程与AMS通信时使用的Binder接口。AMS启动后向ServiceManager注册,其他进程从ServiceManager中获取代理。
  • IApplicationThread:服务进程启动后创建的Binder接口。回传给AMS,并由AMS进行管理。
  • IServiceConnection:应用进程创建发送给AMS,当服务连接成功后通过该Binder回调到应用进程,同时将服务进程的Binder接口回传给应用。

本文仅讲解了通过bindService来启动服务,但Android中存在多种启动服务的方式,它们存在区别,使用场景也不同。

  • startService: 仅仅启动Service,通常为后台服务。服务启动后就与发起者无关。
  • bindService:启动Service并绑定,用于发起者与服务进行交互。当发起者退出时,服务也跟随退出。
  • 启动系统服务:创建一个进程,通过ServiceManager.addService()注册为系统服务,Client通过ServiceManager.getService()来获取服务。这种方法在native和java都可以使用,但需要手动启动服务进程。

Service的管理也是不同的,系统服务是由ServiceManager进行管理的,而startService和bindService启动的服务是由AMS来管理。

更多相关文章

  1. Android(安卓)之Notification 用法
  2. 《android 利用自带技术解析json字符》
  3. android 通过uri启动Activity
  4. Activity 组件的启动流程
  5. Android(安卓)studio黑科技
  6. Android(安卓)优化开机启动
  7. Android(安卓)动态代理以及利用动态代理实现 ServiceHook
  8. Android主题更换换肤
  9. [Android5.1]开机动画显示工作流程分析

随机推荐

  1. Android(安卓)Studio Gradle 重命名输出A
  2. How to display a custom dialog in your
  3. Android 检测用户一段时间无操作
  4. Android(安卓)NDK编译常见错误及解决方案
  5. 关于Android中的SQLite使用
  6. Android复习(十一)
  7. 无法关联源码
  8. Android通过socket连接服务器(PC)
  9. 跨进程共享 SharedPreferences
  10. Android批量插入数据