美文网首页android之基础学习攻克
Service相关流程学习-Unbouned Stop Serv

Service相关流程学习-Unbouned Stop Serv

作者: weiinter105 | 来源:发表于2018-11-26 23:30 被阅读0次

Service stopService-Unbounded Service

ContextImpl#stopService

1480    @Override
1481    public boolean stopService(Intent service) {
1482        warnIfCallingFromSystemProcess();
1483        return stopServiceCommon(service, mUser);
1484    }

ContextImpl#stopServiceCommon

1530    private boolean stopServiceCommon(Intent service, UserHandle user) {
1531        try {
1532            validateServiceIntent(service);
1533            service.prepareToLeaveProcess(this);
1534            int res = ActivityManager.getService().stopService(
1535                mMainThread.getApplicationThread(), service,
1536                service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
1537            if (res < 0) {
1538                throw new SecurityException(
1539                        "Not allowed to stop service " + service);
1540            }
1541            return res != 0;
1542        } catch (RemoteException e) {
1543            throw e.rethrowFromSystemServer();
1544        }
1545    }

ActivityManagerService#stopService

18776
18777    @Override
18778    public int stopService(IApplicationThread caller, Intent service,
18779            String resolvedType, int userId) {
18780        enforceNotIsolatedCaller("stopService");
18781        // Refuse possible leaked file descriptors
18782        if (service != null && service.hasFileDescriptors() == true) {
18783            throw new IllegalArgumentException("File descriptors passed in Intent");
18784        }
18785
18786        synchronized(this) {
18787            return mServices.stopServiceLocked(caller, service, resolvedType, userId);
18788        }
18789    }

ActiveServices#stopServiceLocked

631    int stopServiceLocked(IApplicationThread caller, Intent service,
632            String resolvedType, int userId) {
633        if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "stopService: " + service
634                + " type=" + resolvedType);
635
636        final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
637        if (caller != null && callerApp == null) {
638            throw new SecurityException(
639                    "Unable to find app for caller " + caller
640                    + " (pid=" + Binder.getCallingPid()
641                    + ") when stopping service " + service);
642        }
643
644        // If this service is active, make sure it is stopped.
645        ServiceLookupResult r = retrieveServiceLocked(service, resolvedType, null,
646                Binder.getCallingPid(), Binder.getCallingUid(), userId, false, false, false); //找到要stop的ServiceRecord
647        if (r != null) {
648            if (r.record != null) {
649                final long origId = Binder.clearCallingIdentity();
650                try {
651                    stopServiceLocked(r.record);
652                } finally {
653                    Binder.restoreCallingIdentity(origId);
654                }
655                return 1;
656            }
657            return -1;
658        }
659
660        return 0;
661    }
600    private void stopServiceLocked(ServiceRecord service) {
601        if (service.delayed) { //如果stop的Service当前还是delay状态(如kill Service所在进程时这个Service在delay的队列里)
602            // If service isn't actually running, but is is being held in the
603            // delayed list, then we need to keep it started but note that it
604            // should be stopped once no longer delayed.
605            if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Delaying stop of pending: " + service);
606            service.delayedStop = true; //设置delayStop的属性为true
607            return;
608        }
609        synchronized (service.stats.getBatteryStats()) {
610            service.stats.stopRunningLocked();
611        }
612        service.startRequested = false; //更新ServiceRecord的状态信息
613        if (service.tracker != null) {
614            service.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(),
615                    SystemClock.uptimeMillis());
616        }
617        service.callStart = false;
627        // END
628        bringDownServiceIfNeededLocked(service, isKnowConn, false);
629    }

ActiveServices#bringDownServiceIfNeededLocked

在必要条件下调用bringDownServiceLocked

2545    private final void bringDownServiceIfNeededLocked(ServiceRecord r, boolean knowConn,
2546            boolean hasConn) {
2547        //Slog.i(TAG, "Bring down service:");
2548        //r.dump("  ");
2549
2550        if (isServiceNeededLocked(r, knowConn, hasConn)) {  //判断服务是否还有存在的必要,如果还有必要存在,那么那直接return
2551            return;
2552        }
2553
2554        // Are we in the process of launching?
2555        if (mPendingServices.contains(r)) { //Service还未启动,不需要停止,直接return;在bringUpServiceLocked中mPendingServices.add(r),如果启动失败,肯定不会添加;
                                                                           //适用于一开始Service所在进程都没启动的情况;mPendingServices是代表服务所在进程启动后,待启动的Service
2556            return;
2557        }
2558
2559        bringDownServiceLocked(r);
2560    }

