startService()源码分析

Android2023年12月8日 pm12:12发布8个月前更新 3XCN.COM站长
0 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、 本站名称: 91易搜
2、 本站网址: 91es.com3xcn.com
3、 本站文章: 部分来源于网络,仅供站长学习和参考,若侵权请留言
广告也精彩

相关文章

广告也精彩

暂无评论

评论审核已启用。您的评论可能需要一段时间后才能被显示。

暂无评论...

网站升级中

公告

近期网站升级中,可能存在一些bug。欢迎反馈 https://www.91es.com/we.html

本站域名

本站域名 : 91es.com3xcn.com。本站邮箱 : 站长邮箱 i@oorr.cn,通知邮箱we@oorr.cn ,如有更新,请看公告 。