【Service的工作过程】startService的启动过程

Service有两种开启方式即startService、bindService,本章是startService的启动流程。

目录

在这里插入图片描述

ContextImpl到AMS的调用过程

时序图

在这里插入图片描述

了解

最常见的开启service组件的方式就是在Activity中直接startService,其实在Activity也是Context的一个子类,startService方法定义在Context这个类中。Context相关的集成关系如下图

在这里插入图片描述
Context定义了整个应用运行的上下文环境,是一个抽象类,ContextWrapper是其包装类(从名字可以看出装饰者模式的痕迹)真正的实现类是ContextImpl类。

具体过程

activity#startService
public class ContextWrapper extends Context {
    @UnsupportedAppUsage
    Context mBase;
    
    ...
    
    @Override
    public ComponentName startService(Intent service) {
        return mBase.startService(service);
    }
}

startService方法中会调用mBase的startService方法,Context类型的mBase对象具体指的是什么呢?这里先卖个关子。通过以下来说明下:

Activity的启动过程中的ActivityThread启动Activity时会创建Activity的上下文环境如下

// ActivityThread 中
 
 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
 
 ...
 
 // 1、首先创建上下文环境
 //createBaseContextForActivity 内部通过ContextImpl.createActivityContext 来进行创建
 ContextImpl appContext = createBaseContextForActivity(r);
...

// 2、吧上下文环境传与activity关联起来。
 activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback,
                        r.assistToken);


}

attach 内部将ContextImpl赋值给ContextWrapper 成员变量mBase。由于ContextWrapper 是ContextImpl的装饰者,这样ContextWrapper就可以行驶ContextImpl的功能了。

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

  private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {

...
//ActivityManager.getService() 返回IActivityManager 对象
//IActivityManager 为AMS的代理类
 ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), user.getIdentifier());
...
}

startServiceCommon方法中会调用AMS的代理IActivityManager的startService方法,最终调用的是AMS的startService方法

ActivityThread 启动Service调用过程

时序图

在这里插入图片描述

具体过程

AMS#startService
 @Override
    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage, int userId)
            throws TransactionTooLargeException {
...
         ComponentName res;
            try {
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return res;

}

这里调用mServices的startServiceLocked方法,mServices的类型是ActiveServices 继续往下看

ActiveServices #startServiceLocked
  ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
            throws TransactionTooLargeException {
...
//1、retrieveServiceLocked方法会查找service参数对应的ServiceRecord,
//并将ServiceRecord封装成serviceLookUpResult返回。
//ps:当找不到ServiceRecord时会调用PMS获取service信息,并封装到ServiceRecord中
  ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType, callingPackage,
                    callingPid, callingUid, userId, true, callerFg, false);
        if (res == null) {
            return null;
        }
        if (res.record == null) {
            return new ComponentName("!", res.permission != null
                    ? res.permission : "private to package");
        }
// 2、通过上述ServiceLookupResult来取出ServiceRecord 对象
        ServiceRecord r = res.record;
...

//3、ServiceRecord 对象继续往下传递
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        return cmp;
}
ActiveServices #startServiceInnerLocked
    ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
...
 // 调用 bringUpServiceLocked
 String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
        if (error != null) {
            return new ComponentName("!!", error);
        }
...
 return r.name;
}
ActiveServices #bringUpServiceLocked
  private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {

...
  //1、processName描述service想要运行的进程,默认值为当前进程
  final String procName = r.processName;
        String hostingType = "service";
        ProcessRecord app;

        if (!isolated) {
        //2、mAm为AMS类型对象,这里调用AMS的getProcessRecordLocked表示去AMS中查询
        //是否存在一个与service对应的ProcessRecord类型对象。
            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) {//3、service应用进程存在
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
                    //4、启动service
                    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 {       
            app = r.isolatedProc;
            if (WebViewZygote.isMultiprocessEnabled()
                    && r.serviceInfo.packageName.equals(WebViewZygote.getPackageName())) {
                hostingType = "webview_service";
            }
        }
        // 假如需要的应用进程不存在时,创建应用进程。
        if (app == null && !permissionsReviewRequired) {
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingType, r.name, false, isolated, false)) == null) {
                String msg = "Unable to launch app "
                        + r.appInfo.packageName + "/"
                        + r.appInfo.uid + " for service "
                        + r.intent.getIntent() + ": process is bad";
                Slog.w(TAG, msg);
                bringDownServiceLocked(r);
                return msg;
            }
            if (isolated) {
                r.isolatedProc = app;
            }
        }
...
return null;
}

ActiveServices #realStartServiceLocked
 private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
...
 app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);
...

}

app.thread是IApplicationThread 类型,它的实现是ActivityThread的内部类ApplicationThread,所以最终会调用ApplicationThread的scheduleCreateService

ActivityThread类#内部类ApplicationThread#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;
           // 内部调用H类的sendMessage方法发送消息。
            sendMessage(H.CREATE_SERVICE, s); 
        }

//sendMessage 重载方法的最终调用
 private void sendMessage(int what, Object obj, int arg1, int arg2, int seq) {
        if (DEBUG_MESSAGES) Slog.v(
                TAG, "SCHEDULE " + mH.codeToString(what) + " arg1=" + arg1 + " arg2=" + arg2 +
                        "seq= " + seq);
        Message msg = Message.obtain();
        msg.what = what;
        SomeArgs args = SomeArgs.obtain();
        args.arg1 = obj;
        args.argi1 = arg1;
        args.argi2 = arg2;
        args.argi3 = seq;
        msg.obj = args;
        //H类的sendMessage方法
        mH.sendMessage(msg);
    }

这里将启动service参数封装成CreateServiceData 对象,并通过H类的sendMessage发送消息。H 类通过handleMessage处理消息。

H#handleMessage
 public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
            ...
            
 case CREATE_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
                    handleCreateService((CreateServiceData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
...
}

H 类是一个Handle类,是ActivityThread的内部类。这里调用ActivityThread的handleCreateService方法进行后续处理。

ActivityThread#handleCreateService
   private void handleCreateService(CreateServiceData data) {

        unscheduleGcIdler();
        //1、获取要启动Service的应用程序的LoadedApk 信息
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
        // 2、获取类加载器,创建service 对象。
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = (Service) cl.loadClass(data.info.name).newInstance();
        }
        ...
        
 try {
            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
            // 3、创建Service的上下文环境
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            // 4、通过service的attach方法来初始化service
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
             //5、调用Service 类对象service启动service       
            service.onCreate();
        // 6、和Activity类似,启动的组件信息在ActivityThread类的对应成员信息中存储。
            mServices.put(data.token, service);
            //mServices是一个ArrayMap
            try {
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
}

The end

参考:
安卓进阶解密:微信读书版

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值