ActiveServices#isServiceNeededLocked

2527    private final boolean isServiceNeededLocked(ServiceRecord r, boolean knowConn,
2528            boolean hasConn) {
2529        // Are we still explicitly being asked to run?
//在进入bringDownServiceIfNeededLocked函数前,startRequested已经置为false了
2530        if (r.startRequested) {
2531            return true;
2532        }
2533
2534        // Is someone still bound to us keeping us running?
2535        if (!knowConn) {
//如果其它客户端,携带BIND_AUTO_CREATE标志,绑定过该Service,那么hasConn被置为true
2536            hasConn = r.hasAutoCreateConnections();
2537        }
2538        if (hasConn) {
2539            return true;
2540        }
2541
2542        return false;
2543    }

ServiceRecord#hasAutoCreateConnections

395    public boolean hasAutoCreateConnections() {
396        // XXX should probably keep a count of the number of auto-create
397        // connections directly in the service.
398        for (int conni=connections.size()-1; conni>=0; conni--) {
399            ArrayList<ConnectionRecord> cr = connections.valueAt(conni);
400            for (int i=0; i<cr.size(); i++) {
401                if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
402                    return true;
403                }
404            }
405        }
406        return false;
407    }

通过上述代码,我们知道一个Service如果同时以Bounded Service和Unbounded Service存在, 那么必须解绑后,才能被stopService结束。

ActiveServices#bringDownServiceLocked

