Activity组件之一Service--- startService

来源:互联网 发布:公司活动软文 知乎 编辑:程序博客网 时间:2024/05/01 21:15

关于Activity的四大组件之一Service, 这里面有几样东西可以分析呢?

1. 关于Service的启动,根据不同的需求可以分为有两种:一种是通过调用StartService,另一种就是BindService。

    第一个话题,怎么去使用,然后这两种方法分别是怎么启动的,也就是说启动流程是怎么样的。(代码,UML图)

     有什么区别呢?

2. 关于这两种 不同的方式,Service处理完成事务之后 怎么销毁?

3. 关于Service的ANR会在什么时候产生呢?

4. Service是时候被加载进AMS的,也就是说我要去start一个Service的时候,系统是怎么知道有没有这个Service呢?



第一,关于Service的声明还有如何加载到AMS中。

1. 首先Service必须要在应用的AndroidManifest.xml中申明

<manifest ... >  ...  <application ... >      <service android:name=".ExampleService" />      ...  </application></manifest>

2. PackageManagerService如何去解析呢?

    1) 当我们安装一个apk的时候,PMS会去解析新装的apk的package的一系列的信息。具体的过程需要debug查看代码,我们这里先指关注PackageParser.parsePackage()

    private Package parsePackage(        Resources res, XmlResourceParser parser, int flags, String[] outError)        throws XmlPullParserException, IOException {        ... ...        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {                      if (tagName.equals("application")) {                if (foundApp) {                ... ...                foundApp = true;                if (!parseApplication(pkg, res, parser, attrs, flags, outError)) {                    return null;                }            } else if (tagName.equals("permission")) {               ... ...            } else if (tagName.equals("permission-tree")) {               ... ...            } else if (tagName.equals("uses-permission")) {               ... ...            }        return pkg;    }   
    

    2) PackageParser.parseApplication()

        在parse Manifest中的Application的标签时,如果我们在里面声明了Service就会通过 owner.services.add(s);把这个service添加到对应package的services数组中,然后PMS会去遍历所有的packages中的service,通过mServices.addService(s);把它加到PMS中的mServices的数组中。这样我们的Service便在PMS中有了记录。

在PMS中一个Package就对应一个应用程序,里面记录着apk相关的所有东西,包括package的名字,进程名,里面的Activity,service,receive等等。

    private boolean parseApplication(Package owner, Resources res,            XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)        throws XmlPullParserException, IOException {                 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT                && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {                continue;            }            String tagName = parser.getName();            if (tagName.equals("activity")) {                ... ...                owner.activities.add(a);            } else if (tagName.equals("receiver")) {                ... ...                owner.receivers.add(a);            } else if (tagName.equals("service")) {                Service s = parseService(owner, res, parser, attrs, flags, outError);                if (s == null) {                    mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;                    return false;                }                owner.services.add(s);


第二,通过StartService()去启动一个Service

1. ContextImpl.StartService(Intent service)

   StartService会直接去调用startServiceAsUser,而startServiceAsUser则会通过ActivityManagerNative通过binder去调用AMS的startService()

    @Override    public ComponentName startService(Intent service) {        warnIfCallingFromSystemProcess();        return startServiceAsUser(service, mUser);    }

    @Override    public ComponentName startServiceAsUser(Intent service, UserHandle user) {        try {            service.setAllowFds(false);            ComponentName cn = ActivityManagerNative.getDefault().startService(                mMainThread.getApplicationThread(), service,                service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());             ......            return cn;        } catch (RemoteException e) {            return null;        }    }

2  AMS.startService(IApplicationThread caller, Intent service, String resolvedType, int userId) 

    这个函数中caller就是一个binder对象,

                         servcie就是传过来的Intent

    public ComponentName startService(IApplicationThread caller, Intent service,            String resolvedType, int userId) {        synchronized(this) {            final int callingPid = Binder.getCallingPid();            final int callingUid = Binder.getCallingUid();            checkValidCaller(callingUid, userId);            final long origId = Binder.clearCallingIdentity();            ComponentName res = mServices.startServiceLocked(caller, service,                    resolvedType, callingPid, callingUid, userId);            Binder.restoreCallingIdentity(origId);            return res;        }    }

3. ActiveServices.startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, int userId)

  1) 首先根据caller去查找出与之对应的ProcessRecord对象 callerApp.    

  2)  retrieveServiceLocked(service, resolvedType, callingPid, callingUid, userId, true);   // 

  3) bringUpServiceLocked(r, service.getFlags(), false)  // 

   ComponentName startServiceLocked(IApplicationThread caller,            Intent service, String resolvedType,            int callingPid, int callingUid, int userId) {        if (caller != null) {            final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);        }        ServiceLookupResult res =            retrieveServiceLocked(service, resolvedType,                    callingPid, callingUid, userId, true);        if (res == null) {            return null;        }        ... ...        ServiceRecord r = res.record;        NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked(                callingUid, r.packageName, service, service.getFlags(), null);        if (unscheduleServiceRestartLocked(r)) {            if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);        }        r.startRequested = true;        r.callStart = false;        r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),                service, neededGrants));        r.lastActivity = SystemClock.uptimeMillis();        synchronized (r.stats.getBatteryStats()) {            r.stats.startRunningLocked();        }        String error = bringUpServiceLocked(r, service.getFlags(), false);        if (error != null) {            return new ComponentName("!!", error);        }        return r.name;    }

