Android Framework—Service

news2024/11/24 21:09:13

介绍

Service是一种可以在后台执行长时间运行操作而不提供界面的应用组件。服务可以由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行。此外,组件可以通过绑定到服务与之进行交互,甚至是执行进程之间的通信。

正文

1.Service的介绍

<service android:name=".MyService"
    android:isolatedProcess="true"
    android:directBootAware="true"
    android:process=":subService"/>
import android.app.Service
import android.content.Intent
import android.os.IBinder

class PreloadService : Service() {
    override fun onBind(p0: Intent?): IBinder? {
        return null
    }
}

service的标签属性比较简单,具体可以参考官网。我在这里就举几个属性的例子:

isolatedProcess:服务与系统其余部分隔离的特殊进程下运行。

process:指定服务运行的进程名称。以:开头,系统会根据需要时创建新进程,并且服务会在该进程运行。

directBootAware:服务是否支持直接启动,也就是可以在用户解锁设备之前运行。

Service的生命周期

在这里插入图片描述

它的生命周期会和我们使用Service的不同 也有所不同。左边是startService 右边是bindService。我们汇编可以根据源码 再来看看执行的时机。

Service的运行模式

1.前台Service:执行一些用户能注意到的操作,前台服务必须显示通知。

2.后台Service:后台服务不会影响用户,在26以后,系统会对后台服务施加限制。

更多Android Framework 学习资料 请点击免费领取

2.Service的启动

1.startService

在源码中我们可以直接在Activity中调用startService,那就跟一下 看看它是如何开启Service的。 文件目录:/android/frameworks/base/core/java/android/content/ContextWrapper.java

public ComponentName startServiceAsUser(Intent service, UserHandle user) {
    return mBase.startServiceAsUser(service, user);
}
//mBase就是ContextImpl 参考Activity创建流程
Context mBase;

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

