Android进阶(五):Service启动过程(最详细&最简单)

1.前言

  • 最近一直在看 《Android进阶解密》 的一本书,这本书编写逻辑、流程都非常好,而且很容易看懂,非常推荐大家去看看(没有收广告费,单纯觉得作者写的很好)。
  • 上一篇简单的介绍了Android进阶(四):Activity启动过程(最详细&最简单)
  • 今天就介绍Service 2种启动方式种:startService启动 (基于Android 8.0 系统)。
  • 本文提供一种看源码的思路,因此bindService启动流程就没有再本文展开(与startService流程类似)。
  • 文章中实例 linhaojian的Github

2.Context继承关系

  • 在讲解Service启动过程前,先了解一下它的继承关系,便于后续的源码理解:
    Context继承关系.png
  • 从图中,可以发现:
    • Activity,Service,Application都是ContextWrapper的子类;
    • ContextWrapper里面引用着一个ContextImpl实例;
    • ContextWrapper里所有的方法都是通过调用ContextImpl进行实现;
  • 通过上述3点可以发现,其他就是[装饰者模式](https://www.jianshu.com/p/16e946f42ce1)

2.Service启动过程的时序图

Service启动时序图.png


3.源码分析

3.1 startService()启动分析

3.1.1 ContextImpl
class ContextImpl extends Context {
    @Override
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, false, mUser);// 1
    }
    private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess(this);
            ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), user.getIdentifier());// 2
            // ....
            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}
  • 注释1:startService最终也是调用startServiceCommon函数
  • 注释2:ActivityManager.getService()其实就是ActivityManagerService,调用ActivityManagerService类里面的startService方法
3.1.2 ActivityManagerService
    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 {
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);// 1
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return res;
        }
    }
  • 注释1:调用ActiveServices的startServiceLocked()
3.1.3 ActiveServices
    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
            throws TransactionTooLargeException {
        //.....
        ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType, callingPackage,
                    callingPid, callingUid, userId, true, callerFg, false, false);// 1
        if (res == null) {
            return null;
        }
        if (res.record == null) {
            return new ComponentName("!", res.permission != null
                    ? res.permission : "private to package");
        }
        ServiceRecord r = res.record;
        if (!mAm.mUserController.exists(r.userId)) {
            Slog.w(TAG, "Trying to start service with non-existent user! " + r.userId);
            return null;
        }
        //.....
        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);// 2
        return cmp;
    }
  • 注释1:创建 & 封装启动Service的相关数据
  • 注释2:调用自身的startServiceInnerLocked()
    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();
        }
        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false); // 3
        if (error != null) {
            return new ComponentName("!!", error);
        }
        //.....
        return r.name;
    }
  • 注释3:调用自身的bringUpServiceLocked()
    private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
            // ....
        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
        final String procName = r.processName;
        String hostingType = "service";
        ProcessRecord app;
        if (!isolated) {
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
                        + " app=" + app);
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
                    realStartServiceLocked(r, app, execInFg);// 4
                    return null;
                } catch (TransactionTooLargeException e) {
                    throw e;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
                }
            }
        } else {
            app = r.isolatedProc;
            if (WebViewZygote.isMultiprocessEnabled()
                    && r.serviceInfo.packageName.equals(WebViewZygote.getPackageName())) {
                hostingType = "webview_service";
            }
        }
        //.....
    }
  • 注释4:调用自身的realStartServiceLocked()
    private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        //.....
        boolean created = false;
        try {
            if (LOG_SERVICE_START_STOP) {
                String nameTerm;
                int lastPeriod = r.shortName.lastIndexOf('.');
                nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName;
                EventLogTags.writeAmCreateService(
                        r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
            }
            synchronized (r.stats.getBatteryStats()) {
                r.stats.startLaunchedLocked();
            }
            mAm.notifyPackageUse(r.serviceInfo.packageName,
                                 PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
            app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);// 5
            r.postNotification();
            created = true;
        } catch (DeadObjectException e) {
            Slog.w(TAG, "Application dead when creating service " + r);
            mAm.appDiedLocked(app);
            throw e;
        } finally {
            //...
        }
        // 通知ActivityThread调用Service的onStartCommand方法
        sendServiceArgsLocked(r, execInFg, true);// 6
        //.....
    }
  • 注释5:通知ActivityThread,真正的创建Service
  • 注释6:调用自身的sendServiceArgsLocked()启动Service的其他生命周期方法,下面会介绍
3.1.4 ActivityThread
  • scheduleCreateService()其实就是通过Handler机制进行线程切换,最后会调用handleCreateService();
    private void handleCreateService(CreateServiceData data) {
        unscheduleGcIdler();
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);// 1
        Service service = null;
        try {
            // 通过类加载器,创建Service实例
            java.lang.ClassLoader cl = packageInfo.getClassLoader();// 2
            service = packageInfo.getAppFactory()
                    .instantiateService(cl, data.info.name, data.intent);// 3
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to instantiate service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }
        try {
            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            //向Service对象中初始化基本设置
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());// 4
            //调用service的onCreate生命周期函数
            service.onCreate();// 5
            mServices.put(data.token, service);
            try {
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to create service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }
    }
  • 注释1:获取LoadedApk对象,负责解析manifest文件
  • 注释2:获取ClassLoader类加载器,负责创建Service实例
  • 注释3:通过AppComponentFactory,创建Service对象
  • 注释4:设置Service基础参数
  • 注释5:调用Service的onCreate方法
3.1.5 AppComponentFactory
public class AppComponentFactory {
    public @NonNull Service instantiateService(@NonNull ClassLoader cl,
            @NonNull String className, @Nullable Intent intent)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return (Service) cl.loadClass(className).newInstance();// 1
    }
}
  • 注释1:通过类加载器,创建Service实例
3.1.6 ActiveServices的sendServiceArgsLocked()函数
    private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
            boolean oomAdjusted) throws TransactionTooLargeException {
        //...        
       Exception caughtException = null;
        try {
            r.app.thread.scheduleServiceArgs(r, slice);// 1
        } catch (TransactionTooLargeException e) {
            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Transaction too large for " + args.size()
                    + " args, first: " + args.get(0).args);
            Slog.w(TAG, "Failed delivering service starts", e);
            caughtException = e;
        }
        //....
    }
  • 注释1:调用ActivityThread的scheduleServiceArgs函数(在Service创建之后,会调用sendServiceArgsLocked(),实现其他的生命周期方法的调用)
3.1.7 ActivityThread的handleServiceArgs函数
  • scheduleServiceArgs()最终通过Handler机制切换线程 & 调用handleServiceArgs();
    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) {
                    res = s.onStartCommand(data.args, data.flags, data.startId);// 1
                } else {
                    s.onTaskRemoved(data.args);
                    res = Service.START_TASK_REMOVED_COMPLETE;
                }
               //...
            } catch (Exception e) {
                // ...
            }
        }
    }
  • 注释1:调用Service的onStartCommand()

4.类关系

Service启动类结构.png

  • 通过上图发现,Service启动过程就是AMS与ActivityThread不同的进程交互实现的。

5.总结

  • 到此,**Service启动过程**介绍完毕。
  • 如果喜欢我的分享,可以点击  关注  或者  ,你们支持是我分享的最大动力 。
    linhaojian的Github

欢迎关注linhaojian_CSDN博客或者linhaojian_简书

不定期分享关于安卓开发的干货。


写技术文章初心
  • 技术知识积累
  • 技术知识巩固
  • 技术知识分享
  • 技术知识交流
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值