android 9.0 startService启动Servcie的过程分析

在Activity中使用startService启动Service时,会调用ContextWrapper的startService方法

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/content/ContextWrapper.java

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

这个方法的mBase就是一个ContextImpl类型的对象。所以这里调用了ContextImpl类的startService方法

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ContextImpl.java

@Override
public ComponentName startService(Intent service) {
    warnIfCallingFromSystemProcess();
    //注意传入的第二个参数是 false ,表示启动的服务不是前台服务
    return startServiceCommon(service, false, mUser);
}

private ComponentName startServiceCommon(Intent service, boolean requireForeground,
        UserHandle user) {
    try {
    //  Android 5.0后强制要求Service必须通过显式Intent启动5,否则会直接抛出异常
        validateServiceIntent(service);
        service.prepareToLeaveProcess(this);
	//关键代码
        ComponentName cn = ActivityManager.getService().startService(
            mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                        getContentResolver()), requireForeground,
                        getOpPackageName(), user.getIdentifier());
        // ...
        return cn;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

这个方法内部通过先调用validateServiceIntent方法进行Intent检查,Android 5.0后强制要求Service必须通过显式Intent启动5,否则会直接抛出异常,接着调用 ActivityManager.getService()获取到了ActivityManagerService(后面简称AMS)在app进程的代理对象,并调用了这个代理对象的startService方法,下面看看AMS中的startService方法的具体实现:


http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

@Override
public ComponentName startService(IApplicationThread caller, Intent service,
        String resolvedType, boolean requireForeground, String callingPackage, int userId)
        throws TransactionTooLargeException {
    enforceNotIsolatedCaller("startService");
    // ...
    synchronized(this) {
        // ...
        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方法,下面看看这个方法具体实现:


http://androidxref.com/9.0.0_r3/xref/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)
        throws TransactionTooLargeException {

    // ...
    // 关键代码
    ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
    return cmp;
}


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;
}


private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
        boolean whileRestarting, boolean permissionsReviewRequired)
        throws TransactionTooLargeException {
   
    //...

    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";
            bringDownServiceLocked(r);
            return msg;
        }
	// ...
    }

    // ...
    return null;
}

这个方法中的mAm.startProcessLocked(),mAm这个变量是AMS,代码跳转到AMS类中执行,下面看看这个方法


http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

@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 */);
}

接着调用了startProcessLocked的几个重载方法后,最终调用了startProcess方法,startProcess方法内部会调用Process类的start方法


http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/os/Process.java

public static final ProcessStartResult start(final String processClass,
                              final String niceName,
                              int uid, int gid, int[] gids,
                              int runtimeFlags, int mountExternal,
                              int targetSdkVersion,
                              String seInfo,
                              String abi,
                              String instructionSet,
                              String appDataDir,
                              String invokeWith,
                              String[] zygoteArgs) {
    return zygoteProcess.start(processClass, niceName, uid, gid, gids,
                runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
}

这个方法内部又调用了ZygoteProcess类的start方法。这个过程是SystemServer进程和ZygoteProcess进程进行通信的过程,它们之间通信是通过Socket进行通信的。


http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/os/ZygoteProcess.java


public final Process.ProcessStartResult start(final String processClass,
                                              final String niceName,
                                              int uid, int gid, int[] gids,
                                              int runtimeFlags, int mountExternal,
                                              int targetSdkVersion,
                                              String seInfo,
                                              String abi,
                                              String instructionSet,
                                              String appDataDir,
                                              String invokeWith,
                                              String[] zygoteArgs) {
    try {
        return startViaZygote(processClass, niceName, uid, gid, gids,
                runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                abi, instructionSet, appDataDir, invokeWith, false /* startChildZygote */,
                zygoteArgs);
    } catch (ZygoteStartFailedEx ex) {
        Log.e(LOG_TAG,
                "Starting VM process through Zygote failed");
        throw new RuntimeException(
                "Starting VM process through Zygote failed", ex);
    }
}


private Process.ProcessStartResult startViaZygote(final String processClass,
                                                  final String niceName,
                                                  final int uid, final int gid,
                                                  final int[] gids,
                                                  int runtimeFlags, int mountExternal,
                                                  int targetSdkVersion,
                                                  String seInfo,
                                                  String abi,
                                                  String instructionSet,
                                                  String appDataDir,
                                                  String invokeWith,
                                                  boolean startChildZygote,
                                                  String[] extraArgs)
                                                  throws ZygoteStartFailedEx {
    ArrayList<String> argsForZygote = new ArrayList<String>();

    // ...

    synchronized(mLock) {
    //关键代码
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
    }
}

zygoteSendArgsAndGetResult方法创建一个App进程。至此,app进程总算创建完成。接着会执行app进程的ActivityThread的main方法。这个main方法是app进程的入口。下面看看ActivityThread类的main方法。


http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ActivityThread.java

public static void main(String[] args) {
    // ...

    Process.setArgV0("<pre-initialized>");

    Looper.prepareMainLooper();

    // ...

    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

   // ...
    Looper.loop();

    throw new RuntimeException("Main thread loop unexpectedly exited");
}

这个方法内部, 主要是准备一个Looper对象,并准备一个消息列表,用于存在主线程的handler发送的消息。并创建一个ActivityThread对象。并调用attach方法,并且,如果sMainThreadHandler为null,给sMainThreadHandler赋值,
并且调用Looper.loop方法循环到从消息队列中抽取消息。下面来看看attach方法的具体实现:


private void attach(boolean system, long startSeq) {
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
        // ...
        final IActivityManager mgr = ActivityManager.getService();
        try {
            mgr.attachApplication(mAppThread, startSeq);
        } 
        // ...
    } else {
        // ...
    }

    // ...
}