//开启Service
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
        UserHandle user) {
    try {
        //校验intent
        validateServiceIntent(service);
        //设置intent的属性,准备离开现有进程
        service.prepareToLeaveProcess(this);
        //调用AMS的startService  传入了 当前进程,service(目标servcie),true 
        ComponentName cn = ActivityManager.getService().startService(
            mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                        getContentResolver()), requireForeground,
                        getOpPackageName(), user.getIdentifier());
        return cn;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

看看AMS是如何开启Service

public ComponentName startService(IApplicationThread caller, Intent service,
        String resolvedType, boolean requireForeground, String callingPackage, int userId)
        throws TransactionTooLargeException {
        //判断是否是隔离进程调用
    enforceNotIsolatedCaller("startService");
   
    synchronized(this) {
        //获取pid
        final int callingPid = Binder.getCallingPid();
        //获取uid
        final int callingUid = Binder.getCallingUid();
        //获取origid
        final long origId = Binder.clearCallingIdentity();
        ComponentName res;
        try {
        //调用mService的startServiceLocked 这里的mService就是之前讲AMS启动流程时创建的ActiveServices 用来管理Service的
            res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid,
                    requireForeground, callingPackage, userId);
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
        return res;
    }
}
文件目录:/android/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
        int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
        throws TransactionTooLargeException {
    return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired,
            callingPackage, userId, false);
}


ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
        int callingPid, int callingUid, boolean fgRequired, String callingPackage,
        final int userId, boolean allowBackgroundActivityStarts)
        throws TransactionTooLargeException {

    final boolean callerFg;
    if (caller != null) {//不为null 获取到当前进程的ProcessRecord
        final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
        callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
    } else {
        callerFg = true;
    }
    //得到ServiceRecord对象:先从mServiceMap中查找 如果有就返回 没有的话就创建(通过pkms.resolveService 查找service创建ServiceRecord包装成ServiceLookupResult返回)
    ServiceLookupResult res =
        retrieveServiceLocked(service, null, resolvedType, callingPackage,
                callingPid, callingUid, userId, true, callerFg, false, false);
     //拿到ServiceRecord  ServiceRecord继承自Binder
    ServiceRecord r = res.record;
  
    final boolean bgLaunch = !mAm.isUidActiveLocked(r.appInfo.uid);

    boolean forcedStandby = false;
    if (bgLaunch && appRestrictedAnyInBackground(r.appInfo.uid, r.packageName)) {
        forcedStandby = true;
    }

    boolean forceSilentAbort = false;
    if (fgRequired) {//这里是false不走 前台走这里
    }

    if (forcedStandby || (!r.startRequested && !fgRequired)) {
    //判断是否运行启动服务:常驻内存、蓝牙、电源白名单允许直接启动服务 否则执行默认策略:如果大于AndroidO不允许启动后台服务
        final int allowed = mAm.getAppStartModeLocked(r.appInfo.uid, r.packageName,
                r.appInfo.targetSdkVersion, callingPid, false, false, forcedStandby);
        if (allowed != ActivityManager.APP_START_MODE_NORMAL) {//不允许启动服务的逻辑
            if (allowed == ActivityManager.APP_START_MODE_DELAYED || forceSilentAbort) {
                return null;
            }
            if (forcedStandby) {
                if (fgRequired) {//false
                    return null;
                }
            }
            UidRecord uidRec = mAm.mProcessList.getUidRecordLocked(r.appInfo.uid);
            return new ComponentName("?", "app is in background uid " + uidRec);
        }
    }
    if (r.appInfo.targetSdkVersion < Build.VERSION_CODES.O && fgRequired) {//不走这里
        fgRequired = false;
    }
    //记录时间戳
    r.lastActivity = SystemClock.uptimeMillis();
    //设置已经开启了
    r.startRequested = true;
    r.delayedStop = false;
    r.fgRequired = fgRequired;
    //添加了一个ServiceRecord.StartItem taskRemoved = false  如果是BindService 不会添加 因为他直接调用的是realStartService
    r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
            service, neededGrants, callingUid));

    if (fgRequired) {//这里不走
    }

    final ServiceMap smap = getServiceMapLocked(r.userId);
    boolean addToStarting = false;

    if (allowBackgroundActivityStarts) {
        r.whitelistBgActivityStartsOnServiceStart();
    }
    //调用startServiceInnerLocked
    ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
    return cmp;
}


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();
    }
    //调用bringUpServiceLocked 开启进程
    String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
    if (error != null) {
        return new ComponentName("!!", error);
    }
    if (r.startRequested && addToStarting) {
        boolean first = smap.mStartingBackground.size() == 0;
        smap.mStartingBackground.add(r);
        r.startingBgTimeout = SystemClock.uptimeMillis() + mAm.mConstants.BG_START_TIMEOUT;
        if (DEBUG_DELAYED_SERVICE) {
            RuntimeException here = new RuntimeException("here");
            here.fillInStackTrace();
        } else if (DEBUG_DELAYED_STARTS) {
        }
        if (first) {
            smap.rescheduleDelayedStartsLocked();
        }
    } else if (callerFg || r.fgRequired) {
        smap.ensureNotStartingBackgroundLocked(r);
    }

    return r.name;
}


private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
        boolean whileRestarting, boolean permissionsReviewRequired)
        throws TransactionTooLargeException {
    if (r.app != null && r.app.thread != null) {//已经运行
        sendServiceArgsLocked(r, execInFg, false);
        return null;
    }
    if (!whileRestarting && mRestartingServices.contains(r)) {
        return null;
    }
    if (mRestartingServices.remove(r)) {
        clearRestartingIfNeededLocked(r);
    }
    if (r.delayed) {
        getServiceMapLocked(r.userId).mDelayedStartList.remove(r);
        r.delayed = false;
    }
    //是否需要进程隔离下 运行
    final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
    //获取进程名
    final String procName = r.processName;
    //创建HostingRecord
    HostingRecord hostingRecord = new HostingRecord("service", r.instanceName);
    ProcessRecord app;

    if (!isolated) {//非隔离进程
        //获取到service的ProcessRecord
        app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
        if (app != null && app.thread != null) {//进程已经存在 启动了
            try {
                app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
                realStartServiceLocked(r, app, execInFg);
                return null;
            } catch (TransactionTooLargeException e) {
                throw e;
            } catch (RemoteException e) {
            }
        }
    } else {//隔离进程
        //第一次开启isolatedProc是null
        app = r.isolatedProc;
        if (WebViewZygote.isMultiprocessEnabled()
                && r.serviceInfo.packageName.equals(WebViewZygote.getPackageName())) {
            hostingRecord = HostingRecord.byWebviewZygote(r.instanceName);
        }
        if ((r.serviceInfo.flags & ServiceInfo.FLAG_USE_APP_ZYGOTE) != 0) {
            hostingRecord = HostingRecord.byAppZygote(r.instanceName, r.definingPackageName,
                    r.definingUid);
        }
    }
    //服务还没启动调用startProcessLocked 创建进程
    if (app == null && !permissionsReviewRequired) {
        if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                hostingRecord, false, isolated, false)) == null) {
            String msg = "Unable to launch app "
                    + r.appInfo.packageName + "/"
                    + r.appInfo.uid + " for service "
                    + r.intent.getIntent() + ": process is bad"; 
            bringDownServiceLocked(r);
            return msg;
        }
        if (isolated) {
            r.isolatedProc = app;
        }
    }

    if (r.fgRequired) {//不走这里 是false
        mAm.tempWhitelistUidLocked(r.appInfo.uid,
                SERVICE_START_FOREGROUND_TIMEOUT, "fg-service-launch");
    }
    if (!mPendingServices.contains(r)) {
    //假如mPendingServices中
        mPendingServices.add(r);
    }

    if (r.delayedStop) {
        r.delayedStop = false;
        if (r.startRequested) {
            stopServiceLocked(r);
        }
    }

    return null;
}

