Android深入四大组件(二)Service的启动过程

7人阅读 评论(0) 收藏 举报
分类:

相关文章
Android深入理解四大组件系列

前言

此前我用较长的篇幅来介绍Android应用程序的启动过程(根Activity的启动过程),这一篇我们接着来分析Service的启动过程。建议阅读此篇文章前,请先阅读Android深入四大组件(一)应用程序启动过程(前篇)Android深入四大组件(一)应用程序启动过程(后篇)这两篇文章。

1.ContextImpl到ActivityManageService的调用过程

要启动Service,我们会调用startService方法,它的实现在ContextWrapper中,代码如下所示。
frameworks/base/core/java/android/content/ContextWrapper.java

public class ContextWrapper extends Context {
    Context mBase;
...
  @Override
    public ComponentName startService(Intent service) {
        return mBase.startService(service);
    }
...    
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在startService方法中会调用mBase的startService方法,Context类型的mBase对象具体指的是什么呢?在Android深入四大组件(一)应用程序启动过程(后篇)这篇文章中我们讲过ActivityThread启动Activity时会调用如下代码创建Activity的上下文环境。
frameworks/base/core/java/android/app/ActivityThread.java

 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
  ...
            if (activity != null) {
                Context appContext = createBaseContextForActivity(r, activity);//1
         ...
                }
                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);
                ...
        }
        return activity;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

在注释1处创建上下文对象appContext ,并传入Activity的attach方法中,将Activity与上下文对象appContext 关联起来,这个上下文对象appContext 的具体类型是什么,我们接着查看createBaseContextForActivity方法,代码如下所示。
frameworks/base/core/java/android/app/ActivityThread.java

private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) {
...

    ContextImpl appContext = ContextImpl.createActivityContext(
            this, r.packageInfo, r.token, displayId, r.overrideConfig);
    appContext.setOuterContext(activity);
    Context baseContext = appContext;
    ...
    return baseContext;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

这里可以得出结论,上下文对象appContext 的具体类型就是ContextImpl 。Activity的attach方法中将ContextImpl赋值给ContextWrapper的成员变量mBase中,因此,mBase具体指向就是ContextImpl 。
那么,我们紧接着来查看ContextImpl的startService方法,代码如下所示。
frameworks/base/core/java/android/app/ContextImpl.java

Override
public ComponentName startService(Intent service) {
    warnIfCallingFromSystemProcess();
    return startServiceCommon(service, mUser);
}
 private ComponentName startServiceCommon(Intent service, UserHandle user) {
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess(this);
            /**
            * 1
            */
            ComponentName cn = ActivityManagerNative.getDefault().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), getOpPackageName(), user.getIdentifier());
      ...
            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

startService方法中会return startServiceCommon方法,在startServiceCommon方法中会在注释1处调用ActivityManageService(AMS)的代理对象ActivityManagerProxy(AMP)的startService方法,最终会调用AMS的startService方法。至于注释1处的代码为何会调用AMS的startService方法,在Android深入四大组件(一)应用程序启动过程(前篇)这篇文章中已经讲过,这里不再赘述。
ContextImpl到ActivityManageService的调用过程如下面的时序图所示。

2.ActivityThread启动Service

我们接着来查看AMS的startService方法。
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

Override
public ComponentName startService(IApplicationThread caller, Intent service,
        String resolvedType, String callingPackage, int userId)
        throws TransactionTooLargeException {
 ...
    synchronized(this) {
 ...
        ComponentName res = mServices.startServiceLocked(caller, service,
                resolvedType, callingPid, callingUid, callingPackage, userId);//1
        Binder.restoreCallingIdentity(origId);
        return res;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

注释1处调用mServices的startServiceLocked方法,mServices的类型是ActiveServices,ActiveServices的startServiceLocked方法代码如下所示。
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, String callingPackage, final int userId)
            throws TransactionTooLargeException {
      ...
        return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
    }

   ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {

     ...
        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
     ...
        return r.name;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

startServiceLocked方法的末尾return了startServiceInnerLocked方法,而startServiceInnerLocked方法中又调用了bringUpServiceLocked方法:
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

  private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
...
  final String procName = r.processName;//1
  ProcessRecord app;
  if (!isolated) {
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);//2
            if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
                        + " app=" + app);
            if (app != null && app.thread != null) {//3
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, 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 (app == null && !permissionsReviewRequired) {//5
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    "service", r.name, false, isolated, false)) == null) {//6
              ...
            }
            if (isolated) {
                r.isolatedProc = app;
            }
        }

 ...     
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

在注释1处得到ServiceRecord的processName的值赋值给procName ,其中ServiceRecord用来描述Service的android:process属性。注释2处将procName和Service的uid传入到AMS的getProcessRecordLocked方法中,来查询是否存在一个与Service对应的ProcessRecord类型的对象app,ProcessRecord主要用来记录运行的应用程序进程的信息。注释5处判断Service对应的app为null则说明用来运行Service的应用程序进程不存在,则调用注释5处的AMS的startProcessLocked方法来创建对应的应用程序进程。关于创建应用程序进程请查看Android应用程序进程启动过程(前篇)Android应用程序进程启动过程(后篇)这两篇文章。注释3处判断如果用来运行Service的应用程序进程存在,则调用注释4处的realStartServiceLocked方法:

frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