这个方法中,获取了ActivityManagerServcie在app客户端的代理对象,调用代理对象的attachApplication方法,这时,app进程挂起,SystemServer进程的AMS类的attachApplication方法执行。


http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
    synchronized (this) {
        // ...
	    //关键代码
        attachApplicationLocked(thread, callingPid, callingUid, startSeq);
        Binder.restoreCallingIdentity(origId);
    }
}


@GuardedBy("this")
private final boolean attachApplicationLocked(IApplicationThread thread,
        int pid, int callingUid, long startSeq) {
	// ...

    try {
	 // ...
        if (app.isolatedEntryPoint != null) {

            thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
        } else if (app.instr != null) {
            thread.bindApplication(processName, appInfo, providers,
                    app.instr.mClass,
                    profilerInfo, app.instr.mArguments,
                    app.instr.mWatcher,
                    app.instr.mUiAutomationConnection, testMode,
                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(getGlobalConfiguration()), app.compat,
                    getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked(),
                    buildSerial, isAutofillCompatEnabled);
        } else {
            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);
        }
        // ...
    }
// ...
        // Find any services that should be running in this process...
        if (!badApp) {
            try {
	    //关键代码
                didSomething |= mServices.attachApplicationLocked(app, processName);
                checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
                badApp = true;
            }
        }
    // ...

    return true;
}

attachApplication方法内部,又继续调用了attachApplicationLocked方法,attachApplicationLocked方法内部,通过IApplicationThread的bindApplication方法,IApplicationThread内部的bindApplication方法内,通过sendMessage(H.BIND_APPLICATION, data),这样ActivityThread内的内部类H,它是继承了Handler的,这样H类的handleMessage方法中的代码执行,这样handleBindApplication()方法就执行了,handleBindApplication()方法主要
做了三件事:
1.创建Instrumentation对象;
2.调用LoadedApk类的makeApplication方法创建Application对象
3.调用Instrumentation对象的callApplicationOnCreate方法
经过上面三个步骤,Application就创建了,并且它的OnCreate方法也执行了。

继续看AMS类的attachApplicationLocked方法


http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

@GuardedBy("this")
private final boolean attachApplicationLocked(IApplicationThread thread,
        int pid, int callingUid, long startSeq) {
	// ...

    try {
	 // ...
        if (app.isolatedEntryPoint != null) {

            thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
        } else if (app.instr != null) {
            thread.bindApplication(processName, appInfo, providers,
                    app.instr.mClass,
                    profilerInfo, app.instr.mArguments,
                    app.instr.mWatcher,
                    app.instr.mUiAutomationConnection, testMode,
                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(getGlobalConfiguration()), app.compat,
                    getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked(),
                    buildSerial, isAutofillCompatEnabled);
        } else {
            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);
        }
        // ...
    }
// ...
        // Find any services that should be running in this process...
        if (!badApp) {
            try {
	    //关键代码
                didSomething |= mServices.attachApplicationLocked(app, processName);
                checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
                badApp = true;
            }
        }
    // ...

    return true;
}

这个方法内部,还会继续执行mServices.attachApplicationLocked(app, processName);
mServices是ActiveServices类型的,所以跳转到ActivieServices类中执行