3.1 ActiveServices.retrieveServiceLocked(Intent service, String resolvedType, int callingPid, int callingUid, int userId,  boolean createIfNeeded)

     1)先在mServiceMap中去查找是否它所在的进程里面已经有这个ServiceRecord了,如果有就直接取出来付给r.

           如果传递过来的service是指定类名的,那么service.getComponent()就不等于null,于是就通过mServiceMap.getServiceByName(service.getComponent(), userId); 去寻找.

         通过IntentFilter到userId对应的进程里面去查找是否已经有了。

     2)如果mServiceMap中还不存在就去new一个新的ServiceRecord

           首先会去通过AppGlobals.getPackageManager().resolveService()(service, resolvedType, ActivityManagerService.STOCK_PM_FLAGS, userId) 到PMS里去查找是有符合Intent的已经在PMS加载过的Service的信息。这个函数会返回一个ResolveInfo。

          如果找到了对应的Service,就会new ServiceRecord(mAm, ss, name, filter, sInfo, res);并且把它放到mServiceMap说明当前已经有这个Service了,最后把找到的这个ServiceRecord封装到new ServiceLookupResult(r, null)中作为一个结果返回。

    private ServiceLookupResult retrieveServiceLocked(Intent service,            String resolvedType, int callingPid, int callingUid, int userId,            boolean createIfNeeded) {        ServiceRecord r = null;        if (service.getComponent() != null) {            r = mServiceMap.getServiceByName(service.getComponent(), userId);        }        if (r == null) {            Intent.FilterComparison filter = new Intent.FilterComparison(service);            r = mServiceMap.getServiceByIntent(filter, userId);        }        if (r == null) {            try {                ResolveInfo rInfo =                    AppGlobals.getPackageManager().resolveService(                                service, resolvedType,                                ActivityManagerService.STOCK_PM_FLAGS, userId);                ServiceInfo sInfo =                    rInfo != null ? rInfo.serviceInfo : null;                ... ...                ComponentName name = new ComponentName(                        sInfo.applicationInfo.packageName, sInfo.name);                if (userId > 0) {                    if (mAm.isSingleton(sInfo.processName, sInfo.applicationInfo,                            sInfo.name, sInfo.flags)) {                        userId = 0;                    }                    sInfo = new ServiceInfo(sInfo);                    sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId);                }                r = mServiceMap.getServiceByName(name, 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);                    }                    r = new ServiceRecord(mAm, ss, name, filter, sInfo, res);                    res.setService(r);                    mServiceMap.putServiceByName(name, UserHandle.getUserId(r.appInfo.uid), r);                    mServiceMap.putServiceByIntent(filter, UserHandle.getUserId(r.appInfo.uid), r);                    // Make sure this component isn't in the pending list.                    int N = mPendingServices.size();                    for (int i=0; i<N; i++) {                        ServiceRecord pr = mPendingServices.get(i);                        if (pr.serviceInfo.applicationInfo.uid == sInfo.applicationInfo.uid                                && pr.name.equals(name)) {                            mPendingServices.remove(i);                            i--;                            N--;                        }                    }                }            } catch (RemoteException ex) {                // pm is in same process, this will never happen.            }        }        if (r != null) {            if (mAm.checkComponentPermission(r.permission,                    callingPid, callingUid, r.appInfo.uid, r.exported)                    != PackageManager.PERMISSION_GRANTED) {                if (!r.exported) {                    Slog.w(TAG, "Permission Denial: Accessing service " + r.name                            + " from pid=" + callingPid                            + ", uid=" + callingUid                            + " that is not exported from uid " + r.appInfo.uid);                    return new ServiceLookupResult(null, "not exported from uid "                            + r.appInfo.uid);                }                Slog.w(TAG, "Permission Denial: Accessing service " + r.name                        + " from pid=" + callingPid                        + ", uid=" + callingUid                        + " requires " + r.permission);                return new ServiceLookupResult(null, r.permission);            }            return new ServiceLookupResult(r, null);        }        return null;    }


3.3 ActiveServices.bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean whileRestarting)

     获取ServiceRecord所在的application是否已经启动,如果启动了就直接调用realStartServiceLocked(r, app); 如果没有启动就先去mAm.startProcessLocked启动对应的process,然后把需要start的service添加到mPendingServices中,等到进程起来之后会调用attachApplicationLocked去启动相应的service,当然还是调用realStartServiceLocked(sr, proc);

    private final String bringUpServiceLocked(ServiceRecord r,            int intentFlags, boolean whileRestarting) {                ... ...        if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);        ... ...        // Make sure that the user who owns this service is started.  If not,        // we don't want to allow it to run.        if (mAm.mStartedUsers.get(r.userId) == null) {            String msg = "Unable to launch app "                    + r.appInfo.packageName + "/"                    + r.appInfo.uid + " for service "                    + r.intent.getIntent() + ": user " + r.userId + " is stopped";            Slog.w(TAG, msg);            bringDownServiceLocked(r, true);            return msg;        }        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);            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);                    realStartServiceLocked(r, app);                    return null;                } catch (RemoteException e) {                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);                }                // If a dead object exception was thrown -- fall through to                // restart the application.            }        } 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) {            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,                    "service", r.name, false, isolated)) == 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, true);                return msg;            }            if (isolated) {                r.isolatedProc = app;            }        }        if (!mPendingServices.contains(r)) {            mPendingServices.add(r);        }        return null;    }

