美文网首页
【源码解析】Service的启动过程

【源码解析】Service的启动过程

作者: AndroidHint | 来源:发表于2018-12-03 19:54 被阅读0次

    一、前言

    我们知道Service一般有两种工作状态,一种是启动状态,一种是绑定状态
    启动状态的Service是这样生成的:

    Intent intent = new Intent(this, MyService.class);
    startService(intent);
    

    绑定状态的Service是这样生成的:

    Intent intent = new Intent(this, MyService.class);
    bindService(intent, mServiceConnection, BIND_ATUO_CREATE);
    

    针对这两种Service,我们从源码的角度分析一下两种工作状态的区别。

    以下源码分析是基于Android SDK 27

    二、启动状态的Service

    从启动状态的Service的生成代码中可以知道,入口是ContextImpl的startService方法,如下所示。

    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, false, mUser);
    }
    

    startService方法调用了startServiceCommon方法,如下所示。

    private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess(this);
            //调用了AMS的startService方法
            ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            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());
                } else if (cn.getPackageName().equals("?")) {
                    throw new IllegalStateException(
                            "Not allowed to start service " + service + ": " + cn.getClassName());
                }
            }
            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
    

    startServiceCommon方法又通过ActivityManager.getService()对象调用了startService方法。而ActivityManager.getService()对象就是ActivityManagerService服务(AMS)。我们转到ActivityManagerService的startService方法,如下所示。

    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, 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 + " fg=" + requireForeground);
        synchronized(this) {
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            ComponentName res;
            try {
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return res;
        }
    }
    

    在上面的代码中,AMS通过了mServices这个对象,调用了mServices的startServiceLocked方法,而mServices是ActiveServices类型,它的startServiceLocked方法如下所示。

    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
            throws TransactionTooLargeException {
        final boolean callerFg;
        if (caller != null) {
            final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
            if (callerApp == null) {
                throw new SecurityException();
            }
            callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
        } else {
            callerFg = true;
        }
    
        ...省略
    
        ServiceRecord r = res.record;
    
        if (!r.startRequested && !fgRequired) {
            final int allowed = mAm.getAppStartModeLocked(r.appInfo.uid, r.packageName,
                    r.appInfo.targetSdkVersion, callingPid, false, false);
            ...省略
        }
    
        NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked(
                callingUid, r.packageName, service, service.getFlags(), null, r.userId);
    
        if (mAm.mPermissionReviewRequired) {
            if (!requestStartTargetPermissionsReviewIfNeededLocked(r, callingPackage,
                    callingUid, service, callerFg, userId)) {
                return null;
            }
        }
    
        if (unscheduleServiceRestartLocked(r, callingUid, false)) {
            ...省略
        }
        ...省略
        if (!callerFg && !fgRequired && r.app == null
                && mAm.mUserController.hasStartedUserState(r.userId)) {
            ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);
            if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) {
                ...省略
                addToStarting = true;
            } else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) {
                addToStarting = true;
            } else if (DEBUG_DELAYED_STARTS) {
                ...省略
            }
        } else if (DEBUG_DELAYED_STARTS) {
            ...省略
        }
    
        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        return cmp;
    }
    

    为了能关注重点代码,我们将部分代码逻辑省略掉了。最终ActiveServices的startServiceLocked方法调用了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);
        }
    
        ...省略
    
        return r.name;
    }
    

    startServiceInnerLocked方法继续调用了ActiveServices的内部方法——bringUpServiceLocked,而bringUpServiceLocked方法又继续调用了realStartServiceLocked方法。如下所示。

    private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        ...省略
    
        boolean created = false;
        try {
            ...省略
            mAm.notifyPackageUse(r.serviceInfo.packageName,
                                 PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
            app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
            r.postNotification();
            created = true;
        } catch (DeadObjectException e) {
            Slog.w(TAG, "Application dead when creating service " + r);
            mAm.appDiedLocked(app);
            throw e;
        } finally {
            ...省略
        }
    
        if (r.whitelistManager) {
            app.whitelistManager = true;
        }
    
        requestServiceBindingsLocked(r, execInFg);
    
        updateServiceClientActivitiesLocked(app, null, true);
    
        if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                    null, null, 0));
        }
    
        sendServiceArgsLocked(r, execInFg, true);
    
        ...省略
    }
    

    在上面的方法中,通过调用app.thread对象的scheduleCreateService方法来创建Service。而app.thread对象是ActivityThread类型的。所以,创建Service就转化到了ActivityThread的scheduleCreateService方法,如下所示。

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

    scheduleCreateService方法中,通过sendMessage方法,发送了一个通知,其处理者是ActivityThread的内部类H,H继承了Handler,其中的handleMessage方法处理了上面的通知。在handleMessage方法中,对于H.CREATE_SERVICE的处理,如下所示。

    case CREATE_SERVICE:
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
        handleCreateService((CreateServiceData)msg.obj);
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        break;
    

    上面的逻辑中,调用了handleCreateService方法,如下所示。

    private void handleCreateService(CreateServiceData data) {
        unscheduleGcIdler();
    
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
            //1、使用反射的形式创建了Service对象
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = (Service) cl.loadClass(data.info.name).newInstance();
        } catch (Exception e) {
            
        }
    
        try {
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);
            //2、如果Application对象没有创建,则创建一个Application对象。在其中调用了Application的生命周期方法
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            //3、调用Service对象的attach方法
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            //4、调用Service对象的onCreate方法
            service.onCreate();
            mServices.put(data.token, service);
            try {
                ActivityManager.getService().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);
            }
        }
    }
    

    上面的代码中,主要执行了以下几个步骤。
    1、使用了反射的形式创建了Service对象。
    2、如果Application对象没有创建,则创建Application对象,并调用其中的生命周期函数。
    3、调用Service对象的attach生命周期方法。
    4、调用Service对象的onCreate生命周期方法。

    至此,启动状态的Service已经创建并运行起来了。而它的销毁过程其实和创建过程的流程差不多,最终都是在ActivityThread中执行相关的逻辑。这里就不再详细分析。我们接下来说一下绑定状态下的Service的工作过程。

    三、绑定状态的Service

    从绑定状态的Service的生成代码中可以知道,入口是ContextImpl的bindService方法,如下所示。

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

    ContextImpl中的bindService方法调用了bindServiceCommon方法,如下所示。

    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
            handler, UserHandle user) {
        // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
        IServiceConnection sd;
        if (conn == null) {
            throw new IllegalArgumentException("connection is null");
        }
        if (mPackageInfo != null) {
            //1、传入ServiceConnection对象获取一个IServiceConnection对象
            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);
            //2、调用了AMS的bindService方法
            int res = ActivityManager.getService().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) {
            throw e.rethrowFromSystemServer();
        }
    }
    

    上面的代码中,调用了ActivityManager.getService()对象的bindService方法。前面我们分析启动状态的Service时,就知道了ActivityManager.getService()对象是一个ActivityManagerService(AMS)对象,所以我们转到了ActivityManagerService的bindService方法,如下所示。

    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) {
            return mServices.bindServiceLocked(caller, token, service,
                    resolvedType, connection, flags, callingPackage, userId);
        }
    }
    

    ActivityManagerService的bindService方法中,使用了mServices的bindServiceLocked方法。而mServices对象是ActiveServices类型的。所以ActiveServices的bindServiceLocked方法如下所示。

    int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, final IServiceConnection connection, int flags,
            String callingPackage, final int userId) throws TransactionTooLargeException {
        ...省略
    
        ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
                    Binder.getCallingUid(), userId, true, callerFg, isBindExternal);
        ...省略
        //记住ServiceRecord这个对象,特别重要
        ServiceRecord s = res.record;
    
        boolean permissionsReviewRequired = false;
    
        // If permissions need a review before any of the app components can run,
        // we schedule binding to the service but do not start its process, then
        // we launch a review activity to which is passed a callback to invoke
        // when done to start the bound service's process to completing the binding.
        if (mAm.mPermissionReviewRequired) {
            if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(
                    s.packageName, s.userId)) {
    
                permissionsReviewRequired = true;
    
                final ServiceRecord serviceRecord = s;
                final Intent serviceIntent = service;
    
                RemoteCallback callback = new RemoteCallback(
                        new RemoteCallback.OnResultListener() {
                    @Override
                    public void onResult(Bundle result) {
                        synchronized(mAm) {
                            final long identity = Binder.clearCallingIdentity();
                            try {
                                if (!mAm.getPackageManagerInternalLocked()
                                        .isPermissionsReviewRequired(
                                                serviceRecord.packageName,
                                                serviceRecord.userId)) {
                                    try {
                                        //这里的serviceRecord对象就是上面的s
                                        bringUpServiceLocked(serviceRecord,
                                                serviceIntent.getFlags(),
                                                callerFg, false, false);
                                    } catch (RemoteException e) {
                                        /* ignore - local call */
                                    }
                                } else {
                                    unbindServiceLocked(connection);
                                }
                            } finally {
                                Binder.restoreCallingIdentity(identity);
                            }
                        }
                    }
                });
    
                mAm.mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        mAm.mContext.startActivityAsUser(intent, new UserHandle(userId));
                    }
                });
            }
        }
    
        final long origId = Binder.clearCallingIdentity();
    
        try {     
            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);
            // Once the apps have become associated, if one of them is caller is ephemeral
            // the target app should now be able to see the calling app
            mAm.grantEphemeralAccessLocked(callerApp.userId, service,
                    s.appInfo.uid, UserHandle.getAppId(callerApp.uid));
    
            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
            //记住这个ConnectionRecord对象,后面绑定Service对象时会出现该对象
            //这个ConnectionRecord对象存储了connection对象,即IServiceConnection对象。
            ConnectionRecord c = new ConnectionRecord(b, activity,
                    connection, flags, clientLabel, clientIntent);
            //这里的connection是ServiceDispatcher的内部类InnerConnection,而InnerConnection继承了IServiceConnection.Stub
            IBinder binder = connection.asBinder();
            //s是ServiceRecord类型的对象,不要忘记了。
            //s.connections是一个ArrayMap对象,它存储了一个ArrayList,这里的ArrayList是clist。
            //而clist又存储了ConnectionRecord对象。而ConnectionRecord对象又存储了connection参数。
            //而connection参数是一个IServiceConnection对象,也就是上面说过的InnerConnection对象。
            ArrayList<ConnectionRecord> clist = s.connections.get(binder);
            if (clist == null) {
                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 ((c.flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
                s.whitelistManager = 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,
                        permissionsReviewRequired) != null) {
                    return 0;
                }
            }
    
            ...省略
    
            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, false);
                } 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);
            }
    
            getServiceMapLocked(s.userId).ensureNotStartingBackgroundLocked(s);
    
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    
        return 1;
    }
    

    在ActiveServices的bindServiceLocked方法中,又调用了ActiveServices的内部方法——bringUpServiceLocked,而bringUpServiceLocked又调用了realStartServiceLocked方法,如下所示。

    private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        ...省略
        r.app = app;
        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
    
        final boolean newService = app.services.add(r);
        bumpServiceExecutingLocked(r, execInFg, "create");
        mAm.updateLruProcessLocked(app, false, null);
        updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
        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;
                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);
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
            r.postNotification();
            created = true;
        } catch (DeadObjectException e) {
            Slog.w(TAG, "Application dead when creating service " + r);
            mAm.appDiedLocked(app);
            throw e;
        } finally {
            if (!created) {
                // Keep the executeNesting count accurate.
                final boolean inDestroying = mDestroyingServices.contains(r);
                serviceDoneExecutingLocked(r, inDestroying, inDestroying);
    
                // Cleanup.
                if (newService) {
                    app.services.remove(r);
                    r.app = null;
                }
    
                // Retry.
                if (!inDestroying) {
                    scheduleServiceRestartLocked(r, false);
                }
            }
        }
    
        if (r.whitelistManager) {
            app.whitelistManager = true;
        }
    
        requestServiceBindingsLocked(r, execInFg);
    
        updateServiceClientActivitiesLocked(app, null, true);
    
        // If the service is in the started state, and there are no
        // pending arguments, then fake up one so its onStartCommand() will
        // be called.
        if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                    null, null, 0));
        }
    
        sendServiceArgsLocked(r, execInFg, true);
    
        if (r.delayed) {
            if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r);
            getServiceMapLocked(r.userId).mDelayedStartList.remove(r);
            r.delayed = false;
        }
    
        if (r.delayedStop) {
            // Oh and hey we've already been asked to stop!
            r.delayedStop = false;
            if (r.startRequested) {
                if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
                        "Applying delayed stop (from start): " + r);
                stopServiceLocked(r);
            }
        }
    }
    

    上面的代码中,通过app.thread对象的scheduleCreateService方法创建了Service对象。我们已经知道app.thread是ActivityThread对象,所以这里是调用了ActivityThread的scheduleCreateService方法,如下所示。

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

    这个scheduleCreateService方法和上面我们分析的启动状态的Service的创建方法是一样的,最后都是通过反射的形式创建了Service对象,并调用了Service对象的attach、onCreate等生命周期方法。

    如果仅到此为止,启动状态的Service和绑定状态的Service就没什么区别了。但是既然官方给定了两种不同状态的Service,它们之间肯定存在着区别的。

    我们回溯到之前已经分析过的代码,终于在ActiveServices的realStartServiceLocked方法中看到,它在执行了app.thread.scheduleCreateService创建Service对象后,接着执行了requestServiceBindingsLocked方法,如下所示。

    private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
            throws TransactionTooLargeException {
        for (int i=r.bindings.size()-1; i>=0; i--) {
            IntentBindRecord ibr = r.bindings.valueAt(i);
            if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
                break;
            }
        }
    }
    

    Note:启动状态的Service也会调用requestServiceBindingsLocked这个方法,但是其中的r.bindings.size为空,因此不能往下执行逻辑。

    对于绑定状态的Service来说,ActiveServices的requestServiceBindingsLocked方法中又执行了ActiveServices的requestServiceBindingLocked方法,如下所示。

    private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
        ...省略
        if ((!i.requested || rebind) && i.apps.size() > 0) {
            try {
                bumpServiceExecutingLocked(r, execInFg, "bind");
                r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
                //绑定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 (TransactionTooLargeException e) {
                
            } catch (RemoteException e) {
                
            }
        }
        return true;
    }
    

    上面的代码中调用了r.app.thread的scheduleBindService方法,而r.app.thread是一个ActivityThread对象,其中的scheduleBindService方法如下所示。

    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;
    
        sendMessage(H.BIND_SERVICE, s);
    }
    

    scheduleBindService方法通过调用sendMessage方法,发送了一个消息给ActivityThread的内部类H处理,其处理逻辑如下所示。

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

    在内部类H的handleMessage方法中,对于H.BIND_SERVICE的处理是调用了handleBindService方法,如下所示。

    private void handleBindService(BindServiceData data) {
        //从mServices获取上面创建的Service对象
        Service s = mServices.get(data.token); 
        if (s != null) {
            try {
                data.intent.setExtrasClassLoader(s.getClassLoader());
                data.intent.prepareToEnterProcess();
                try {
                    if (!data.rebind) { //第一次绑定时的逻辑
                        //执行Service对象的onBind方法,onBind方法返回一个IBinder对象
                        IBinder binder = s.onBind(data.intent);
                        //将onBind方法返回的IBinder对象作为参数,调用AMS的publishService方法
                        ActivityManager.getService().publishService(
                                data.token, data.intent, binder);
                    } else {
                        s.onRebind(data.intent);
                        ActivityManager.getService().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                    }
                    ensureJitEnabled();
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            } catch (Exception e) {
                
            }
        }
    }
    

    handleBindService方法主要做了以下几件事:
    1、从mServices这个变量中获取一个Service对象,该Service对象就是我们上面创建过的。
    2、调用Service对象的onBind方法,该方法返回了一个IBinder对象。该IBinder对象可以简单理解为是Service的逻辑处理
    3、调用了ActivityManagerService(AMS)的publishService方法,将该IBinder对象作为参数传递进去。
    我们接着看AMS的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);
        }
    }
    

    上面的代码中调用了ActiveServices的publishServiceLocked方法,如下所示。

    void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
        final long origId = Binder.clearCallingIdentity();
        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;
                    //ServiceRecord的connections是一个ArrayMap对象。
                    //遍历该ArrayMap对象的Value值,Value值是一个ArrayList对象
                    //遍历ArrayList对象,获取每一个ConnectionRecord对象,通过filter找到
                    //相应的ConnectionRecord对象
                    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)) {
                                continue;
                            }
                            try {
                                //c是ConnectionRecord对象,其中的conn是InnerConnection
                                //对象,这里实际上是调用了InnerConnection的connected方法。
                                c.conn.connected(r.name, service, false);
                            } catch (Exception e) {
                            }
                        }
                    }
                }
    
                serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }
    

    上面的注释提到,在try方法块中调用了c.conn对象的connected方法,而c.conn对象是InnerConnection对象。所以我们转到InnerConnection对象的connected方法,如下所示。

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

    上面的代码首先通过mDispatcher对象获取了LoadedApk的内部类ServiceDispatcher对象,然后调用了该对象的connected方法。如下所示。

    public void connected(ComponentName name, IBinder service, boolean dead) {
        if (mActivityThread != null) {
            mActivityThread.post(new RunConnection(name, service, 0, dead));
        } else {
            doConnected(name, service, dead);
        }
    }   
    

    上面的connected方法中有两个分支,而不论哪个分支,最终都会执行到doConnected方法,所以我们直接看doConnected方法的逻辑,如下所示。

    public void doConnected(ComponentName name, IBinder service, boolean dead) {
        ServiceDispatcher.ConnectionInfo old;
        ServiceDispatcher.ConnectionInfo info;
    
        synchronized (this) {
            old = mActiveConnections.get(name);
            //Service已经绑定过了
            if (old != null && old.binder == service) {
                // Huh, already have this one.  Oh well!
                return;
            }
            //将新的Service信息存储起来
            if (service != null) {
                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) {
                    mActiveConnections.remove(name);
                    return;
                }
            } else {
                mActiveConnections.remove(name);
            }
            if (old != null) {
                old.binder.unlinkToDeath(old.deathMonitor, 0);
            }
        }
    
        ///将旧的Service进行解绑的操作
        if (old != null) {
            mConnection.onServiceDisconnected(name);
        }
        if (dead) {
            mConnection.onBindingDied(name);
        }
        //调用mConnection对象的onServiceConnected方法绑定新的Service
        //这里的mConnection就是ServiceConnection对象,也即是我们最开始调用bindService方法时
        //传进来的参数。这里的service参数就是Service服务的onBind方法返回的IBinder对象。
        if (service != null) {
            mConnection.onServiceConnected(name, service);
        }
    }
    

    上面的代码中,如果是第一次连接,会走到最后的mConnection的onServiceConnected方法。这里的mConnection对象就是ServiceConnection对象,也就是我们最开始调用bindService传进来的参数。

    这里看一个调用bindService方法的小例子:

    bindService(intent, new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            bookManager = IBookManager.Stub.asInterface(service);
        }
    
        @Override
        public void onServiceDisconnected(ComponentName name) {
            bookManager = null;
        }
    }, BIND_AUTO_CREATE);
    

    可以看到ServiceConnection的onServiceConnected方法,传进来的第二个参数service是IBinder对象,也就是我们上面分析的Service的onBind方法返回的IBinder对象。通过该IBinder对象,我们可以实现Activity和Service(本地Service或者远程Service)之间的交互。

    至此,Service的两种状态的工作过程都分析完毕了。这里先抛出两个问题流到后续再讨论:
    1、为什么使用bindService方法时,Activity和Service是绑定起来的,当Activity被销毁,Service也会跟着被销毁?
    2、Activity和Service的交互,Service可以是本地的或者是跨进程的,两者之间有什么区别?

    相关文章

      网友评论

          本文标题:【源码解析】Service的启动过程

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