startService()源码分析

Android  源码分析  2023年12月8日 pm12:12发布3个月前更新 城堡大人
133 0 0

前言

startService()源码分析之前Android 6.0是有简单分析过的,但太久了,而且记录也很粗糙,到现在也忘记得差不多了。

最近抽空重新走一下,也算是自己的复习吧。

这里看的是Android P的源代码。

正文

这里是Apk1去启动Apk2的服务(Apk2没有启动过)

Intent intent = new Intent();
intent.setPackage("com.biumall.server");
intent.setComponent(new ComponentName("com.biumall.server", "com.biumall.server.DemoService"));
startService(intent);

PS: Apk1和Apk2都为系统应用,要不然:

Not allowed to start service Intent { xxxxx  }: app is in background uid null

因为Apk2没有启动。系统应用区启动就没啥问题。这部分可以看《Android启动没有运行的App中的service:Not allowed to start service Intent {...}: app is in background uid null

回归正题。进入源码分析。

ContextImpl.java才是Context背后的大佬,这里直接进入。

ContextImpl.java

startService()
@Override
public ComponentName startService(Intent service) {
    return startServiceCommon(service, false, mUser);
}
startServiceCommon()
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
        UserHandle user) {
    try {
        //略 [不是分析重点都会略去]

        //ActivityManager.getService()是ActivityManagerService
        //这部分的分析网上很多,之前也跟过,但没单独分开,后续有机会单独写一下
        //这里调用的是ActivityManagerService.startService()
        ComponentName cn = ActivityManager.getService().startService(
            mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                        getContentResolver()), requireForeground,
                        getOpPackageName(), user.getIdentifier());
        //略
        return cn;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

关于ActivityManager.getService()的,如果不懂就百度吧,我之前文件有解释过。

也就是启动服务最终还是进入ActivityManagerService中。

ActivityManagerService.java

startService()
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
        String resolvedType, boolean requireForeground, String callingPackage, int userId)
        throws TransactionTooLargeException {
    //略
    synchronized(this) {
        final int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        ComponentName res;
        try {
            //调用ActiveServices.startServiceLocked()
            res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid,
                    requireForeground, callingPackage, userId);
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
        return res;
    }
}

ActiveServices.java

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
        int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)throws TransactionTooLargeException {
    //略
    //这里很多初始化和判断,但不关心,跳过,如果需要就看源码
    //调用的是startServiceInnerLocked()
    ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
    return cmp;
}
startServiceInnerLocked()
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
        boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
    ServiceState stracker = r.getTracker();
    //stracker为null,我们还没启动过呢
    if (stracker != null) {
        stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
    }
    //略
    //重点,这里是拉起服务
    String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
    //进程启动成功 ,error为null
    if (error != null) {
        return new ComponentName("!!", error);
    }
    //略
    return r.name;
}
bringUpServiceLocked()
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
        boolean whileRestarting, boolean permissionsReviewRequired)
        throws TransactionTooLargeException {
    //[重1]r.app是不为null,也即是进程存在,可以直接启动服务
    if (r.app != null && r.app.thread != null) {
        //如果满足上面条件,ApplicationInfo信息存在
        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;
    }
    if (!mAm.mUserController.hasStartedUserState(r.userId)) {
        bringDownServiceLocked(r);
        return msg;
    }
    try {
        AppGlobals.getPackageManager().setPackageStoppedState(
                r.packageName, false, r.userId);
    } catch (RemoteException e) {
       //略
    }
    final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
    final String procName = r.processName;
    String hostingType = "service";
    ProcessRecord app;
    //判读是否是独立进程false
    if (!isolated) {
        //[重2]获取ProcessRecord,通过ActivityManagerService获取,进程信息
        //如果这里能获取到ProcessRecord,表示进程也是启动过的,这里就启动服务。
        app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
        //没有启动过,app= null
        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) {
                Slog.w(TAG, "Exception when starting service " + r.shortName, e);
            }
        }
    } else {
        //略
    }
    //进程没有启动,这里启动进程
    //传入的permissionsReviewRequired为false
    if (app == null && !permissionsReviewRequired) {
        //[重3]这里进行启动进程
        if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                hostingType, r.name, false, isolated, false)) == null) {
             //启动失败才走这里。
            bringDownServiceLocked(r);
            return msg;
        }
        //略
    }
    //略
    //[重4],这里添加服务到Pending列表
    if (!mPendingServices.contains(r)) {
        mPendingServices.add(r);
    }
    //略
    return null;
}