3.3.1  ActiveService.realStartServiceLocked(ServiceRecord r, ProcessRecord app)

     1) app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo)); 通过app.thread.scheduleCreateService去调用ActivityThread的scheduleCreateService。在ActivityThread的中通过handle去发送和处理“CREATE_SERVICE”的消息。调用handleCreateService

         

     2)  requestServiceBindingLock()  //这个函数在BindService的时候才会起作用 

     3)  sendServiceArgsLocked(r, true); //处理传递给Service的Intent带来的参数

    private final void realStartServiceLocked(ServiceRecord r,            ProcessRecord app) throws RemoteException {        r.app = app;        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();        app.services.add(r);        bumpServiceExecutingLocked(r, "create");        mAm.updateLruProcessLocked(app, true);        boolean created = false;        try {            mAm.mStringBuilder.setLength(0);            r.intent.getIntent().toShortString(mAm.mStringBuilder, true, false, true, false);            EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,                    r.userId, System.identityHashCode(r), r.shortName,                    mAm.mStringBuilder.toString(), r.app.pid);            synchronized (r.stats.getBatteryStats()) {                r.stats.startLaunchedLocked();            }            mAm.ensurePackageDexOpt(r.serviceInfo.packageName);            app.thread.scheduleCreateService(r, r.serviceInfo,                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));            r.postNotification();            created = true;        } finally {          ... ...        }        requestServiceBindingsLocked(r);        // 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));        }        sendServiceArgsLocked(r, true);    }