AMS这里会先检查Service是否可以执行(常驻内存、蓝牙、电源白名单允许直接启动服务),接着调用bringUpServiceLocked 判断是否需要隔离进程如果非隔离 就看是否已经启动进程 执行realStartServiceLocked,否则是隔离进程 直接开启新进程。我们没有设置隔离进程 所以我们会直接开启新进程,开启进程的过程在之前已经接触很多次了,我们直接跳过,开启成功之后会将ServiceRecord添加到mPendingServices中去。所以我们看看进程创建成功之后会如何开启Service。

private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
        int pid, int callingUid, long startSeq) {
            //到这里来
            thread.bindApplication(processName, appInfo, providers,
                    instr2.mClass,
                    profilerInfo, instr2.mArguments,
                    instr2.mWatcher,
                    instr2.mUiAutomationConnection, testMode,
                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.isPersistent(),
                    new Configuration(app.getWindowProcessController().getConfiguration()),
                    app.compat, getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked(),
                    buildSerial, autofillOptions, contentCaptureOptions);
      
    boolean badApp = false;
    boolean didSomething = false;
   //在这里开启activity
    if (normalMode) {
        try {
            didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
        } catch (Exception e) {
            badApp = true;
        }
    }

    
    if (!badApp) {
        try {
        //开启Service
            didSomething |= mServices.attachApplicationLocked(app, processName);
        } catch (Exception e) {
            badApp = true;
        }
    }
    return true;
}
//还是在ActiveService中

boolean attachApplicationLocked(ProcessRecord proc, String processName)
        throws RemoteException {
    boolean didSomething = false;
     //此时Services的size是大于0的
    if (mPendingServices.size() > 0) {
        ServiceRecord sr = null;
        try {
            for (int i=0; i<mPendingServices.size(); i++) {
                sr = mPendingServices.get(i);
                if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
                        || !processName.equals(sr.processName))) {
                    continue;
                }

                mPendingServices.remove(i);
                i--;
                proc.addPackage(sr.appInfo.packageName, sr.appInfo.longVersionCode,
                        mAm.mProcessStats);
                 //调用realStartServiceLocked开启service
                realStartServiceLocked(sr, proc, sr.createdFromFg);
                didSomething = true;
                if (!isServiceNeededLocked(sr, false, false)) {
                    bringDownServiceLocked(sr);
                }
            }
        } catch (RemoteException e) {
            throw e;
        }
    }
    return didSomething;
}

//开启service
private final void realStartServiceLocked(ServiceRecord r,
        ProcessRecord app, boolean execInFg) throws RemoteException {
    //服务和当前进程绑定
    r.setProcess(app);
    r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
    //添加到ProcessRecord中
    final boolean newService = app.services.add(r);
    //埋炸弹scheduleServiceTimeoutLocked
    bumpServiceExecutingLocked(r, execInFg, "create");
    //更新进程LRU
    mAm.updateLruProcessLocked(app, false, null);
    updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
    //更新OOMAdj
    mAm.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_START_SERVICE);
    boolean created = false;
    try {
        synchronized (r.stats.getBatteryStats()) {
            r.stats.startLaunchedLocked();
        }
        mAm.notifyPackageUse(r.serviceInfo.packageName,
                             PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
        app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
        //调用到应用进程 也就是服务进程 ActivityThread
        app.thread.scheduleCreateService(r, r.serviceInfo,
                mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
                app.getReportedProcState());
        r.postNotification();
        created = true;
    } catch (DeadObjectException e) {
    } finally {
    }

    if (r.whitelistManager) {
        app.whitelistManager = true;
    }
    //处理Bind我们不处理 没有Bind 此时直说startService
    requestServiceBindingsLocked(r, execInFg);

    updateServiceClientActivitiesLocked(app, null, true);

    if (newService && created) {
        app.addBoundClientUidsOfNewService(r);
    }
    if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
        r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                null, null, 0));
    }
    //发送Service的args
    sendServiceArgsLocked(r, execInFg, true);
    if (r.delayed) {
        getServiceMapLocked(r.userId).mDelayedStartList.remove(r);
        r.delayed = false;
    }
}

