Binder之bindService

8次阅读

共计 10787 个字符,预计需要花费 27 分钟才能阅读完成。

一个需要进行 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<ServiceConnection, LoadedApk.ServiceDispatcher> 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<ServiceConnection, LoadedApk.ServiceDispatcher>();
                    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<ConnectionRecord> clist = s.connections.get(binder);
            if (clist == null) {clist = new ArrayList<ConnectionRecord>();
                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<ConnectionRecord>();
                }
                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<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) {
                // 如果 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.java

private 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 来管理。

正文完
 0