重点。分为如下几个步骤。

  1. [重1]判断ServiceRecord中是否带有ApplicationInfo信息,如果有,表示Application已经启动了,调用sendServiceArgsLocked。

  2. [重2]查看是否有ProcessRecord信息,如果有直接进入realStartServiceLocked()

  3. [重3]进程启动,上面两个条件不满足,表示进程不存在,需要fork一个进程来。

  4. [重4]把服务添加到mPendingServices中,等进程启动完层后启动。

由于我们进程没有启动过,因此,需要等进程启动成功后才可以启动服务。因此,startService()大部分执行完成。

接下来就是等待进程的启动,然后系统把Service拉起来。

下面关注进程的启动。

ActivityManagerService.java

startProcessLocked()
@GuardedBy("this")
final ProcessRecord startProcessLocked(String processName,
        ApplicationInfo info, boolean knownToBeDead, int intentFlags,
        String hostingType, ComponentName hostingName, boolean allowWhileBooting,
        boolean isolated, boolean keepIfLarge) {
    return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
            hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
            null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
            null /* crashHandler */);
}

由于进程的启动这部分跟《startActivity之进程启动》重合,也就是Zygote会fork出一个子进程,然后通过反射启动ActivityThread.java的main()方法。

进程启动略

想看的直接看《startActivity之进程启动》吧。

ActivityThread.java

这部分跟《startActivity源码分析2》也跟重复,因此,下面也就大概的走一下。

main()
public static void main(String[] args) {
    //略
    Looper.prepareMainLooper();
    long startSeq = 0;
    //创建一个ActivityThread
    ActivityThread thread = new ActivityThread();
    //[重]这里执行了attach()
    thread.attach(false, startSeq);
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    //进入循环,正常情况不会退出的
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}
attach()
private void attach(boolean system, long startSeq) {
    //略
    //传入的system为false
    if (!system) {
        //略
        //获取的是ActivityManagerService
        final IActivityManager mgr = ActivityManager.getService();
        try {
            //[重]进行attach
            mgr.attachApplication(mAppThread, startSeq);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
        //略
    }
    //略
}

ActivityManagerService.java

attachApplication()
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
    synchronized (this) {
        //略
        attachApplicationLocked(thread, callingPid, callingUid, startSeq);
        //略
    }
}
attachApplicationLocked()
@GuardedBy("this")
private final boolean attachApplicationLocked(IApplicationThread thread,
        int pid, int callingUid, long startSeq) {
    //略
    final String processName = app.processName;
    try {
        AppDeathRecipient adr = new AppDeathRecipient(app, pid, thread);
        //binder死亡监听
        thread.asBinder().linkToDeath(adr, 0);
        app.deathRecipient = adr;
    } catch (RemoteException e) {
        app.resetPackageList(mProcessStats);
        startProcessLocked(app, "link fail", processName);
        return false;
    }
    //略
    try {
        //略
        //isolatedEntryPoint为null
        if (app.isolatedEntryPoint != null) {
            thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
        } else if (app.instr != null) {
            //略
        } else {
            //[重1]绑定bindApplication
            //通过Handler处理,主要是执行Application的onCreate()方法。
            //这里不会阻塞!!!
            thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                    null, null, null, testMode,
                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(getGlobalConfiguration()), app.compat,
                    getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked(),
                    buildSerial, isAutofillCompatEnabled);
        }
        //略
    } catch (Exception e) {
        //略
        return false;
    }
    //略
    boolean badApp = false;
    boolean didSomething = false;
    //启动Activity 
    if (normalMode) {
        try {
            //重点启动Activity相关
            if (mStackSupervisor.attachApplicationLocked(app)) {
                didSomething = true;
            }
        } catch (Exception e) {
            badApp = true;
        }
    }
    //启动服务
    if (!badApp) {
        try {
            //[重2],启动服务
            didSomething |= mServices.attachApplicationLocked(app, processName);
            checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
        } catch (Exception e) {
            badApp = true;
        }
    }
    //启动广播
    if (!badApp && isPendingBroadcastProcessLocked(pid)) {
        try {
            //重点
            didSomething |= sendPendingBroadcastsLocked(app);
        } catch (Exception e) {
            badApp = true;
        }
    }
    //略
    return true;
}

