Framework 学习之旅:Service 启动过程

前言

Service 的启动过程将分为两个部分,分别是ContextImpl到ActivityManageService调用过程和ActivityThread启动Service过程。

ContextImpl到ActivityManageService调用过程

一般启动服务操作在Activity中调用startService方法,从Activity的startService开始进行了解,Activity继承ContextWrapper,所以调用的是ContextWrapper的startService方法。

frameworks/base/core/java/android/content/ContextWrapper.java

public class ContextWrapper extends Context {
    Context mBase;

    public ContextWrapper(Context base) {
        mBase = base;
    }

    @Override
    public ComponentName startService(Intent service) {
      return mBase.startService(service);
    } 
}

从以上代码可知,startService方法最终调用的是mBase的startService方法,mBase是Context类型并且它是一个抽象类,mBase具体指向实际上是ContextImpl类(它是Context的实现类)。原因是:在Activity的启动流程中,ActivityThread启动Activity会调用performLaunchActivity()方法。

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

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ......
    ContextImpl appContext = createBaseContextForActivity(r);//1
    ......
    if (activity != null) {
        ......
          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);
        ......
    }
}

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

final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
              ......
               attachBaseContext(context);
              ......
            }
            
protected void attachBaseContext(Context newBase) {
        super.attachBaseContext(newBase); 
        if (newBase != null) {
            newBase.setAutofillClient(this);
            newBase.setContentCaptureOptions(getContentCaptureOptions());
        }
    }

在注释1处创建上下文对象appContext,并传入Activity的attach方法中,将Activity与上下文对象appContext关联起来,这个上下文对象appContext的具体类型是什么,查看createBaseContextForActivity()方法:

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

private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
    .....
    ContextImpl appContext = ContextImpl.createActivityContext(
                this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
   .....
   return appContext;
}

从以上代码可以看出,上下文对象appContext具体类型就是Contextlmpl,在Activity的attach方法中将Contextlmpl赋值给ContextWrapper的成员变量mBase,mBase具体指向的就是Contextlmpl。查看Contextlmpl的startService方法:

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

    @Override
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, false, mUser);
    }
    
    private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess(this);
            // 直接调用 AMS的 startService方法 , 返回一个 ComponentName 对象。
            ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), user.getIdentifier());
            .......
            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

ContextImpl的startService方法调用自身的startServiceCommon方法,在startServiceCommon()方法中调用AMS的代理IActivityManager的startService方法,最终调用的是AMS的startService方法。

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

    /**
     * @hide
     */
    @UnsupportedAppUsage
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }
    
     @UnsupportedAppUsage
    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

从以上源码可知,ActivityManager最终获取的是IActivityManager,通过AIDL实现应该程序进程与AMS所在的SystemServer进程通信,而他的实现则在ActivityMangerService中。前面分析的ContextImpl的startServiceCommon方法中最终调用的就是AMS的startServie方法,并且将mMainThread.getApplicationThread获取的IApplicationThread的实现类ApplicationThread引用传递给AMS,方便后续AMS能与应用程序进程通信启动Service。

时序图

Framework 学习之旅:Service 启动过程_第1张图片

ActivityThread启动Service过程

接着,上一节分析ContextImpl最终调用的是AMS的startService方法:

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

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    ......
    
    final ActiveServices mServices;
    ......
            
     public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage, int userId)
            throws TransactionTooLargeException {
        enforceNotIsolatedCaller("startService");
        // Refuse possible leaked file descriptors
        ........
        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;
        }
    }
}

从源码可以看出,AMS实现了IActivityManager,并且实现了startService方法。从注释1处调用mServices的startServiceLocked方法,mServices的类型是ActiveServices,ActiveServices是用来管理Service的类。继续看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, boolean fgRequired, String callingPackage,
            final int userId, boolean allowBackgroundActivityStarts)
            throws TransactionTooLargeException {
        .......

        ServiceLookupResult res =
            retrieveServiceLocked(service, null, resolvedType, callingPackage,
                    callingPid, callingUid, userId, true, callerFg, false, false);//1
        .......

        ServiceRecord r = res.record;//2

        .......

        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);//3
        return cmp;
    }

注释1处的retrieveServiceLocked方法会查找是否有与参数service对应的ServiceRecord,如果没有找到,就会调用PackageManagerService去获取参数service对应的Service信息,并封装到ServiceRecord中,最后将ServiceRecord封装为ServiceLookupResult返回。其中ServiceRecord用于描述一个Service。

注释2处,根据ServiceLookupResult获取对应的ServiceRecord,并传入到注释3处的startServicelnnerLocked方法中。

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

ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
       
        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);//1
        if (error != null) {
            return new ComponentName("!!", error);
        }

       .....

        return r.name;
    }