2562    private final void bringDownServiceLocked(ServiceRecord r) {
2563        //Slog.i(TAG, "Bring down service:");
2564        //r.dump("  ");
2565
2566        // Report to all of the connections that the service is no longer
2567        // available.
2568        for (int conni=r.connections.size()-1; conni>=0; conni--) {
2569            ArrayList<ConnectionRecord> c = r.connections.valueAt(conni);
2570            for (int i=0; i<c.size(); i++) {
2571                ConnectionRecord cr = c.get(i);
2572                // There is still a connection to the service that is
2573                // being brought down.  Mark it as dead.
2574                cr.serviceDead = true;
2575                try {
    //从之前的isServiceNeeded函数来看
    //只有BIND_AUTO_CREATE创建的ServiceConnection,才能阻止Service被终止
    //因此,Service是可以有普通的ServiceConnection的
    //通知客户端,Service要被stop了
     //其实就是调用客户端自定义的ServiceConnection的onServiceDisconnected接口 (bindService中的逻辑)
     //这里是回调操作,做完回调操作后还要做解绑操作
2576                    cr.conn.connected(r.name, null, true);
2577                } catch (Exception e) {
2578                    Slog.w(TAG, "Failure disconnecting service " + r.name +
2579                          " to connection " + c.get(i).conn.asBinder() +
2580                          " (in " + c.get(i).binding.client.processName + ")", e);
2581                }
2582            }
2583        }
2584
2585        // Tell the service that it has been unbound.
2586        if (r.app != null && r.app.thread != null) {
2587            for (int i=r.bindings.size()-1; i>=0; i--) {
2588                IntentBindRecord ibr = r.bindings.valueAt(i); // All active bindings to the service. //IntentBindRecord 表示绑定Service时的Intent 参考https://www.jianshu.com/p/04ad8a12d808
/*
其中IntentBindRecord.service 最终会保存绑定的service的ServiceRecord;
IntentBindRecord.intent 就是前面所说的绑定service时设定的参数一致的intent在AMS中的表示Intent.FilterComparison对象;
IntentBindRecord.apps用来记录所有使用该类intetn绑定同一个service的客户端信息。key是客户端进程ProcessRecord,value是AppBindRecord。因为不同的客户端可能使用相同的intent参数来绑定同一个service,所以IntentBindRecord要记录下这些客户端信息;
IntentBindRecord.binder最终保存service的代理binder;
IntentBindRecord.received为true,表明IntentBindRecord.binder已经指向远端service的binder;
IntentBindRecord.requested为false,表明IntentBindRecord.binder还没有指向远端service的binder;
具体见bindService中的流程
*/
2589                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing down binding " + ibr
2590                        + ": hasBound=" + ibr.hasBound);//Unbounded Service也可以被绑定,此处执行unBindService相关的工作
2591                if (ibr.hasBound) {
                      //做解绑操作
2592                    try {
2593                        bumpServiceExecutingLocked(r, false, "bring down unbind"); //执行命令时,调用bumpServiceExecutingLocked先做更改ServiceRecord状态的操作
//关键在r.executeNesting++; r.executingStart = now; 记录命令次数和执行时间,有一个超时的机制(本次命令执行时间过长,就超时)
2594                        mAm.updateOomAdjLocked(r.app, true);
2595                        ibr.hasBound = false; 
2596                        ibr.requested = false;
2597                        r.app.thread.scheduleUnbindService(r,
2598                                ibr.intent.getIntent()); //调用scheduleUnbindService
2599                    } catch (Exception e) {
2600                        Slog.w(TAG, "Exception when unbinding service "
2601                                + r.shortName, e);
2602                        serviceProcessGoneLocked(r);
2603                    }
2604                }
2605            }
2606        }
2607
2608        // Check to see if the service had been started as foreground, but being
2609        // brought down before actually showing a notification.  That is not allowed. //针对前台Service
2610        if (r.fgRequired) { //postNotifcation中有相关逻辑,在sendServiceArgsLocked中如果r.isForeground为true,代表执行过notification了 r.fgRequired = false;
//如果在执行到stopService时这个值仍未true,代表Service还没有走到post Notification逻辑就stop了,需要将相关进程crash
2611            Slog.w(TAG_SERVICE, "Bringing down service while still waiting for start foreground: "
2612                    + r);
2613            r.fgRequired = false;
2614            r.fgWaiting = false;
2615            mAm.mHandler.removeMessages(
2616                    ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG, r);
2617            if (r.app != null) {
2618                Message msg = mAm.mHandler.obtainMessage(
2619                        ActivityManagerService.SERVICE_FOREGROUND_CRASH_MSG);
2620                msg.obj = r.app;
2621                msg.getData().putCharSequence(
2622                    ActivityManagerService.SERVICE_RECORD_KEY, r.toString());
2623                mAm.mHandler.sendMessage(msg);
2624            }
2625        }
2626
2627        if (DEBUG_SERVICE) {
2628            RuntimeException here = new RuntimeException();
2629            here.fillInStackTrace();
2630            Slog.v(TAG_SERVICE, "Bringing down " + r + " " + r.intent, here);
2631        }
2632        r.destroyTime = SystemClock.uptimeMillis();
2633        if (LOG_SERVICE_START_STOP) {
2634            EventLogTags.writeAmDestroyService(
2635                    r.userId, System.identityHashCode(r), (r.app != null) ? r.app.pid : -1);
2636        }
2637
2638        final ServiceMap smap = getServiceMapLocked(r.userId);
2639        ServiceRecord found = smap.mServicesByName.remove(r.name);
2640
2641        // Note when this method is called by bringUpServiceLocked(), the service is not found
2642        // in mServicesByName and found will be null.
2643        if (found != null && found != r) {
2644            // This is not actually the service we think is running...  this should not happen,
2645            // but if it does, fail hard.
2646            smap.mServicesByName.put(r.name, found);
2647            throw new IllegalStateException("Bringing down " + r + " but actually running "
2648                    + found);
2649        }
2650        smap.mServicesByIntent.remove(r.intent); //清除smap中的缓存
2651        r.totalRestartCount = 0;
2652        unscheduleServiceRestartLocked(r, 0, true);
2653
2654        // Also make sure it is not on the pending list.
2655        for (int i=mPendingServices.size()-1; i>=0; i--) {
2656            if (mPendingServices.get(i) == r) {
2657                mPendingServices.remove(i); //将其从进程的待处理的mPendingServices中remove
2658                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Removed pending: " + r);
2659            }
2660        }
2661
2662        cancelForegroundNotificationLocked(r);  //int foregroundId;       // Notification ID of last foreground req. 将前台服务的通知取消
2663        if (r.isForeground) { // is service currently in foreground mode?
2664            decActiveForegroundAppLocked(smap, r); //减小前台应用,总之也是对ServiceMap中的缓存进行处理
2665        }
2666        r.isForeground = false;
2667        r.foregroundId = 0;
2668        r.foregroundNoti = null;
2669
2670        // Clear start entries.
2671        r.clearDeliveredStartsLocked();
2672        r.pendingStarts.clear(); //将ServiceRecord中的delivered list和penglist中的startItem都删除
2673
2674        if (r.app != null) {
2675            synchronized (r.stats.getBatteryStats()) {
2676                r.stats.stopLaunchedLocked();
2677            }
2678            r.app.services.remove(r);//Service所在进程清除该ServiceRecord
2679            if (r.whitelistManager) {
2680                updateWhitelistManagerLocked(r.app);
2681            }
2682            if (r.app.thread != null) {
2683                updateServiceForegroundLocked(r.app, false); //如果前台服务被stop了,那么其进程优先级可能需要调整(当进程中不存在其他前台服务时调整)
2684                try {
2685                    bumpServiceExecutingLocked(r, false, "destroy"); //开始执行destory,调用bumpServiceExecutingLocked做前面的准备工作
2686                    mDestroyingServices.add(r);
2687                    r.destroying = true;
2688                    mAm.updateOomAdjLocked(r.app, true);
2689                    r.app.thread.scheduleStopService(r); //调用ActivityThread的scheduleStopService
2690                } catch (Exception e) {
2691                    Slog.w(TAG, "Exception when destroying service "
2692                            + r.shortName, e);
2693                    serviceProcessGoneLocked(r);
2694                }
2695            } else {
2696                if (DEBUG_SERVICE) Slog.v(
2697                    TAG_SERVICE, "Removed service that has no process: " + r);
2698            }
2699        } else {
2700            if (DEBUG_SERVICE) Slog.v(
2701                TAG_SERVICE, "Removed service that is not running: " + r);
2702        }
2703
2704        if (r.bindings.size() > 0) {
2705            r.bindings.clear();
2706        }
2707
2708        if (r.restarter instanceof ServiceRestarter) {
2709           ((ServiceRestarter)r.restarter).setService(null); //清除ServiceRestarter
2710        }
2711
2712        int memFactor = mAm.mProcessStats.getMemFactorLocked();
2713        long now = SystemClock.uptimeMillis();
2714        if (r.tracker != null) {
2715            r.tracker.setStarted(false, memFactor, now);
2716            r.tracker.setBound(false, memFactor, now);
2717            if (r.executeNesting == 0) {
2718                r.tracker.clearCurrentOwner(r, false);
2719                r.tracker = null;
2720            }
2721        }
2722
2723        smap.ensureNotStartingBackgroundLocked(r);//一个服务结束后,可能后台service减少,那么会重新触发ServiceMap的ensureNotStartingBackgroundLocked是否进行delay Service的判断
2724    }