http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

boolean attachApplicationLocked(ProcessRecord proc, String processName)
        throws RemoteException {
    boolean didSomething = false;
    // Collect any services that are waiting for this process to come up.
    if (mPendingServices.size() > 0) {
        ServiceRecord sr = null;
        try {
            for (int i=0; i<mPendingServices.size(); i++) {
                // ...
	        //关键代码
                realStartServiceLocked(sr, proc, sr.createdFromFg);
               // ...
            }
        } 
	// ...
    }

// ...
    return didSomething;
}


private final void realStartServiceLocked(ServiceRecord r,
        ProcessRecord app, boolean execInFg) throws RemoteException {
// ...

    boolean created = false;
    try {
        // ...
	//关键代码
        app.thread.scheduleCreateService(r, r.serviceInfo,
                mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                app.repProcState);
        r.postNotification();
        created = true;
    } 
    // ...
    // 关键代码
    sendServiceArgsLocked(r, execInFg, true);

    // ...
}

这个方法中的app.thread对象就是ApplicationThread类型的对象,所以跳转到 ApplicationThread类的scheduleCreateService方法


http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ActivityThread.java

public final void scheduleCreateService(IBinder token,
        ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
    updateProcessState(processState, false);
    // ...
    // 关键代码
    sendMessage(H.CREATE_SERVICE, s);
}


public void handleMessage(Message msg) {
	// ...
        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);
	// ...
}


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();

        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            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 {
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);

            Application app = packageInfo.makeApplication(false, mInstrumentation);
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            service.onCreate();
            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);
            }
        }
}

scheduleCreateService方法内部最终会调用到handleCreateService方法,
handleCreateService方法内部主要做了如下事情:
1.通过类加载方式创建Service的实例对象
2.调用LoadedApk的makeApplication方法创建Application对象,由于在前面的步骤中已经创建了
Application对象,所在这个方法中,就直接返回之前创建的Application对象。
3.调动Service的attach方法,attach方法内部,主要是调用attachBaseContext,将ContextImpl对象赋值给Service父类的mBase对象。`

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/Service.java

public final void attach(
        Context context,
        ActivityThread thread, String className, IBinder token,
        Application application, Object activityManager) {
    //关键代码
    attachBaseContext(context);
    // ...
}

4.调用Servcie的onCreate方法,这样Service的OnCreate方法就执行了
至此,Servcie创建了并且调用了OnCreate方法,下面继续看看ActiveServices类的realStartServiceLocked方法中的sendServiceArgsLocked方法


http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

private final void realStartServiceLocked(ServiceRecord r,
        ProcessRecord app, boolean execInFg) throws RemoteException {
// ...

    boolean created = false;
    try {
        // ...
	//关键代码
        app.thread.scheduleCreateService(r, r.serviceInfo,
                mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                app.repProcState);
        r.postNotification();
        created = true;
    } 
    // ...
    // 关键代码
    sendServiceArgsLocked(r, execInFg, true);

    // ...
}


private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
        boolean oomAdjusted) throws TransactionTooLargeException {
    // ...
    try {
        r.app.thread.scheduleServiceArgs(r, slice);
    } 
    // ...
}

sendServiceArgsLocked方法中的r.app.thread其实就是IApplicationThread类型的对象,所以最终会执行
ApplicationThread类中的scheduleServiceArgs方法,下面来看这个方法具体实现:


http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ActivityThread.java

public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
    List<ServiceStartArgs> list = args.getList();

    for (int i = 0; i < list.size(); i++) {
        //...
	// 关键代码
        sendMessage(H.SERVICE_ARGS, s);
    }
}

public void handleMessage(Message msg) {
    case SERVICE_ARGS:
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceStart: " + String.valueOf(msg.obj)));
        handleServiceArgs((ServiceArgsData)msg.obj);
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        break;
}

private void handleServiceArgs(ServiceArgsData data) {
   Service s = mServices.get(data.token);
   if (s != null) {
       try {
           // ...
           int res;
           if (!data.taskRemoved) {
	   // 关键代码
               res = s.onStartCommand(data.args, data.flags, data.startId);
           } else {
               s.onTaskRemoved(data.args);
               res = Service.START_TASK_REMOVED_COMPLETE;
           }
           // ...
       } 
       // ...
   }
}

handleServiceArgs方法中,执行了Servcie的onStartCommand方法,至此,Service的onStartCommand方法得到执行。

以上便是startServcie启动Servcie的过程分析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值