回到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;
    //给mH发送了H.CREATE_SERVICE
    sendMessage(H.CREATE_SERVICE, s);
}

case CREATE_SERVICE:
    handleCreateService((CreateServiceData)msg.obj);
    break;
//创建Service
private void handleCreateService(CreateServiceData data) {
    unscheduleGcIdler();

    LoadedApk packageInfo = getPackageInfoNoCheck(
            data.info.applicationInfo, data.compatInfo);
    Service service = null;
    try {
        //反射创建Service
        java.lang.ClassLoader cl = packageInfo.getClassLoader();
        service = packageInfo.getAppFactory()
                .instantiateService(cl, data.info.name, data.intent);
    } catch (Exception e) {
    }

    try {
        //创建Context
        ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
        context.setOuterContext(service);
        //调用makeApplication
        Application app = packageInfo.makeApplication(false, mInstrumentation);
        //调用service的attach 绑定ActivityThread token Application 以及AMS
        service.attach(context, this, data.info.name, data.token, app,
                ActivityManager.getService());
         //调用service的onCreate
        service.onCreate();
        //存入到mService中去
        mServices.put(data.token, service);
        try {
        //告诉AMS创建完成
            ActivityManager.getService().serviceDoneExecuting(
                    data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    } catch (Exception e) {
    }
}

public final void attach(
        Context context,
        ActivityThread thread, String className, IBinder token,
        Application application, Object activityManager) {
    attachBaseContext(context);
    mThread = thread;           // NOTE:  unused - remove?
    mClassName = className;
    mToken = token;
    mApplication = application;
    mActivityManager = (IActivityManager)activityManager;
    mStartCompatibility = getApplicationInfo().targetSdkVersion
            < Build.VERSION_CODES.ECLAIR;
}


到AMS 处理服务创建

public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
    synchronized(this) {
        if (!(token instanceof ServiceRecord)) {
            throw new IllegalArgumentException("Invalid service token");
        }
        mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res);
    }
}

//AMS开启Service成功
void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
    boolean inDestroying = mDestroyingServices.contains(r);
    if (r != null) {
        //在这里把炸弹拆除
        serviceDoneExecutingLocked(r, inDestroying, inDestroying);
    } 
}
发送的args
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
        boolean oomAdjusted) throws TransactionTooLargeException {
    final int N = r.pendingStarts.size();
    if (N == 0) {//不是0
        return;
    }
    ArrayList<ServiceStartArgs> args = new ArrayList<>();

    while (r.pendingStarts.size() > 0) {
        ServiceRecord.StartItem si = r.pendingStarts.remove(0);
        if (si.intent == null && N > 1) {
            continue;
        }
        si.deliveredTime = SystemClock.uptimeMillis();
        r.deliveredStarts.add(si);
        si.deliveryCount++;
        //埋炸弹
        bumpServiceExecutingLocked(r, execInFg, "start");
        if (!oomAdjusted) {
            oomAdjusted = true;
            mAm.updateOomAdjLocked(r.app, true, OomAdjuster.OOM_ADJ_REASON_START_SERVICE);
        }
        if (r.fgRequired && !r.fgWaiting) {//前台Service
            if (!r.isForeground) {
                scheduleServiceForegroundTransitionTimeoutLocked(r);
            } else {
                r.fgRequired = false;
            }
        }
        int flags = 0;
        if (si.deliveryCount > 1) {
            flags |= Service.START_FLAG_RETRY;
        }
        if (si.doneExecutingCount > 0) {
            flags |= Service.START_FLAG_REDELIVERY;
        }
        args.add(new ServiceStartArgs(si.taskRemoved, si.id, flags, si.intent));
    }
    //执行ActivityThread的scheduleServiceArgs
    r.app.thread.scheduleServiceArgs(r, slice);
}