参考 Android O 通知栏的"running in the background"

我们看下其中的decActiveForegroundAppLocked方法

    private void decActiveForegroundAppLocked(ServiceMap smap, ServiceRecord r) {
        ActiveForegroundApp active = smap.mActiveForegroundApps.get(r.packageName);
        if (active != null) {
            active.mNumActive--;
            if (active.mNumActive <= 0) {
                active.mEndTime = SystemClock.elapsedRealtime();
                if (foregroundAppShownEnoughLocked(active, active.mEndTime)) {
                    // Have been active for long enough that we will remove it immediately.
                    smap.mActiveForegroundApps.remove(r.packageName);
                    smap.mActiveForegroundAppsChanged = true;
                    requestUpdateActiveForegroundAppsLocked(smap, 0);
                } else if (active.mHideTime < Long.MAX_VALUE){
                    requestUpdateActiveForegroundAppsLocked(smap, active.mHideTime);
                }
            }
        }
    }

该方法主要是移除前台service,根据foregroundAppShownEnoughLocked判断,是否马上移除还是过一段时间移除。
该方法主要在两个地方调用。一个是在setServiceForegroundInnerLocked中调用,当应用调用startForeground,第一个参数设为0时,会走到这个路径。
另一个bringDownServiceLocked,也就是当绑定到该service的数量减小时,会调用该方法。

ActivityThread#scheduleStopService

904        public final void scheduleStopService(IBinder token) {
905            sendMessage(H.STOP_SERVICE, token);
906        }
1730                case STOP_SERVICE:
1731                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop");
1732                    handleStopService((IBinder)msg.obj);
1733                    maybeSnapshot();
1734                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1735                    break;

ActivityThread#handleStopService

