Android Service

作者: lbtrace | 来源:发表于2017-11-18 14:19 被阅读55次

    Service组件

    Service 是一个可以在后台执行长时间运行操作而不提供用户界面的应用组件。服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行。

    Service按照启动方式基本分为两种类型:

    • 启动服务(startService)

      应用组件通过调用startService()启动服务,一旦启动,服务可在后台无限期运行,即使启动服务的组件已被销毁也不受影响。如果Service运行在单独的进程中,即使客户端进程死亡,Service进程仍然存活。调用stopSelf()或者stopService()可以停止服务(销毁服务),注意Service所在的进程状态改变,但不停止。

    • 绑定服务(BindService)

      应用组件通过调用bindService()绑定服务,绑定服务提供了一个客户端-服务器接口,允许组件与服务进行交互、发送请求、获取结果,甚至是利用进程间通信 (IPC) 跨进程执行这些操作。多个组件可以同时绑定到该服务,但全部取消绑定后,该服务即会被销毁。注意绑定服务停止后,其所在的进程状态改变,但不停止。

    服务通常运行在宿主进程的主线程中,如果服务将执行任何 CPU 密集型工作或阻塞性操作,则应在服务内创建新线程(IntentService)或者使用单独的服务进程来完成这项工作。下面重点分析startService()以及bindService()的流程。

    startService流程分析

    我们从ContextImpl的startService()开始分析。

        public ComponentName startService(Intent service) {
            // 系统进程直接调用,打印警告
            warnIfCallingFromSystemProcess();
            return startServiceCommon(service, mUser);
        }
    
    

    下面看startServiceCommon()

        private ComponentName startServiceCommon(Intent service, UserHandle user) {
            try {
                validateServiceIntent(service);
                service.prepareToLeaveProcess(this);
                // 通过Binder IPC请求AMS调用startService
                ComponentName cn = ActivityManagerNative.getDefault().startService(
                    mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                                getContentResolver()), getOpPackageName(), user.getIdentifier());
                if (cn != null) {
                    if (cn.getPackageName().equals("!")) {
                        throw new SecurityException(
                                "Not allowed to start service " + service
                                + " without permission " + cn.getClassName());
                    } else if (cn.getPackageName().equals("!!")) {
                        throw new SecurityException(
                                "Unable to start service " + service
                                + ": " + cn.getClassName());
                    }
                }
                return cn;
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    
    

    这样,客户端进程的请求就传递到system进程中,下面分析AMS中startService()的实现。

        public ComponentName startService(IApplicationThread caller, Intent service,
                String resolvedType, String callingPackage, int userId)
                throws TransactionTooLargeException {
            enforceNotIsolatedCaller("startService");
            // Refuse possible leaked file descriptors
            if (service != null && service.hasFileDescriptors() == true) {
                throw new IllegalArgumentException("File descriptors passed in Intent");
            }
    
            if (callingPackage == null) {
                throw new IllegalArgumentException("callingPackage cannot be null");
            }
    
            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
                    "startService: " + service + " type=" + resolvedType);
            synchronized(this) {
                final int callingPid = Binder.getCallingPid();
                final int callingUid = Binder.getCallingUid();
                final long origId = Binder.clearCallingIdentity();
                // 调用ActiveServices的startServiceLocked
                ComponentName res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid, callingPackage, userId);
                Binder.restoreCallingIdentity(origId);
                return res;
            }
        }
    
    

    ActiveServices负责管理Service组件,下面看ActiveServices的startServiceLocked()

        ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
                int callingPid, int callingUid, String callingPackage, final int userId)
                throws TransactionTooLargeException {
            if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service
                    + " type=" + resolvedType + " args=" + service.getExtras());
    
            final boolean callerFg;
            if (caller != null) {
                // 获取调用者的ProcessRecord
                final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
                if (callerApp == null) {
                    throw new SecurityException(
                            "Unable to find app for caller " + caller
                            + " (pid=" + Binder.getCallingPid()
                            + ") when starting service " + service);
                }
                // 检查调用者的SchedGroup,影响服务的超时时间
                callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
            } else {
                callerFg = true;
            }
    
            // 查询目标ServiceRecord,如果不存在创建
            ServiceLookupResult res =
                retrieveServiceLocked(service, resolvedType, callingPackage,
                        callingPid, callingUid, userId, true, callerFg, false);
            ......
            // 调用startServiceInnerLocked
            return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        }
    

    下面首先看retrieveServiceLocked()的实现,然后分析startServiceInnerLocked()

        private ServiceLookupResult retrieveServiceLocked(Intent service,
                String resolvedType, String callingPackage, int callingPid, int callingUid, int userId,
                boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal) {
            ServiceRecord r = null;
            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "retrieveServiceLocked: " + service
                    + " type=" + resolvedType + " callingUid=" + callingUid);
    
            userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId, false,
                    ActivityManagerService.ALLOW_NON_FULL_IN_PROFILE, "service", null);
    
            // 找到userId对应的ServiceMap,注意uid(应用沙箱)!= userId(代表一个用户,比如普通用户的userId = 0,也就是ps命令显示的u0)
            // 例如,u0_a100表示用户0的第101个app,userId = 0, uid = 10100
            ServiceMap smap = getServiceMap(userId);
            final ComponentName comp = service.getComponent();
            if (comp != null) {
                // 根据组件名查找userId的Service,同一用户的Service存放在ServiceMap中
                r = smap.mServicesByName.get(comp);
            }
            if (r == null && !isBindExternal) {
                Intent.FilterComparison filter = new Intent.FilterComparison(service);
                // 根据FilterComparison查找userId的Service
                r = smap.mServicesByIntent.get(filter);
            }
            if (r != null && (r.serviceInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) != 0
                    && !callingPackage.equals(r.packageName)) {
                // 可以运行在其他包中的服务正运行在自己的包中,不能共享ServiceRecord
                // If an external service is running within its own package, other packages
                // should not bind to that instance.
                r = null;
            }
            if (r == null) {
                try {
                    // 向PMS查询需要运行的Service组件信息
                    // TODO: come back and remove this assumption to triage all services
                    ResolveInfo rInfo = AppGlobals.getPackageManager().resolveService(service,
                            resolvedType, ActivityManagerService.STOCK_PM_FLAGS
                                    | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
                            userId);
                    ......
                    if (r == null && createIfNeeded) {
                        Intent.FilterComparison filter
                                = new Intent.FilterComparison(service.cloneFilter());
                        ServiceRestarter res = new ServiceRestarter();
                        BatteryStatsImpl.Uid.Pkg.Serv ss = null;
                        BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics();
                        synchronized (stats) {
                            ss = stats.getServiceStatsLocked(
                                    sInfo.applicationInfo.uid, sInfo.packageName,
                                    sInfo.name);
                        }
                        // 创建ServiceRecord
                        r = new ServiceRecord(mAm, ss, name, filter, sInfo, callingFromFg, res);
                        res.setService(r);
                        smap.mServicesByName.put(name, r);
                        smap.mServicesByIntent.put(filter, r);
                    ......
                    }
                }
            }
        }
    

    下面看startServiceInnerLocked()

        ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
                boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
            ServiceState stracker = r.getTracker();
            // 记录服务的运行状态
            if (stracker != null) {
                stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
            }
            r.callStart = false;
            synchronized (r.stats.getBatteryStats()) {
                r.stats.startRunningLocked();
            }
            // 启动服务
            String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
            if (error != null) {
                return new ComponentName("!!", error);
            }
            ......
        }
    

    下面分析bringUpServiceLocked()

       private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
                boolean whileRestarting, boolean permissionsReviewRequired)
                throws TransactionTooLargeException {
            ......
            // 检查服务是否运行在单独的进程中
            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 (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.
                }
            } else {
                // If this service runs in an isolated process, then each time
                // we call startProcessLocked() we will get a new isolated
                // process, starting another process if we are currently waiting
                // for a previous process to come up.  To deal with this, we store
                // in the service any current isolated process it is running in or
                // waiting to have come up.
                app = r.isolatedProc;
            }
    
            // Not running -- get it started, and enqueue this service record
            // to be executed when the app comes up.
            if (app == null && !permissionsReviewRequired) {
                // 创建服务进程
                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;
                }
            }
            ......
        }
    

    我们知道Serivce组件可以运行在宿主应用进程或者单独的进程中,这里我们只关注Service运行的进程已经存在的情况。(对于Service所在的进程还没有运行的情况,Service进程启动后,会调用attachApplication(),在该方法中会启动pending Services)下面看realStartServiceLocked()

        private final void realStartServiceLocked(ServiceRecord r,
                ProcessRecord app, boolean execInFg) throws RemoteException {
            if (app.thread == null) {
                throw new RemoteException();
            }
            if (DEBUG_MU)
                Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid
                        + ", ProcessRecord.uid = " + app.uid);
            r.app = app;
            r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
    
            // 服务添加到进程Service列表
            final boolean newService = app.services.add(r);
            // 更新服务统计信息,设置服务超时消息,根据服务是否在前台执行,超时时间不同
            bumpServiceExecutingLocked(r, execInFg, "create");
            mAm.updateLruProcessLocked(app, false, null);
            mAm.updateOomAdjLocked();
    
            boolean created = false;
            try {
                if (LOG_SERVICE_START_STOP) {
                    String nameTerm;
                    int lastPeriod = r.shortName.lastIndexOf('.');
                    nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName;
                    // 事件log
                    EventLogTags.writeAmCreateService(
                            r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
                }
                synchronized (r.stats.getBatteryStats()) {
                    r.stats.startLaunchedLocked();
                }
                mAm.notifyPackageUse(r.serviceInfo.packageName,
                                     PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
                app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
                // 通过Binder IPC调度应用执行服务
                app.thread.scheduleCreateService(r, r.serviceInfo,
                        mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                        app.repProcState);
                r.postNotification();
                created = true;
            } catch (DeadObjectException e) {
            ......
            }
            ......
            // 创建服务启动项,用于请求应用执行onStartCommand
            if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
                r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                        null, null));
            }
    
            // 请求应用执行onStartCommand
            sendServiceArgsLocked(r, execInFg, true);
            ......
        }
    

    下面分析Service宿主进程处理CreateService请求。

        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对象
                ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
                // 将服务对象的ContextImpl的outerContext设置为Service对象本身
                context.setOuterContext(service);
    
                Application app = packageInfo.makeApplication(false, mInstrumentation);
                // 执行Service的attach方法,这里的data.token为Binder代理对象
                // 其对应的Binder实体对象为ServiceRecord对象
                service.attach(context, this, data.info.name, data.token, app,
                        ActivityManagerNative.getDefault());
                // 调用Service的onCreate方法
                service.onCreate();
                mServices.put(data.token, service);
                try {
                    // 通知AMS,Service执行完毕,系统将移除服务超时消息
                    ActivityManagerNative.getDefault().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            } catch (Exception e) {
                if (!mInstrumentation.onException(service, e)) {
                    throw new RuntimeException(
                        "Unable to create service " + data.info.name
                        + ": " + e.toString(), e);
                }
            }
        }
    

    bindService流程分析

    bindService的流程教startService更加复杂,下面从bindService()开始分析。

        public boolean bindService(Intent service, ServiceConnection conn,
                int flags) {
            warnIfCallingFromSystemProcess();
            // 参数追加MainThread的Handler和进程所属用户的标示UserHandle(注意区分uid)
            return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
                    Process.myUserHandle());
        }
    

    下面看bindServiceCommon()的实现。

        private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
                handler, UserHandle user) {
            IServiceConnection sd;
            if (conn == null) {
                throw new IllegalArgumentException("connection is null");
            }
            if (mPackageInfo != null) {
                // 返回IServiceConnection.Stub对象,用于接收服务连接状态的变化;
                // 如果在Activity上下文中调用bindService,getOuterContext()返回Activity,handler用于向MainThread发消息
                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);
                // 通过Binder IPC请求AMS执行bindService
                int res = ActivityManagerNative.getDefault().bindService(
                    mMainThread.getApplicationThread(), getActivityToken(), service,
                    service.resolveTypeIfNeeded(getContentResolver()),
                    sd, flags, getOpPackageName(), user.getIdentifier());
                if (res < 0) {
                    throw new SecurityException(
                            "Not allowed to bind to service " + service);
                }
                return res != 0;
            } catch (RemoteException e) {
            }
        }
    

    下面看ActivityManagerService如何处理bindService()请求。

        // caller:ApplicationThreadProxy对象
        // token: ActivityRecord.Token对象
        // service: service intent
        // connection: IServiceConnection.Proxy对象,用于通知服务客户端服务连接的变化
        public int bindService(IApplicationThread caller, IBinder token, Intent service,
                String resolvedType, IServiceConnection connection, int flags, String callingPackage,
                int userId) throws TransactionTooLargeException {
            enforceNotIsolatedCaller("bindService");
    
            // Refuse possible leaked file descriptors
            if (service != null && service.hasFileDescriptors() == true) {
                throw new IllegalArgumentException("File descriptors passed in Intent");
            }
    
            if (callingPackage == null) {
                throw new IllegalArgumentException("callingPackage cannot be null");
            }
    
            synchronized(this) {
                // 调用ActiveServices的bindServiceLocked
                return mServices.bindServiceLocked(caller, token, service,
                        resolvedType, connection, flags, callingPackage, userId);
            }
        }
    

    下面分析bindServiceLocked()

        int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
                String resolvedType, final IServiceConnection connection, int flags,
                String callingPackage, final int userId) throws TransactionTooLargeException {
            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "bindService: " + service
                    + " type=" + resolvedType + " conn=" + connection.asBinder()
                    + " flags=0x" + Integer.toHexString(flags));
            // 获取服务客户端的ProcessRecord
            final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
            if (callerApp == null) {
                throw new SecurityException(
                        "Unable to find app for caller " + caller
                        + " (pid=" + Binder.getCallingPid()
                        + ") when binding service " + service);
            }
    
            ActivityRecord activity = null;
            if (token != null) {
                // 查找客户端的ActivityRecord
                activity = ActivityRecord.isInStackLocked(token);
                if (activity == null) {
                    Slog.w(TAG, "Binding with unknown activity: " + token);
                    return 0;
                }
            }
            ......
            // 查找ServiceRecord
           ServiceLookupResult res =
                retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
                        Binder.getCallingUid(), userId, true, callerFg, isBindExternal);
            ......
           try {
                if (unscheduleServiceRestartLocked(s, callerApp.info.uid, false)) {
                    if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "BIND SERVICE WHILE RESTART PENDING: "
                            + s);
                }
    
                if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                    s.lastActivity = SystemClock.uptimeMillis();
                    if (!s.hasAutoCreateConnections()) {
                        // This is the first binding, let the tracker know.
                        ServiceState stracker = s.getTracker();
                        if (stracker != null) {
                            // 记录服务的状态
                            stracker.setBound(true, mAm.mProcessStats.getMemFactorLocked(),
                                    s.lastActivity);
                        }
                    }
                }
    
                mAm.startAssociationLocked(callerApp.uid, callerApp.processName, callerApp.curProcState,
                        s.appInfo.uid, s.name, s.processName);
    
                AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
                ConnectionRecord c = new ConnectionRecord(b, activity,
                        connection, flags, clientLabel, clientIntent);
    
                // 返回BinderProxy对象
                IBinder binder = connection.asBinder();
                ArrayList<ConnectionRecord> clist = s.connections.get(binder);
                if (clist == null) {
                    clist = new ArrayList<ConnectionRecord>();
                    s.connections.put(binder, clist);
                }
                ......
                // BinderProxy以及ConnectionRecord添加到mServiceConnections
                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,
                            permissionsReviewRequired) != null) {
                        return 0;
                    }
                }
                ......
           }
           ......
        }
    

    bindServiceLocked()中的涉及较多的类,简单总结下:

    • IntentBindRecord: 用于bind服务的特定的Intent
    • AppBindRecord: 表示Service和一个客户App的关联
    • ConnectionRecord: 一个特定的连接记录

    bringUpServiceLocked()在分析startService时已经分析过了,下面重点分析下realStartServiceLocked()

        private final void realStartServiceLocked(ServiceRecord r,
                ProcessRecord app, boolean execInFg) throws RemoteException {
            // 参考上文startService中的分析
            ......
            // 请求执行Service的onBind
            requestServiceBindingsLocked(r, execInFg);
            ......
            // bindService时,startRequested = false这样不再请求执行onStartCommand
            if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
                r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                        null, null));
            }
    
            sendServiceArgsLocked(r, execInFg, true);
            ......
        }
    

    下面分析requestServiceBindingsLocked().

        private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
                boolean execInFg, boolean rebind) throws TransactionTooLargeException {
            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);
                    // 调度应用执行onBind
                    r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                            r.app.repProcState);
                    // 参数rebind = false
                    if (!rebind) {
                        i.requested = true;
                    }
                    i.hasBound = true;
                    i.doRebind = false;
                } catch (TransactionTooLargeException e) {
                    // Keep the executeNesting count accurate.
                    if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r, e);
                    final boolean inDestroying = mDestroyingServices.contains(r);
                    serviceDoneExecutingLocked(r, inDestroying, inDestroying);
                    throw e;
                } catch (RemoteException e) {
                    if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r);
                    // Keep the executeNesting count accurate.
                    final boolean inDestroying = mDestroyingServices.contains(r);
                    serviceDoneExecutingLocked(r, inDestroying, inDestroying);
                    return false;
                }
            }
            return true;
        }
    

    scheduleBindService()是个Binder IPC, 最终服务端调用handleBindService()进行处理。

        private void handleBindService(BindServiceData data) {
            // 取出Service对象,服务创建时添加到mServices
            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) {
                            // 执行Service的onBind, 请求AMS publishService
                            IBinder binder = s.onBind(data.intent);
                            // 参数binder为onBind返回的Binder对象
                            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) {
                        throw ex.rethrowFromSystemServer();
                    }
                } catch (Exception e) {
                    if (!mInstrumentation.onException(s, e)) {
                        throw new RuntimeException(
                                "Unable to bind to service " + s
                                + " with " + data.intent + ": " + e.toString(), e);
                    }
                }
            }
        }
    
    

    下面分析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");
                }
                // 调用ActiveServices的publishServiceLocked
                // token为ServiceRecord对象,service为BinderProxy对象(对应onBind返回的Binder对象)
                mServices.publishServiceLocked((ServiceRecord)token, intent, service);
            }
        }
    

    下面分析publishServiceLocked()

        void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
            final long origId = Binder.clearCallingIdentity();
            try {
                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "PUBLISHING " + r
                        + " " + intent + ": " + service);
                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;
                        // 通知所有的client端,服务连接成功
                        for (int conni=r.connections.size()-1; conni>=0; conni--) {
                            ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
                            for (int i=0; i<clist.size(); i++) {
                                ConnectionRecord c = clist.get(i);
                                if (!filter.equals(c.binding.intent.intent)) {
                                    if (DEBUG_SERVICE) Slog.v(
                                            TAG_SERVICE, "Not publishing to: " + c);
                                    if (DEBUG_SERVICE) Slog.v(
                                            TAG_SERVICE, "Bound intent: " + c.binding.intent.intent);
                                    if (DEBUG_SERVICE) Slog.v(
                                            TAG_SERVICE, "Published intent: " + intent);
                                    continue;
                                }
                                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Publishing to: " + c);
                                try {
                                    // 通过Binder IPC通知client端服务已经连接
                                    // c.conn为IServiceConnection.Proxy对象,对应的IServiceConnection.Stub对象
                                    // 为LoadApk中InnerConnection
                                    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);
                                }
                            }
                        }
                    }
    
                    serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
                }
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
        }
    
    

    下面分析InnerConnection的connected()实现。

            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) {
                        // 由ServiceDispatcher分发服务连接状态
                        sd.connected(name, service);
                    }
                }
            }
    

    下面分析ServiceDispatcher的connected()

            public void connected(ComponentName name, IBinder service) {
                if (mActivityThread != null) {
                    // 在UI 线程中处理服务连接状态消息
                    mActivityThread.post(new RunConnection(name, service, 0));
                } else {
                    doConnected(name, service);
                }
            }
    

    UI线程处理消息,调用RunConnection的run()run()中最终调用ServiceDispatcher的doConnected(),我们直接看doConnected()

            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.
                        info = new ConnectionInfo();
                        info.binder = service;
                        info.deathMonitor = new DeathMonitor(name, service);
                        try {
                            // 注册服务死亡通知,这样服务死亡时,调用服务客户端的onServiceDisconnected
                            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;
                        }
                    }
                }
                ......
                // If there is a new service, it is now connected.
                if (service != null) {
                    // 调用自定义的ServiceConnected的onServiceConnected方法
                    // 其中,service为BinderProxy对象,用于通过Binder IPC访问Service
                    mConnection.onServiceConnected(name, service);
                }
            }
    

    小结

    bindService的流程相对复杂,下面总结下bindService的流程。


    参考

    1. https://developer.android.com/guide/components/services.html

    相关文章

      网友评论

        本文标题:Android Service

        本文链接:https://www.haomeiwen.com/subject/vrmevxtx.html