public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
    List<ServiceStartArgs> list = args.getList();

    for (int i = 0; i < list.size(); i++) {
        ServiceStartArgs ssa = list.get(i);
        ServiceArgsData s = new ServiceArgsData();
        s.token = token;
        s.taskRemoved = ssa.taskRemoved;
        s.startId = ssa.startId;
        s.flags = ssa.flags;
        s.args = ssa.args;
        //给mH发送SERVICE_ARGS
        sendMessage(H.SERVICE_ARGS, s);
    }
}

case SERVICE_ARGS:
    handleServiceArgs((ServiceArgsData)msg.obj);
    break;

//处理Args
private void handleServiceArgs(ServiceArgsData data) {
    Service s = mServices.get(data.token);
    if (s != null) {
        try {
            if (data.args != null) {
                data.args.setExtrasClassLoader(s.getClassLoader());
                data.args.prepareToEnterProcess();
            }
            int res;
            if (!data.taskRemoved) {//这里是false 所以会执行onStartCommand
                res = s.onStartCommand(data.args, data.flags, data.startId);
            } else {
            }

            QueuedWork.waitToFinish();

            try {
                //通知AMS 拆除炸弹
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
            } catch (RemoteException e) {
            }
        } catch (Exception e) {
        }
    }
}

进程创建之后,会调用AMSattachApplication 接着处理service(ActiveService),之前创建之后会添加到mPendingServices中,现在继续处理调用realStartServiceLocked来开启Service,在开启的过程中会埋入一个炸弹(给Handler发送一个SERVICE_TIMEOUT_MSG) 如果超时未处理会弹出ANR,然后调用app.thread.scheduleCreateService通知客户端创建反射Service、Context 调用onCreateService存入到mService中,调用AMSserviceDoneExecuting进行炸弹的拆除。 然后再埋炸弹 调用app.thread.scheduleServiceArgs 调用service.onStartCommand再通知AMS 拆除炸弹。 这样Service就运行起来了。我们再看看Service的onStop。

还是回到ContextImpl

public boolean stopService(Intent service) {
    return stopServiceCommon(service, mUser);
}