这个方法比较重要,涉及如下几个内容

  1. Application的启动,执行onCreate()

  2. Activity的启动,执行onCreate(),看是否有满足条件的。

  3. Service的启动,执行onCreate(),看是否有满足条件的。

  4. 发送广播 (不过,这部分我没跟,看代码是有,暂时保留吧,后续跟踪)

我们这里只关心Service的启动,至于[重1]Application的onCreate()启动,麻烦移步到《startActivity源码分析2》。

好的,我们看[重2]那部分代码。

if (!badApp) {
    try {
        didSomething |= mServices.attachApplicationLocked(app, processName);
    } catch (Exception e) {
        badApp = true;
    }
}

ActiveServices.java

attachApplicationLocked()
boolean attachApplicationLocked(ProcessRecord proc, String processName)
        throws RemoteException {
    boolean didSomething = false;
    //Pending中的服务,这里大于0
    if (mPendingServices.size() > 0) {
        ServiceRecord sr = null;
        try {
            for (int i=0; i<mPendingServices.size(); i++) {
                sr = mPendingServices.get(i);
                //sr就是上面保存的Service信息
                //ServiceRecord{66fcbc0 u0 com.biumall.biuaidlserver/.server.DemoService}
                if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
                        || !processName.equals(sr.processName))) {
                    continue;
                }
                //找到了,先移除mPendingServices
                mPendingServices.remove(i);
                i--;
                proc.addPackage(sr.appInfo.packageName, sr.appInfo.longVersionCode,
                        mAm.mProcessStats);
                //[重]启动服务,看包名就知道啥意思哈
                realStartServiceLocked(sr, proc, sr.createdFromFg);
                didSomething = true;
                if (!isServiceNeededLocked(sr, false, false)) {
                    bringDownServiceLocked(sr);
                }
            }
        } catch (RemoteException e) {
            throw e;
        }
    }
    //重新启动的服务为0
    if (mRestartingServices.size() > 0) {
        //略
    }
    return didSomething;
}
realStartServiceLocked()
private final void realStartServiceLocked(ServiceRecord r,
        ProcessRecord app, boolean execInFg) throws RemoteException {
    //thread不为null的
    if (app.thread == null) {
        throw new RemoteException();
    }
    r.app = app;
    r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
    final boolean newService = app.services.add(r);
    //发送SERVICE_TIMEOUT_MSG,超时就ANR
    //前台服务20s超时会ANR
    //后台服务超时200s超时会ANR
    bumpServiceExecutingLocked(r, execInFg, "create");
    mAm.updateLruProcessLocked(app, false, null);
    updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
    mAm.updateOomAdjLocked();
    //判断服务是否创建
    boolean created = false;
    try {
        //略
        mAm.notifyPackageUse(r.serviceInfo.packageName,
                             PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
        app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
        //[重]创建服务的启动
        //ActivityThread.scheduleCreateService
        app.thread.scheduleCreateService(r, r.serviceInfo,
                mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                app.repProcState);
        r.postNotification();
        created = true;
    } catch (DeadObjectException e) {
        mAm.appDiedLocked(app);
        throw e;
    } finally {
        //没有异常的话,为true,异常的话重新启动服务。
        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);
            }
        }
    }
    //略
    //[重]会发送sendServiceArgsLocked
    sendServiceArgsLocked(r, execInFg, true);
    //不是延迟启动的,如果到此已经启动差不多了,需要从列表中移除
    if (r.delayed) {
        getServiceMapLocked(r.userId).mDelayedStartList.remove(r);
        r.delayed = false;
    }
    //略
}