3.3.1.1 ActivityThread.handleCreateService()

      在Client端,实例化对应的Service并通过attach,把相关的属性给它。通过mServices.put(data.token, service);把自己加到当前进程的mServices中。

     此时就会调用service.onCreate(); 并且通过mServices.put(data.token, service); 把ActiveServices里面的ServiceRecord传过来的Token与本地Service对象放到mServices的Map中。

     最后会通过ActivityManagerNative.getDefault().serviceDoneExecuting(token, 0, 0, 0);去通知ActiveServices。

    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.        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) {            ... ...        }        try {            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);            ContextImpl context = new ContextImpl();            context.init(packageInfo, null, this);            Application app = packageInfo.makeApplication(false, mInstrumentation);            context.setOuterContext(service);            service.attach(context, this, data.info.name, data.token, app,                    ActivityManagerNative.getDefault());            service.onCreate();            mServices.put(data.token, service);            try {                ActivityManagerNative.getDefault().serviceDoneExecuting(                        data.token, 0, 0, 0);            } catch (RemoteException e) {                // nothing to do.            }        } catch (Exception e) {            ... ...        }    }


3.3.1.3 ActiveServices.sendServiceArgsLocked(ServiceRecord r,boolean oomAdjusted)

     在startServiceLocked函数中bringupService之前,已经调用了r.pendingStarts.add去添加了一个pendingStarts,所以这里的pendingStarts.size()是大于0的。

     1. 通过r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent); 发送Message给Client端处理。

    private final void sendServiceArgsLocked(ServiceRecord r,            boolean oomAdjusted) {        final int N = r.pendingStarts.size();        if (N == 0) {            return;        }        while (r.pendingStarts.size() > 0) {            try {                ServiceRecord.StartItem si = r.pendingStarts.remove(0);                si.deliveredTime = SystemClock.uptimeMillis();                r.deliveredStarts.add(si);                si.deliveryCount++;                if (si.neededGrants != null) {                    mAm.grantUriPermissionUncheckedFromIntentLocked(si.neededGrants,                            si.getUriPermissionsLocked());                }                int flags = 0;                if (si.deliveryCount > 1) {                    flags |= Service.START_FLAG_RETRY;                }                if (si.doneExecutingCount > 0) {                    flags |= Service.START_FLAG_REDELIVERY;                }                r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);            } catch (RemoteException e) {               ....        }    }

