startService()源码分析

Android  源码分析  2023年12月8日 pm12:12发布3个月前更新 91es.com站长
129 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、 本站名称: 91易搜
2、 本站网址: 91es.com
3、 本站内容: 部分来源于网络,仅供学习和参考,若侵权请留言
3、 本站申明: 个人流水账日记,内容并不保证有效

暂无评论

暂无评论...

随机推荐

[摘]音视频学习系列第(一)篇---基础概念

shui知道最在学习这个,这个博主总结得不错,因此摘抄于此,以方便自己查阅。可访问改博主sofarsogoo_932d的一系列文章《音视频学习系列》,感谢他的分享。什么是音/视频音频声音的集合视频图片的集合,当一段连续的图片不断的出现在人眼前(至少要求1秒24帧,即一秒内连续出...

Android双屏异显(Presentation)的简单使用

前言Android 从4.2开始支持双屏显示,支持版本为17以上。Android 双屏原理说白了,自定义一个Presentation类,Android 的标准实现是使用 API Presentation 来实现异显的功能。public class Presentation extends D...

樊小纯:借我

借我一个暮年借我碎片借我瞻前与顾后借我执拗如少年借我后天长成的先天借我变如不曾改变借我素淡的世故和明白的愚借我可预知的脸借我悲怆的磊落借我温软的鲁莽和玩笑的庄严借我最初与最终的不敢借我不言而喻的不见借我一场秋啊可你说这已是冬天

Fragment already added

前言项目中会用Viewpager+Fragment来显示图片,先项目中测试ok,但是我单独拎出来做简单调试时出现:java.lang.IllegalStateException: Fragment already added: PlayFragment尴尬了,就我拎出来的demo代码片段有...

sendBroadcast静态广播源码分析

前言本次分析一下Android P开机后发送静态广播源码分析,记录一下,方便自己查阅。部分流程跟前面的源码分析《startActivity源码分析》和《startService源码分析》都比较类似,所以重复的步骤就省略。PS:启动startActivity的比较复杂,流程多,但搞懂了这个,...

[摘]常见音视频格式

前言本文内容(音视频格式介绍)来源网络,这里我只是整合一下。好记性不如烂笔头正文常见的音频编码格式MP3全称是MPEG Audio Layer3。MP3是利用MPEG Audio Layer 3的技术,将音乐以1:10甚至1:12 的压缩率,压缩成容量较小的file。mp3能够在音质...