private boolean stopServiceCommon(Intent service, UserHandle user) {
        validateServiceIntent(service);
        service.prepareToLeaveProcess(this);
        //调用AMS的stopService
        int res = ActivityManager.getService().stopService(
            mMainThread.getApplicationThread(), service,
            service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
        return res != 0;
}


public int stopService(IApplicationThread caller, Intent service,
        String resolvedType, int userId) {
    enforceNotIsolatedCaller("stopService");
    synchronized(this) {
    //调用ActiveService的stopServiceLocked
        return mServices.stopServiceLocked(caller, service, resolvedType, userId);
    }
}


int stopServiceLocked(IApplicationThread caller, Intent service,
        String resolvedType, int userId) {
    //获取到调用这的ProcessRecord
    final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
    //获取ServiceRecord 
    ServiceLookupResult r = retrieveServiceLocked(service, null, resolvedType, null,
            Binder.getCallingPid(), Binder.getCallingUid(), userId, false, false, false, false);
    if (r != null) {
        if (r.record != null) {
            final long origId = Binder.clearCallingIdentity();
            try {
                //调用stopServiceLocked
                stopServiceLocked(r.record);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return 1;
        }
        return -1;
    }

    return 0;
}


private void stopServiceLocked(ServiceRecord service) {
    if (service.delayed) {
        service.delayedStop = true;
        return;
    }
    synchronized (service.stats.getBatteryStats()) {
        service.stats.stopRunningLocked();
    }
    service.startRequested = false;
    if (service.tracker != null) {
        service.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(),
                SystemClock.uptimeMillis());
    }
    service.callStart = false;

    bringDownServiceIfNeededLocked(service, false, false);
}

private final void bringDownServiceIfNeededLocked(ServiceRecord r, boolean knowConn,
        boolean hasConn) {
    if (isServiceNeededLocked(r, knowConn, hasConn)) {
        return;
    }

    if (mPendingServices.contains(r)) {
        return;
    }

    bringDownServiceLocked(r);
}



private final void bringDownServiceLocked(ServiceRecord r) {
    if (r.app != null && r.app.thread != null) {
        boolean needOomAdj = false;
        //执行unBind
        for (int i = r.bindings.size() - 1; i >= 0; i--) {
            IntentBindRecord ibr = r.bindings.valueAt(i);
            if (ibr.hasBound) {
                try {
                    bumpServiceExecutingLocked(r, false, "bring down unbind");
                    needOomAdj = true;
                    ibr.hasBound = false;
                    ibr.requested = false;
                    r.app.thread.scheduleUnbindService(r,
                            ibr.intent.getIntent());
                } catch (Exception e) {
                    serviceProcessGoneLocked(r);
                }
            }
        }
        if (needOomAdj) {
            mAm.updateOomAdjLocked(r.app, true,
                    OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE);
        }
    }

        r.fgRequired = false;
        r.fgWaiting = false;
        ServiceState stracker = r.getTracker();
        if (stracker != null) {
            stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(),
                    r.lastActivity);
        }
        mAm.mAppOpsService.finishOperation(AppOpsManager.getToken(mAm.mAppOpsService),
                AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
        mAm.mHandler.removeMessages(
                ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG, r);
        if (r.app != null) {
            Message msg = mAm.mHandler.obtainMessage(
                    ActivityManagerService.SERVICE_FOREGROUND_CRASH_MSG);
            msg.obj = r.app;
            msg.getData().putCharSequence(
                ActivityManagerService.SERVICE_RECORD_KEY, r.toString());
            mAm.mHandler.sendMessage(msg);
        }
    }
//记录销毁时间
    r.destroyTime = SystemClock.uptimeMillis();

    final ServiceMap smap = getServiceMapLocked(r.userId);
    //从map中移除
    ServiceRecord found = smap.mServicesByInstanceName.remove(r.instanceName);
    //移除
    smap.mServicesByIntent.remove(r.intent);
    r.totalRestartCount = 0;
    r.isForeground = false;
    r.foregroundId = 0;
    r.foregroundNoti = null;

    r.clearDeliveredStartsLocked();
    r.pendingStarts.clear();
    smap.mDelayedStartList.remove(r);

    if (r.app != null) {
        synchronized (r.stats.getBatteryStats()) {
            r.stats.stopLaunchedLocked();
        }
        r.app.services.remove(r);
        r.app.updateBoundClientUids();
        if (r.whitelistManager) {
            updateWhitelistManagerLocked(r.app);
        }
        if (r.app.thread != null) {
            updateServiceForegroundLocked(r.app, false);
            try {
               //埋炸弹
                bumpServiceExecutingLocked(r, false, "destroy");
                mDestroyingServices.add(r);
                r.destroying = true;
                mAm.updateOomAdjLocked(r.app, true,
                        OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE);
                //到客户端执行scheduleStopService
                r.app.thread.scheduleStopService(r);
            } catch (Exception e) {
                serviceProcessGoneLocked(r);
            }
        } else {
        }
    } 

    if (r.bindings.size() > 0) {
    //清空bindings
        r.bindings.clear();
    }

    if (r.restarter instanceof ServiceRestarter) {
       ((ServiceRestarter)r.restarter).setService(null);
    }

    int memFactor = mAm.mProcessStats.getMemFactorLocked();
    long now = SystemClock.uptimeMillis();
    if (r.tracker != null) {
        r.tracker.setStarted(false, memFactor, now);
        r.tracker.setBound(false, memFactor, now);
        if (r.executeNesting == 0) {
            r.tracker.clearCurrentOwner(r, false);
            r.tracker = null;
        }
    }

    smap.ensureNotStartingBackgroundLocked(r);
}


public final void scheduleStopService(IBinder token) {
    sendMessage(H.STOP_SERVICE, token);
}

case STOP_SERVICE:
    handleStopService((IBinder)msg.obj);
    schedulePurgeIdler();//清空待清理的资源
    break;