3.3.1.3.1 ActivityThread.handleServiceArgs(ServiceArgsData data)

    1. 调用s.onStartCommand去做相关的操作,onStartCommand会返回一个integer. The integer is a value that describes how the system should continue the service in the event that the system kills it.  

     2. 告诉AMS已经完成了ActivityManagerNative.getDefault().serviceDoneExecuting(data.token, 1, data.startId, res); 在ActiveServices.serviceDoneExecutingLocked中会对onStartCommand返回的值作出对应的处理。

    private void handleServiceArgs(ServiceArgsData data) {        Service s = mServices.get(data.token);        if (s != null) {            try {                if (data.args != null) {                    data.args.setExtrasClassLoader(s.getClassLoader());                }                int res;                if (!data.taskRemoved) {                    res = s.onStartCommand(data.args, data.flags, data.startId);                } else {                    s.onTaskRemoved(data.args);                    res = Service.START_TASK_REMOVED_COMPLETE;                }                QueuedWork.waitToFinish();                try {                    ActivityManagerNative.getDefault().serviceDoneExecuting(                            data.token, 1, data.startId, res);                } catch (RemoteException e) {                    // nothing to do.                }                ensureJitEnabled();            } catch (Exception e) {                if (!mInstrumentation.onException(s, e)) {                    throw new RuntimeException(                            "Unable to start service " + s                            + " with " + data.args + ": " + e.toString(), e);                }            }        }    }

ActiveServices.serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) 


    void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {        boolean inStopping = mStoppingServices.contains(r);        if (r != null) {            if (type == 1) {                // This is a call from a service start...  take care of                // book-keeping.                r.callStart = true;                switch (res) {                    case Service.START_STICKY_COMPATIBILITY:                    case Service.START_STICKY: {                        // We are done with the associated start arguments.                        r.findDeliveredStart(startId, true);                        // Don't stop if killed.                        r.stopIfKilled = false;                        break;                    }                    case Service.START_NOT_STICKY: {                        // We are done with the associated start arguments.                        r.findDeliveredStart(startId, true);                        if (r.getLastStartId() == startId) {                            // There is no more work, and this service                            // doesn't want to hang around if killed.                            r.stopIfKilled = true;                        }                        break;                    }                    case Service.START_REDELIVER_INTENT: {                        // We'll keep this item until they explicitly                        // call stop for it, but keep track of the fact                        // that it was delivered.                        ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);                        if (si != null) {                            si.deliveryCount = 0;                            si.doneExecutingCount++;                            // Don't stop if killed.                            r.stopIfKilled = true;                        }                        break;                    }                    case Service.START_TASK_REMOVED_COMPLETE: {                        // Special processing for onTaskRemoved().  Don't                        // impact normal onStartCommand() processing.                        r.findDeliveredStart(startId, true);                        break;                    }                    default:                        throw new IllegalArgumentException(                                "Unknown service start result: " + res);                }                if (res == Service.START_STICKY_COMPATIBILITY) {                    r.callStart = false;                }            }            final long origId = Binder.clearCallingIdentity();            serviceDoneExecutingLocked(r, inStopping);            Binder.restoreCallingIdentity(origId);        } else {            Slog.w(TAG, "Done executing unknown service from pid "                    + Binder.getCallingPid());        }    }

serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) 

    private void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {        if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r                + ": nesting=" + r.executeNesting                + ", inStopping=" + inStopping + ", app=" + r.app);        else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);        r.executeNesting--;        if (r.executeNesting <= 0 && r.app != null) {            if (DEBUG_SERVICE) Slog.v(TAG,                    "Nesting at 0 of " + r.shortName);            r.app.executingServices.remove(r);            if (r.app.executingServices.size() == 0) {                if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,                        "No more executingServices of " + r.shortName);                mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);            }            if (inStopping) {                if (DEBUG_SERVICE) Slog.v(TAG,                        "doneExecuting remove stopping " + r);                mStoppingServices.remove(r);                r.bindings.clear();            }            mAm.updateOomAdjLocked(r.app);        }    }


到此StartService()启动结束,startService会返回一个ComponentName,而这个实际上就是ServiceRecord.name。


4. stopService

   如果一个service通过start开始,想要destroy它只有两个方法,一个是通过调用自己的stopSelf(), 另一个就是通过ContextImpl.stopService(Intent service).

   而这两个方法最终会走到ActiveServices的stopServiceTokenLocked 和 stopServiceLocked, 这两个方法都是去查找在ActivieServices中对应的ServiceRecord,找到之后最终调用bringDownServiceLocked去destroy相关的工作。

  1. r.app.thread.scheduleStopService(r);  通过Binder调用Client端的销毁工作。

    private final void bringDownServiceLocked(ServiceRecord r, boolean force) {        ... ...        if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);        EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,                r.userId, System.identityHashCode(r), r.shortName,                (r.app != null) ? r.app.pid : -1);        mServiceMap.removeServiceByName(r.name, r.userId);        mServiceMap.removeServiceByIntent(r.intent, r.userId);        r.totalRestartCount = 0;        unscheduleServiceRestartLocked(r);        // Also make sure it is not on the pending list.        int N = mPendingServices.size();        for (int i=0; i<N; i++) {            if (mPendingServices.get(i) == r) {                mPendingServices.remove(i);                if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);                i--;                N--;            }        }        r.cancelNotification();        r.isForeground = false;        r.foregroundId = 0;        r.foregroundNoti = null;        // Clear start entries.        r.clearDeliveredStartsLocked();        r.pendingStarts.clear();        if (r.app != null) {            synchronized (r.stats.getBatteryStats()) {                r.stats.stopLaunchedLocked();            }            r.app.services.remove(r);            if (r.app.thread != null) {                try {                    bumpServiceExecutingLocked(r, "stop");                    mStoppingServices.add(r);                    mAm.updateOomAdjLocked(r.app);                    r.app.thread.scheduleStopService(r);                } catch (Exception e) {                    Slog.w(TAG, "Exception when stopping service "                            + r.shortName, e);                    serviceDoneExecutingLocked(r, true);                }                updateServiceForegroundLocked(r.app, false);            } else {                if (DEBUG_SERVICE) Slog.v(                    TAG, "Removed service that has no process: " + r);            }        } else {            if (DEBUG_SERVICE) Slog.v(                TAG, "Removed service that is not running: " + r);        }        ... ...    }

4.1 ActivityThread.handleStopService()

      调用s.onDestroy() 

    private void handleStopService(IBinder token) {        Service s = mServices.remove(token);        if (s != null) {            try {                if (localLOGV) Slog.v(TAG, "Destroying service " + s);                s.onDestroy();                Context context = s.getBaseContext();                if (context instanceof ContextImpl) {                    final String who = s.getClassName();                    ((ContextImpl) context).scheduleFinalCleanup(who, "Service");                }                try {                    ActivityManagerNative.getDefault().serviceDoneExecuting(                            token, 0, 0, 0);                } catch (RemoteException e) {                    // nothing to do.                }            } catch (Exception e) {                ... ...            }        }        //Slog.i(TAG, "Running services: " + mServices);    }



 


原创粉丝点击