在startServicelnnerLock方法继续调用了ActiveServices的bringUpServiceLocked方法,继续查看:

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

final ActivityManagerService mAm;
 
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
    // 获取Service在哪个进程中运行
    final String procName = r.processName;//1
    HostingRecord hostingRecord = new HostingRecord("service", r.instanceName);
    ProcessRecord app;
    if (!isolated) {
        app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);//2
        if (app != null && app.thread != null) {//3
            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.shortInstanceName, e);
                }
        }    
    }else{
        app = r.isolatedProc;
        .....
    }
    
    // 如果用来运行Service的应用程序进程不存在    
    if (app == null && !permissionsReviewRequired) {//5
        // 创建应用程序 
        if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingRecord, false, isolated, false)) == null) {//6
            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;
}

从上面的代码来看,注释1处得到ServiceRecord的processName值并赋值给procName,其中processName用来描述Service要在哪个进程中运行,默认是当前进程,我们也可以在AndroidManifest文件中设 android:process属性来新开启一个进程运行Service 。

在注释2处将procName和Service的uid传入到AMS的getProcessRecordLocked方法,查询是否存在一个与Service对应的ProcessRecord 类型的对象app,ProcessRecord主要描述运行的程序进程的信息。

注释5处判断Service对应app为null则说明用来运行Service的应用程序不存在,则调用注释6处的AMS的startProcessLock方法来创建对应的应用程序进程。

在注释3处判断如果用来运行Service的应用程序存在,则调用注释4处的rea!StartServiceLocked方法来启动 Service:

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

private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
   .....
   r.setProcess(app);//1
   
    try {
            ......
            
            app.thread.scheduleCreateService(r, r.serviceInfo,
            mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
                    app.getReportedProcState());//2
            r.postNotification();
            created = true;
        } catch (DeadObjectException e) {
           .....
        } finally {
            ........
        }
}

注释1处将获取的应用程序进程设置给ServiceRecord也就是Service组件,代表它将在哪个应用程序进程启动。

注释2处realStartServiceLocked方法中调用了app.thread的scheduleCreateService方法。其中app.thread是IApplicationThread类型的,它的实现是ActivityThread的内部类ApplicationThread。

继续看到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;//1
            sendMessage(H.CREATE_SERVICE, s);//2
    }

scheduleLaunchActivity的方法将启动Service的参数封装成 CreateServiceData,sendMessage方法向H类发送类型为CREATE_SERVICE的消息,并将CreateServiceData传递过去。sendMessage
方总有多个重载方法,最终调用的sendMessage方法如下所示:

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

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) {
            Slog.v(TAG,
                    "SCHEDULE " + what + " " + mH.codeToString(what) + ": " + arg1 + " / " + obj);
        }
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }

这里mH指的是H,它是ActivityThread的内部类并继承自Handler ,是应用程序进程中主线程的消息管理类。我们接着查看handleMessage方法:

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

class H extends Handler {
     public static final int CREATE_SERVICE          = 114;
     .....
     public void handleMessage(Message msg) {
         switch (msg.what) {
             ....
             case CREATE_SERVICE:
               handleCreateService((CreateServiceData)msg.obj);
               break;
             ....  
         }
     }
     ....
}

handleMessage方法根据消息类型为CREAE_SERVICE调用handleCreateService方法:

private void handleCreateService(CreateServiceData data) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        // 获取要启动Service的应用程序的LoadedApk
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);//1
        Service service = null;
        try {
            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);

            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);//2
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            //获取类加载器
            java.lang.ClassLoader cl = packageInfo.getClassLoader();//3
            // 创建Service 实例
            service = packageInfo.getAppFactory()
                    .instantiateService(cl, data.info.name, data.intent);//4
            // Service resources must be initialized with the same loaders as the application
            // context.
            context.getResources().addLoaders(
                  app.getResources().getLoaders().toArray(new ResourcesLoader[0]));

            context.setOuterContext(service);
            // 初始化Service
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());//5
            service.onCreate();//6
            mServices.put(data.token, service);//7
            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处获取要启动Service的应用程序的LoadedApk,LoadedApk是一个APK文件的描述类。

在注释2处创建Service的上下文环境ContextImpl对象。

在注释3处通过调用LoadedAPK的getClassLoader方法来获取类加载器。

在注释4处,创建Service实例。

在注释5处通过Service的attach方法来初始化Service。

在注释6处调用Service的onCreate方法,这样Service就启动了。

在注释7处将启动的Service加入到ActivityThread的成员变量mServices中,其中mServices是ArrayMap类型。

时序图

Framework 学习之旅:Service 启动过程_第2张图片
至此,Service 启动分析过程结束。

你可能感兴趣的:(Framework,Service)