private void handleStopService(IBinder token) {
//从mService中移除掉 只是从map中移除掉了引用,所以我们需要注意Service内部的thread 以及变量不要引起内存泄漏或者线程没有停止
    Service s = mServices.remove(token);
    if (s != null) {
        try {
           //调用s的onDestory
            s.onDestroy();
            s.detachAndCleanUp();
            Context context = s.getBaseContext();
            if (context instanceof ContextImpl) {
                final String who = s.getClassName();
                ((ContextImpl) context).scheduleFinalCleanup(who, "Service");
            }
            QueuedWork.waitToFinish();
            try {
            //调用AMS的serviceDoneExecuting 拆除炸弹
                ActivityManager.getService().serviceDoneExecuting(
                        token, SERVICE_DONE_EXECUTING_STOP, 0, 0);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        } catch (Exception e) {
        }
    } else {
    }
}

stop的流程和start的流程差不多,需要注意的是stop只是从map中移除了,我们需要自己释放资源。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/461463.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unreal5 第三人称射击游戏 角色基础制作

快捷键 快捷键 ctrlE 可以快速打开相关蓝图类&#xff0c;直接在场景选中添加到场景中的对象即可。 调试蓝图 选中调试对象&#xff0c;选中需要调试的实例&#xff0c;即可查看当前角色的状态。 动画实例在运行的时候&#xff0c;也可以在右侧箭头获取当前场景已经生成的实…

Linux socket编程(二):多进程服务器

一、多进程服务器 最简单的的服务器程序执行流程为&#xff1a;创建socket → \rightarrow → 绑定监听的IP地址和端口 → \rightarrow → 监听客户端连接 → \rightarrow → 接受/发送数据。当服务端调用read阻塞等待一个客户端发来数据时&#xff0c;无法同时响应其它客户…

七、CANdelaStudio入门-Variant概念与应用

本专栏将由浅入深的展开诊断实际开发与测试的数据库编辑,包含大量实际开发过程中的步骤、使用技巧与少量对Autosar标准的解读。希望能对大家有所帮助,与大家共同成长,早日成为一名车载诊断、通信全栈工程师。 本文介绍CANdelaStudio的Variant概念与应用,欢迎各位朋友订阅、…

Redis实现互相关注功能

Redis实现互相关注功能 我们要实现关注功能&#xff0c;首先&#xff0c;我们需要得到关注的目标ID&#xff1a; PutMapping("/{id}/{isFollow}")public Result followUser(PathVariable("id") Long id,PathVariable("isFollow") Boolean isFol…

下一代大数据分布式存储技术Apache Ozone初步研究

文章目录 概述定义特性架构总体架构写数据读数据 部署安装方式安装Docker启动Docker-compose启动企业预置型(On Premise)安装 实践命令行接口Ofs (Hadoop兼容)Recon API 概述 定义 Apache Ozone 官网地址 https://ozone.apache.org/ 最新版本1.3.0 Apache Ozone 官网最新文档地…

Java线程间通信方式(2)

前文了解了线程通信方式中的Object.wait/Object.notify以及Semaphore,接下来我们继续了解其他的线程间通信方式。 CountDownLatch CountDownLatch利用一个指定的计数初始化&#xff0c;由于调用了countDown方法&#xff0c;await方法会阻塞直到当前技术为0&#xff0c;之后所…

PHP-8.2.5+IIS10 php-cgi.exe - FastCGI 进程意外退出

服务器信息&#xff1a; Windows Server 2019 Standard. Internet Information Services(Version 10.0.17763.1) PHP版本&#xff1a; PHP Version 8.2.5 php-8.2.5-nts-Win32-vs16-x64 下载地址&#xff1a;https://windows.php.net/download#php-8.2 错误信息&#xff1a; H…

【网络】-- UDP协议

目录 传输层 再谈端口号 端口号范围划分 认识知名端口号&#xff08;Well-Know Port Number&#xff09; 两个问题 netstat pidof UDP协议 UDP的特点 UDP的缓冲区 UDP使用注意事项 基于UDP的应用层协议 传输层 负责数据能够从发送端传输接收端。 再谈端口号 端…

【ROS】ubuntu18.04安装ROS(ROS1 Melodic)

1、添加中科大ROS源 1.1、添加源 sudo sh -c . /etc/lsb-release && echo "deb http://mirrors.ustc.edu.cn/ros/ubuntu/ lsb_release -cs main" > /etc/apt/sources.list.d/ros-latest.list1. 2、添加公钥 sudo apt-key adv --keyserver hkp://keyser…

输入捕获实验

实验内容 用TIM5 的通道 1&#xff08;PA0&#xff09;来做输入捕获&#xff0c;捕获 PA0 上高电平的脉宽&#xff08;用 WK_UP 按键输入高电平&#xff09;&#xff0c;通过串口打印高电平脉宽时间。 输入捕获简介 输入捕获模式可以用来测量脉冲宽度或者测量频率。STM32 的…

新库上线 | 全国工艺美术大师信息数据

全国工艺美术大师信息数据 一、数据简介 作为物质产品&#xff0c;工艺美术反映着一定时代、一定社会的物质的和文化的生产水平&#xff1b;作为精神产品&#xff0c;它的视觉形象&#xff08;造型、色彩、装饰&#xff09;又体现了一定时代的审美观。我国工艺美术品的制作较早…

java基础+注解笔记【狂神说java】

基础部分–总结 基础包的命名 //一般为域名倒置 page com.yang.base基础语法 类和方法 根据不同的写法–大小写的差异可以判别是类对象还是方法名 类的首字母都要大写&#xff0c;方法首字母小写可以理解为&#xff0c;类对象是class&#xff0c;方法是函数 类对象 方法 使…

浅谈在 Vue2 和 Vue3 中计算属性和侦听器的一些变化

文章目录 &#x1f4cb;前言&#x1f3af;计算属性&#x1f3af;侦听器&#x1f4dd;最后 &#x1f4cb;前言 计算属性 computed 和侦听器 watch 都是 Vue.js 框架中用来响应式更新视图的重要概念。因此无论是在哪个版本&#xff0c;它们都是不可缺少的概念&#xff0c;这篇文…

音视频八股文(5)--SDL音视频渲染实战。会使用就行,不需要深究。

01-SDL子系统 SDL将功能分成下列数个子系统&#xff08;subsystem&#xff09;&#xff1a; ◼ SDL_INIT_TIMER&#xff1a;定时器 ◼ SDL_INIT_AUDIO&#xff1a;音频 ◼ SDL_INIT_VIDEO&#xff1a;视频 ◼ SDL_INIT_JOYSTICK&#xff1a;摇杆 ◼ SDL_INIT_HAPTIC&#xff1…

第十三章 享元模式

文章目录 前言一、享元模式基本介绍二、享元模式解决网站展现项目完整代码WebSite 抽象网站类User 外部状态用户内部状态网站 ConcreteWebSite网站工厂产生网站和负责共享&#xff08;池&#xff09; WebSiteFactoryClint 测试 三、享元模式在JDK-Interger的应用源码分析四、享…

ERBuilder Data Modeler Crack

ERBuilder Data Modeler Crack 为过程、视图和触发器添加了人工智能驱动的描述生成。 添加了一种新的自动排列方法&#xff0c;可以轻松地排列和组织表格&#xff0c;从而简化ER图的可视化显示。 添加了使用两种身份验证方法创建到远程服务器的SSH连接的功能&#xff1a;密码身…

Linux - 第10节 - Linux多线程(二)

1.Linux线程同步 1.1.同步概念与竞态条件 线程互斥的设计是正确的&#xff0c;但线程互斥在某些场景下并不合理&#xff0c;有可能导致饥饿问题。 饥饿问题&#xff1a;某个执行流访问完临界资源后释放锁&#xff0c;此时相较于其他执行流&#xff0c;该执行流离锁更近&#x…

【目标检测论文阅读笔记】Detection of plane in remote sensing images using super-resolution

Abstract 由于大量的小目标、实例级噪声和云遮挡等因素&#xff0c;遥感图像的目标检测精度低&#xff0c;漏检率或误检率高。本文提出了一种新的基于SRGAN和YOLOV3的目标检测模型&#xff0c;称为SR-YOLO。解决了SRGAN网络 对超参数的敏感性和模态崩溃问题。同时&#xff0c;Y…

【中级软件设计师】—(针对上午题)算法分析与设计(三十八)

【中级软件设计师】—&#xff08;针对上午题&#xff09;算法分析与设计&#xff08;三十八&#xff09; 一、回溯法 1. 什么是回溯法&#xff1f; 相信"迷宫"是许多人儿时的回忆&#xff0c;大家小时候一定都玩过迷宫游戏。我们从不用别人教&#xff0c;都知道走…

TryHackMe-M4tr1x: Exit Denied(boot2root)

M4tr1x: Exit Denied 大多数人只看到一个完美构建的系统。但你一直都是不同的。你不仅看到表面上的东西&#xff0c;还看到 它下面有什么统治;调节和调节的内部关联机制 几乎完美地管理其每个模块&#xff0c;以至于它试图隐藏所有模块 其多面设计中的微小孔。但是&#xff0c…