我们主要关注下面两个方法。

  1. scheduleCreateService()

  2. sendServiceArgsLocked()

先看scheduleCreateService()

ActivityThread.java

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;
    //发送CREATE_SERVICE
    sendMessage(H.CREATE_SERVICE, s);
}
handleMessage()
case CREATE_SERVICE:
    //处理创建服务
    handleCreateService((CreateServiceData)msg.obj);1
    break;
case BIND_SERVICE:
handleCreateService()
private void handleCreateService(CreateServiceData data) {
    unscheduleGcIdler();
    LoadedApk packageInfo = getPackageInfoNoCheck(
            data.info.applicationInfo, data.compatInfo);
    Service service = null;
    try {
        java.lang.ClassLoader cl = packageInfo.getClassLoader();
        //发射,new一个Service
        //这里不跟,具体看instantiateService
        service = packageInfo.getAppFactory()
                .instantiateService(cl, data.info.name, data.intent);
    } catch (Exception e) {
        if (!mInstrumentation.onException(service, e)) {
            throw new RuntimeException(
                "Unable to instantiate service " + data.info.name
                + ": " + e.toString(), e);
        }
    }
    try {
        //创建Service的Context
        ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
        context.setOuterContext(service);
        //创建Application
        //Application上面已经创建了,这里只是获取创建的
        //跟Activity的分析一样。
        Application app = packageInfo.makeApplication(false, mInstrumentation);

        //service 绑定context
        service.attach(context, this, data.info.name, data.token, app,
                ActivityManager.getService());
        //调用Service的onCreate()
        service.onCreate();
        mServices.put(data.token, service);
        //略
    } catch (Exception e) {
        if (!mInstrumentation.onException(service, e)) {
            throw new RuntimeException(
                "Unable to create service " + data.info.name
                + ": " + e.toString(), e);
        }
    }
}

创建Context,调用了服务的onCreate()。

Service.java

此时的Service是com.biumall.server.DemoService

DemoService.onCreate()
public void onCreate() {
}

至此,我们的服务依旧执行了onCreate(),也算是启动完成了。

接着继续分析ActiveServices.java的realStartServiceLocked()中sendServiceArgsLocked()

ActiveServices.java

sendServiceArgsLocked()
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
        boolean oomAdjusted) throws TransactionTooLargeException {
    //pendingStarts在startServiceLocked()添加的。
    final int N = r.pendingStarts.size();
    //不为0
    if (N == 0) {
        return;
    }
    //略
    try {
        //[重]scheduleServiceArgs,有回到了ActivityThread
        r.app.thread.scheduleServiceArgs(r, slice);
    } catch (TransactionTooLargeException e) {
        caughtException = e;
    } catch (RemoteException e) {
        caughtException = e;
    } catch (Exception e) {
        caughtException = e;
    }
    //略
}

ActivityThread.java

scheduleServiceArgs()
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;
        //发送SERVICE_ARGS
        sendMessage(H.SERVICE_ARGS, s);
    }
}
handleMessage()
case SERVICE_ARGS:
    handleServiceArgs((ServiceArgsData)msg.obj);
    break;