3606    private void handleStopService(IBinder token) {
3607        Service s = mServices.remove(token);
3608        if (s != null) {
3609            try {
3610                if (localLOGV) Slog.v(TAG, "Destroying service " + s);
3611                s.onDestroy(); //调用Service的onDestroy函数
3612                s.detachAndCleanUp();
3613                Context context = s.getBaseContext();
3614                if (context instanceof ContextImpl) {
3615                    final String who = s.getClassName();
3616                    ((ContextImpl) context).scheduleFinalCleanup(who, "Service"); //进行清除工作
3617                }
3622                QueuedWork.waitToFinish();
3624
3625                try {
3626                    ActivityManager.getService().serviceDoneExecuting(
3627                            token, SERVICE_DONE_EXECUTING_STOP, 0, 0); //调用serviceDoneExecuting做收尾工作
3628                } catch (RemoteException e) {
3629                    throw e.rethrowFromSystemServer();
3630                }
3631            } catch (Exception e) {
3632                if (!mInstrumentation.onException(s, e)) {
3633                    throw new RuntimeException(
3634                            "Unable to stop service " + s
3635                            + ": " + e.toString(), e);
3636                }
3637                Slog.i(TAG, "handleStopService: exception for " + token, e);
3638            }
3639        } else {
3640            Slog.i(TAG, "handleStopService: token=" + token + " not found.");
3641        }
3642        //Slog.i(TAG, "Running services: " + mServices);
3643    }

ContextImpl#scheduleFinalCleanup

2374    final void scheduleFinalCleanup(String who, String what) {
2375        mMainThread.scheduleContextCleanup(this, who, what);
2376    }

ActivityThread#scheduleContextCleanup

2713    final void scheduleContextCleanup(ContextImpl context, String who,
2714            String what) {
2715        ContextCleanupInfo cci = new ContextCleanupInfo();
2716        cci.context = context;
2717        cci.who = who;
2718        cci.what = what;
2719        sendMessage(H.CLEAN_UP_CONTEXT, cci);
2720    }
1747                case CLEAN_UP_CONTEXT:
1748                    ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
1749                    cci.context.performFinalCleanup(cci.who, cci.what);
1750                    break;

ContextImpl#performFinalCleanup

2378    final void performFinalCleanup(String who, String what) {
2379        //Log.i(TAG, "Cleanup up context: " + this);
2380        mPackageInfo.removeContextRegistrations(getOuterContext(), who, what);
2381    }

LoadedApk#removeContextRegistrations

1049    public void removeContextRegistrations(Context context,
1050            String who, String what) {
1051        final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
1052        synchronized (mReceivers) {
1053            ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
1054                    mReceivers.remove(context);
1055            if (rmap != null) {
1056                for (int i = 0; i < rmap.size(); i++) {
1057                    LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
1058                    IntentReceiverLeaked leak = new IntentReceiverLeaked(
1059                            what + " " + who + " has leaked IntentReceiver "
1060                            + rd.getIntentReceiver() + " that was " +
1061                            "originally registered here. Are you missing a " +
1062                            "call to unregisterReceiver()?");
1063                    leak.setStackTrace(rd.getLocation().getStackTrace());
1064                    Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
1065                    if (reportRegistrationLeaks) {
1066                        StrictMode.onIntentReceiverLeaked(leak);
1067                    }
1068                    try {
1069                        ActivityManager.getService().unregisterReceiver(
1070                                rd.getIIntentReceiver());
1071                    } catch (RemoteException e) {
1072                        throw e.rethrowFromSystemServer();
1073                    }
1074                }
1075            }
1076            mUnregisteredReceivers.remove(context);
1077        }
1078
1079        synchronized (mServices) {
1080            //Slog.i(TAG, "Receiver registrations: " + mReceivers);
1081            ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
1082                    mServices.remove(context);
1083            if (smap != null) {
1084                for (int i = 0; i < smap.size(); i++) {
1085                    LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
1086                    ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
1087                            what + " " + who + " has leaked ServiceConnection "
1088                            + sd.getServiceConnection() + " that was originally bound here");
1089                    leak.setStackTrace(sd.getLocation().getStackTrace());
1090                    Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
1091                    if (reportRegistrationLeaks) {
1092                        StrictMode.onServiceConnectionLeaked(leak);
1093                    }
1094                    try {
1095                        ActivityManager.getService().unbindService(
1096                                sd.getIServiceConnection());
1097                    } catch (RemoteException e) {
1098                        throw e.rethrowFromSystemServer();
1099                    }
1100                    sd.doForget();
1101                }
1102            }
1103            mUnboundServices.remove(context);
1104            //Slog.i(TAG, "Service registrations: " + mServices);
1105        }
1106    }

scheduleFinalCleanup的工作,主要针对于BroadcastReceiver和Bounded Service, 目的是清理它们在AMS中的相关信息

流程图

Unbounded stop Service UML.png

参考: Android 7.0 ActivityManagerService(6) Service相关流程分析

相关文章

网友评论

    本文标题:Service相关流程学习-Unbouned Stop Serv

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