private final void realStartServiceLocked(ServiceRecord r,
        ProcessRecord app, boolean execInFg) throws RemoteException {
   ...
    try {
       ...
        app.thread.scheduleCreateService(r, r.serviceInfo,
                mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                app.repProcState);
        r.postNotification();
        created = true;
    } catch (DeadObjectException e) {
      ...
    } 
    ...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

在realStartServiceLocked方法中调用了app.thread的scheduleCreateService方法。其中app.thread是IApplicationThread类型的,它的实现是ActivityThread的内部类ApplicationThread,其中ApplicationThread继承了ApplicationThreadNative,而ApplicationThreadNative继承了Binder并实现了IApplicationThread接口。ApplicationThread的scheduleCreateService方法如下所示。
frameworks/base/core/java/android/app/ActivityThread.java

   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;
        sendMessage(H.CREATE_SERVICE, s);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

首先将要启动的信息封装成CreateServiceData 对象并传给sendMessage方法,sendMessage方法向H发送CREATE_SERVICE消息,H是ActivityThread的内部类并继承Handler。这个过程和应用程序的启动过程(根Activity启动过程)是类似的。我们接着查看H的handleMessage方法。
frameworks/base/core/java/android/app/ActivityThread.java

  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;
            ...
             }
          ...
          }
       ...   
  }  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

handleMessage方法根据消息类型,调用了handleCreateService方法:

frameworks/base/core/java/android/app/ActivityThread.java

 private void handleCreateService(CreateServiceData data) {
        unscheduleGcIdler();
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);//1
        Service service = null;
        try {
            java.lang.ClassLoader cl = packageInfo.getClassLoader();//2
            service = (Service) cl.loadClass(data.info.name).newInstance();//3
        } catch (Exception e) {
           ...
            }
        }
        try {
            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);

            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);//4
            context.setOuterContext(service);

            Application app = packageInfo.makeApplication(false, mInstrumentation);
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManagerNative.getDefault());//5
            service.onCreate();//6
            mServices.put(data.token, service);//7
         ...
        } catch (Exception e) {
            ...
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

注释1处获取要启动Service的应用程序的LoadedApk,LoadedApk是一个APK文件的描述类。注释2处通过调用LoadedApk的getClassLoader方法来获取类加载器。接着在注释3处根据CreateServiceData对象中存储的Service信息,将Service加载到内存中。注释4处创建Service的上下文环境ContextImpl对象。注释5处通过Service的attach方法来初始化Service。注释6处调用Service的onCreate方法,这样Service就启动了。在注释7处将启动的Service加入到ActivityThread的成员变量mServices中,其中mServices是ArrayMap类型。
最后给出这一节的时序图。


欢迎关注我的微信公众号,第一时间获得博客更新提醒,以及更多成体系的Android相关原创技术干货。
扫一扫下方二维码或者长按识别二维码,即可关注。

转自:https://blog.csdn.net/itachi85/article/details/70515863

查看评论

Android四大组件之activity启动过程

最近一直在搞项目上的事,前端的东西真是又多又杂啊,没办法现在有点时间来仔细研究Android上的,从这开始四大组件的源码工作过程,首先说为什么要从源码上研究四大组件的工作过程,第一,我们平时用的时候直...
  • seven_poul
  • seven_poul
  • 2017-04-09 00:17:15
  • 260

Android深入四大组件(一)应用程序启动过程

在此前的文章中,我讲过了Android系统启动流程和Android应用进程启动过程,这一篇顺理成章来学习Android 7.0的应用程序的启动过程。分析应用程序的启动过程其实就是分析根Activity...
  • itachi85
  • itachi85
  • 2017-04-06 14:01:30
  • 3256

Service 相关操作

  • 2016年01月25日 15:51
  • 6.14MB
  • 下载

从源码出发深入理解 Android Service

本文是 Android 系统学习系列文章中的第三章节的内容,介绍了 Android Service 相关的基础知识,然后从源码的角度上分析 Service 的一些实现原理。对此系列感兴趣的同学,可以收...
  • superjimmy
  • superjimmy
  • 2016-09-22 20:28:01
  • 799

Android四大组件之Service全面学习

什么是服务Android 的服务是 Android 四大组件之一,其他的三大组件是Activity、Broadcast Receiver、Content Provider。 它是程序运行在后台的解决方...
  • tutucoo
  • tutucoo
  • 2017-11-18 12:50:12
  • 530

深入剖析Android四大组件(七)——Activity启动的4个阶段

在Activity的启动流程中,共有4个阶段: 1.第一阶段——启动信息翻译以及服务调用 2.第二阶段——Activity的相关处理 3.第三阶段——处理应用程序进程 4.第四阶段——显示应用程序并处...
  • liyuanjinglyj
  • liyuanjinglyj
  • 2015-11-21 20:35:10
  • 6254

Android四大组件--Activity启动过程(全)

Activity启动过程:
  • u010308400
  • u010308400
  • 2015-12-04 15:47:13
  • 329

Android深入四大组件(五)Content Provider的启动过程

Content Provider做为四大组件之一,通常情况下并没有其他的组件使用频繁,但这不能作为我们不去深入学习它的理由。关于Content Provider一篇文章是写不完的,这一篇文章先来介绍它...
  • itachi85
  • itachi85
  • 2017-05-22 01:09:50
  • 2956

Android Studio 四大组件之一 Service简介

Android Studio 四大组件之 Service简介
  • u011402573
  • u011402573
  • 2016-09-09 21:29:19
  • 445

Android开发四大组件之Service(详解篇)

Service是android系统中的四大组件之一(Activity、Service、BroadcastReceiver、ContentProvider),它跟Activity的级别差不多,区别是Se...
  • fengyuzhengfan
  • fengyuzhengfan
  • 2014-07-21 11:00:42
  • 5656
    个人资料
    持之以恒
    等级:
    访问量: 15万+
    积分: 4600
    排名: 7989
    文章分类
    最新评论