handleServiceArgs()
private void handleServiceArgs(ServiceArgsData data) {
    Service s = mServices.get(data.token);
    if (s != null) {
        try {
            //略
            //data.taskRemoved为false
            if (!data.taskRemoved) {
                //[重]这里执行了onStartCommand
                res = s.onStartCommand(data.args, data.flags, data.startId);
            } else {
                s.onTaskRemoved(data.args);
                res = Service.START_TASK_REMOVED_COMPLETE;
            }
            QueuedWork.waitToFinish();
            try {
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
            ensureJitEnabled();
        } catch (Exception e) {
            if (!mInstrumentation.onException(s, e)) {
                throw new RuntimeException(
                        "Unable to start service " + s
                        + " with " + data.args + ": " + e.toString(), e);
            }
        }
    }
}

哈哈,是不是意外,这里执行了onStartCommand()

Service.java

此时的Service是com.biumall.server.DemoService

DemoService.onStartCommand()
public @StartResult int onStartCommand(Intent intent, @StartArgFlags int flags, int startId) {
    onStart(intent, startId);
    return mStartCompatibility ? START_STICKY_COMPATIBILITY : START_STICKY;
}

到此,服务就启动完成了。

参考文章

部分内容涉及这里,其实很堵都类似的。

  1. startActivity之进程启动

  2. startActivity源码分析2

老文章,感觉也是摘抄的吧,忘了。

  1. startService分析(1)

  2. 启动startService()分析(2)

  3. 启动startService()分析(3)

 历史上的今天

  1. 2022: Android多窗口模式简单记录(0条评论)
  2. 2020: Android 6.0后权限的申请(0条评论)
版权声明 1、 本站名称: 笔友城堡
2、 本站网址: https://www.biumall.com/
3、 本站部分文章来源于网络,仅供学习与参考,如有侵权,请留言

暂无评论

暂无评论...

随机推荐

丰子恺:人生三十即是秋

我的年岁上冠用了“三十”二字,至今已两年了。不解达观的我,从这两个字上受到了不少的暗示与影响。虽然明明觉得自己的体格与精力比二十九岁时全然没有什么差异。但“三十”这一个观念笼在头上,犹之张了一顶阳伞,使我的全身蒙了一个暗淡色的阴影,又仿佛在日历上撕过了立秋的一页以后,虽然太阳的炎威依然没有减却,...

nginx服务器开启Gzip

前言启用Gzip压缩功能, 可以使网站的css、js 等资源在传输时进行压缩,尽管这样会消耗一定的cpu资源,但是会节约大量的出口带宽来提高访问速度。记录一下,方便自己查阅。正文我这用的是Nginx,因此以这个为例,如果是Apache,可以看参考链接一。找到nginx.conf文件# ...

[摘]Android稳定性(一)SWT和ANR

前言查找SWT啥意思时找到这篇文章,加上项目中用的也是MTK平台,因此摘抄这篇文章于此,方便自己学习和查阅。本文摘抄,感谢作者分析。好记性不如烂笔头正文SWT这里解释了什么是SWT以及SWT的作用。什么是SWTSWT:software watchdog,监控SystemServer进...

丝绒陨:年轻人,请忍受一下

暂时,你还需要忍受一下在可以忍受的范围之内或者刚好超出一点,这没什么就像可以承受海盐,可以承受灯塔的遥远亲人离去,朋友疏远……薄荷味的烟此刻正充满这间促狭的屋子在你年轻的时候,不会想到如今你选择在一间昏暗的屋子里住下在城市的肋骨间,感受一成不变的节拍要相信,所有妻子都会出轨。价格不...

川端康成:父母的心

诸位,把眼睛闭上五分钟,然后平心静气地想想父亲或者母亲试试看。你们的父母是如何深深地爱着你们,怀念子女的父母之心是多么温暖、多么广阔,直到现在不是依然使大家感慨万千、激动不已的么?啊,用不着闭上眼睛,你们大家无论早晚不是深深地感到双亲之恩么?这个故事,肯定也是让你们知道父母之心是多么伟大的故事之...

鲁迅 :秋夜

在我的后园,可以看见墙外有两株树,一株是枣树,还有一株也是枣树。这上面的夜的天空,奇怪而高,我生平没有见过这样奇怪而高的天空。他仿佛要离开人间而去,使人们仰面不再看见。然而现在却非常之蓝,闪闪地〖目夹〗着几十个星星的眼,冷眼。他的口角上现出微笑,似乎自以为大有深意,而将繁霜洒在我的园里的野花上。...