startService过程源码分析

startService过程源码分析

一、简介

Service是Android四大组件之一,service有两种使用方式分别是startService和bindService,startService方式启动service之后我们无法控制service,即使调用service的组件死亡也不会导致启动的service死亡。startService方式启动service后至service死亡锁经历的生命周期如下:oncreate—>onstartcommon—>ondestory。本篇文章会分析startService过程源码,下篇文章会分析bindService过程源码。

二、源码分析

我们一般是调用ContextWrapper的startService,然后它又调用mBase.startService,此处mBase是一个ContextImpl对象。在ContextImpl类的startService方法中又调用了startServiceCommon

 //android.content.ContextWrapper
 @Override
 public ComponentName startService(Intent service) {
        return mBase.startService(service);
 }

//ContextImpl.java
public ComponentName startService(Intent service) {
    warnIfCallingFromSystemProcess();
    return startServiceCommon(service, false, mUser);
}

startServiceCommon如下所示:

private ComponentName startServiceCommon(Intent service, boolean requireForeground,
        UserHandle user) {
    try {
        validateServiceIntent(service);
        service.prepareToLeaveProcess(this);
        //1调用了AMS的startService方法
        ComponentName cn = ActivityManager.getService().startService(
            mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                        getContentResolver()), requireForeground,
                        getOpPackageName(), user.getIdentifier());
        return cn;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}


在注释1处通过ActivityManager.getService()获取AMS的本地代理,然后通过该代理调用AMS的startService方法。
下面是获取ActivityManager.getService()获取AMS的本地代理的流程,可以看出是通过这是一个单例模式。获取AMS的方式是通过ServiceManager.getService来获取一个AMS的binder代理,然后转化为一个IActivityManager返回。因为AMS和调用client在不同进程所以返回的am是一个远端binder代理。

public static IActivityManager getService() {
    return IActivityManagerSingleton.get();
}

private static final Singleton IActivityManagerSingleton =
        new Singleton() {
            @Override
            protected IActivityManager create() {
                final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                final IActivityManager am = IActivityManager.Stub.asInterface(b);
                return am;
            }
        };


//IActivityManager.java
private static class Proxy implements android.app.IActivityManager
{
@Override public android.content.ComponentName startService(android.app.IApplicationThread caller, android.content.Intent service, java.lang.String resolvedType, boolean requireForeground, java.lang.String callingPackage, int userId) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
android.content.ComponentName _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder((((caller!=null))?(caller.asBinder()):(null)));s
if ((service!=null)) {
_data.writeInt(1);
service.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
_data.writeString(resolvedType);
_data.writeInt(((requireForeground)?(1):(0)));
_data.writeString(callingPackage);
_data.writeInt(userId);
mRemote.transact(Stub.TRANSACTION_startService, _data, _reply, 0);
_reply.readException();
if ((0!=_reply.readInt())) {
_result = android.content.ComponentName.CREATOR.createFromParcel(_reply);
}
else {
_result = null;
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}

AMS的startService方法如下所示:

//ActivityManagerService.java
public ComponentName startService(IApplicationThread caller, Intent service,
        String resolvedType, boolean requireForeground, String callingPackage, int userId)
        throws TransactionTooLargeException {
    //当调用者是孤立进程,则抛出异常。
    enforceNotIsolatedCaller("startService");
    // Refuse possible leaked file descriptors
    if (service != null && service.hasFileDescriptors() == true) {
        throw new IllegalArgumentException("File descriptors passed in Intent");
    }

    if (callingPackage == null) {
        throw new IllegalArgumentException("callingPackage cannot be null");
    }

    if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
            "*** startService: " + service + " type=" + resolvedType + " fg=" + requireForeground);
    synchronized(this) {
       //1获取调用者的pid和uid
        final int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        ComponentName res;
        try {
           //2、调用ActiveServices的startServiceLocked方法
            res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid,
                    requireForeground, callingPackage, userId);
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
        return res;
    }
}

AMS的startService方法在注释1处获取调用者的pid和uid,然后在注释2处调用ActiveServices的startServiceLocked方法并传入在注释1处获取调用者的pid和uid。

ActiveServices的startServiceLocked方法如下所示:

//ActiveServices.java
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
        int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
        throws TransactionTooLargeException {
        //1、获取调用进程ProcessRecord,如果为null则抛出异常
          if (caller != null) {
            final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
            if (callerApp == null) {
                throw new SecurityException(
                        "Unable to find app for caller " + caller
                        + " (pid=" + callingPid
                        + ") when starting service " + service);
            }
            callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
        }
//2、通过retrieveServiceLocked解析启动service的intent,并将解析结果放在res.record中
ServiceLookupResult res =
    retrieveServiceLocked(service, resolvedType, callingPackage,
            callingPid, callingUid, userId, true, callerFg, false);
   //解析的serviceRecord为null且permission不为null则判断返回缺少权限
  if (res.record == null) {
            return new ComponentName("!", res.permission != null
                    ? res.permission : "private to package");
        }

        ServiceRecord r = res.record;

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

}

在注释1处获取调用进程的ProcessRecord,如果为null则抛出异常,在注释2处调用retrieveServiceLocked解析启动service的intent,解析结果包含serviceRecord和启动该service所需权限,在注释3处调用startServiceInnerLocked。

startServiceInnerLocked如下所示:

ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
        boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
//1、调用bringUpServiceLocked,注意bringUpServiceLocked函数如果返回非null则表示启动出错。
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
if (error != null) {
    return new ComponentName("!!", error);
}
}

在bringUpServiceLocked中我们来分析service与调用者不在同一进程且service所在进程尚未启动的情况,这是最复杂的情况了。此时会调用startProcessLocked启动
service进程。

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
        boolean whileRestarting, boolean permissionsReviewRequired)
        throws TransactionTooLargeException {
        //1、如果service所在进程和主线程均为非空那么表示该service已经存在了,直接调用其onStartCommand方法
       if (r.app != null && r.app.thread != null) {
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }
       //...
        ProcessRecord app;
        if (!isolated) {
            //2、service所在进程已经启动则直接调用realStartServiceLocked启动service
            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.versionCode, mAm.mProcessStats);
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } catch (TransactionTooLargeException e) {
                    throw e;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
                }

                // If a dead object exception was thrown -- fall through to
                // restart the application.
            }
        }
       if (app == null && !permissionsReviewRequired) {
        //3、service与调用者不在同一进程且service所在进程尚未启动则调用startProcessLocked启动service进程
         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;
    }
    
    //4、service所在进程还未启动,将先将这个serviceRecord存储到mPendingServices中表示等待启动的service
        if (!mPendingServices.contains(r)) {
            mPendingServices.add(r);
        }
}
}

在注释1处会先判断service是否已经启动过,如果启动过则直接调用其onStartCommand方法,在注释2处判断service所在进程是否启动,如果进程启动但是service尚未启动那么会调用realStartServiceLocked启动service。在注释3处则是service所在进程未启动那么会先启动service进程,因为进程启动是异步的所以在注释4处会先把service存放到mPendingServices中表示等待启动的service。

下面我们先来看下service所在进程未启动的情况,该情况是调用startProcessLocked,如下所示:

final ProcessRecord startProcessLocked(String processName,
        ApplicationInfo info, boolean knownToBeDead, int intentFlags,
        String hostingType, ComponentName hostingName, boolean allowWhileBooting,
        boolean isolated, boolean keepIfLarge) {
        //调用startProcessLocked
    return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
            hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
            null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
            null /* crashHandler */);
}

final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
        boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
        boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
        String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
//调用startProcessLocked
startProcessLocked(
        app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);

}

经过调用最终是通过startProcessLocked来启动新的进程

private final void startProcessLocked(ProcessRecord app, String hostingType,
        String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
if (entryPoint == null) entryPoint = “android.app.ActivityThread”;
//1、Process.start创建新的进程
startResult = Process.start(entryPoint,
        app.processName, uid, uid, gids, debugFlags, mountExternal,
        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
        app.info.dataDir, invokeWith, entryPointArgs);

}

创建进程过程之前在Android应用进程启动分析一文中说过,详细过程请参考 Android应用进程启动过程.md

创建完新进程之后会调用android.app.ActivityThread的main函数,在Android程序中每个进程都有自己的android.app.ActivityThread。至此下面的这些操作都是在新启动的进程中,调用者所在进程已完成它的命令返回了。

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

Looper.prepareMainLooper();

ActivityThread thread = new ActivityThread();
//1、看下attach
thread.attach(false);
Looper.loop();
}


private void attach(boolean system) {
final IActivityManager mgr = ActivityManager.getService();
try {
    //1、调用了AMS的attachApplication
    mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
    throw ex.rethrowFromSystemServer();
}
}

在ActivityThread的main函数中会调用attach函数,而attach又调用了AMS的attachApplication。

AMS的attachApplication函数如下所示:

@Override
public final void attachApplication(IApplicationThread thread) {
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final long origId = Binder.clearCallingIdentity();
        //1、调用attachApplicationLocked
        attachApplicationLocked(thread, callingPid);
        Binder.restoreCallingIdentity(origId);
    }
}

在注释1处调用attachApplicationLocked,如下所示:

private final boolean attachApplicationLocked(IApplicationThread thread,
        int pid) {
// Find any services that should be running in this process…
if (!badApp) {
    try {
      //1、调用ActiveServices的attachApplicationLocked查看是否有需要启动的service
        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;
    }
}
}

attachApplicationLocked中我们只关注跟service启动有关的内容,就是代用attachApplicationLocked查看是否有需要启动的service

ActiveServices的attachApplicationLocked如下所示:

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 {
            //1、mPendingServices中存储了需要在该进程启动的service,这里依次取出并启动
            for (int i=0; i

在注释1处取出要启动的service并在注释2处调用realStartServiceLocked启动service

realStartServiceLocked如下所示:

private final void realStartServiceLocked(ServiceRecord r,ProcessRecord app, boolean execInFg) throws RemoteException {
 //1、发送delay消息
 bumpServiceExecutingLocked(r, execInFg, "create");
  ...
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);
     //2、调用ApplicationThread的scheduleCreateService方法
    app.thread.scheduleCreateService(r, r.serviceInfo,
            mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
            app.repProcState);
    r.postNotification();
    created = true;
    ...
    //3、service已经start,调用service的onStartCommand
    sendServiceArgsLocked(r, execInFg, true);

}
}

在注释1处会发送一个延迟处理的消息SERVICE_TIMEOUT_MSG。在方法scheduleCreateService执行完成,也就是onCreate回调执行完成之后,便会remove掉该消息。但是如果没能在延时时间之内remove该消息,则会进入执行service timeout流程。注释2处scheduleCreateService会创建service并回调其onCreate生命周期函数。在注释3处则回调用service的onStartCommand。

先来看下bumpServiceExecutingLocked,如下所示

    private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) {
        long now = SystemClock.uptimeMillis();
        if (r.executeNesting == 0) {
            r.executeFg = fg;
            ServiceState stracker = r.getTracker();
            if (stracker != null) {
                stracker.setExecuting(true, mAm.mProcessStats.getMemFactorLocked(), now);
            }
            if (r.app != null) {
                r.app.executingServices.add(r);
                r.app.execServicesFg |= fg;
                if (r.app.executingServices.size() == 1) {
                    //后台启动的服务
                    scheduleServiceTimeoutLocked(r.app);
                }
            }
        } else if (r.app != null && fg && !r.app.execServicesFg) {
            r.app.execServicesFg = true;
             //前台启动的服务
            scheduleServiceTimeoutLocked(r.app);
        }
    }

调用scheduleServiceTimeoutLocked,如下所示:

    void scheduleServiceTimeoutLocked(ProcessRecord proc) {
        if (proc.executingServices.size() == 0 || proc.thread == null) {
            return;
        }
        Message msg = mAm.mHandler.obtainMessage(
                ActivityManagerService.SERVICE_TIMEOUT_MSG);
        msg.obj = proc;
        //发送延迟消息SERVICE_TIMEOUT_MSG
        mAm.mHandler.sendMessageDelayed(msg,
                proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);
    }

scheduleServiceTimeoutLocked主要任务是发送延迟消息SERVICE_TIMEOUT_MSG,针对前后台service延迟时间会有所不同:

  • 对于前台服务,则超时为SERVICE_TIMEOUT,即timeout=20s;
  • 对于后台服务,则超时为SERVICE_BACKGROUND_TIMEOUT,即timeout=200s;

延迟消息发送后就会调用scheduleCreateService创建service,scheduleCreateService如下所示

//ApplicationThread.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;
    //给H发送了一个message
    sendMessage(H.CREATE_SERVICE, s);
}

//ActivityThread.java
H是ActivityThread的一个内部类,继承自Handler
public void handleMessage(Message msg) {
switch (msg.what) {
case CREATE_SERVICE:
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, (“serviceCreate: " + String.valueOf(msg.obj)));
    //1、H接收到CREATE_SERVICE的message之后调用handleCreateService
    handleCreateService((CreateServiceData)msg.obj);
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    break;
}
}

scheduleCreateService通过handler发送了一个CREATE_SERVICE的message,H类收到该消息后会调用handleCreateService进行处理,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.
     //当应用处于后台即将进行GC,而此时被调回到活动状态,则跳过本次gc
    unscheduleGcIdler();

    LoadedApk packageInfo = getPackageInfoNoCheck(
            data.info.applicationInfo, data.compatInfo);
    Service service = null;
    try {
        //1、调用ClassLoader创建service实例
        java.lang.ClassLoader cl = packageInfo.getClassLoader();
        service = (Service) cl.loadClass(data.info.name).newInstance();
    } 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对象
        ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
        context.setOuterContext(service);
        //如果Application不存在则创建Application对象
        Application app = packageInfo.makeApplication(false, mInstrumentation);
        //2、回调service.attach
        service.attach(context, this, data.info.name, data.token, app,
                ActivityManager.getService());
        //3、回调onCreate()
        service.onCreate();
        mServices.put(data.token, service);
        try {
        //4、
     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);
        }
    }
}

可以看出handleCreateService是真正创建service的地方。在注释1处通过反射生成service实例在注释2处调用attach,在注释3处回调onCreate。在注释4处调用AMS的serviceDoneExecuting方法取消之前发送service启动超时的延迟消息。

之后便是onStartCommand方法的回调,上面我们在AS的realStartServiceLocked函数中注释3处调用了sendServiceArgsLocked,sendServiceArgsLocked如下所示:

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

ApplicationThread的scheduleServiceArgs如下所示:

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

            for (int i = 0; i < list.size(); i++) {
                ServiceStartArgs ssa = list.get(i);
                ServiceArgsData s = new ServiceArgsData();
                s.token = token;
                s.taskRemoved = ssa.taskRemoved;
                s.startId = ssa.startId;
                s.flags = ssa.flags;
                s.args = ssa.args;
                //1、发送SERVICE_ARGS消息
                sendMessage(H.SERVICE_ARGS, s);
            }
        }

在注释1处发送SERVICE_ARGS消息,该消息是在handleServiceArgs函数中处理的,如下所示:

 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) {
                   //调用service的onStartCommand
                    res = s.onStartCommand(data.args, data.flags, data.startId);
                }
     }

至此service启动完毕。

启动流程:

  1. Process A进程采用Binder IPC向system_server进程发起startService请求;
  2. system_server进程接收到请求后,向zygote进程发送创建进程的请求;
  3. zygote进程fork出新的子进程Remote Service进程;
  4. Remote Service进程,通过Binder IPC向sytem_server进程发起attachApplication请求;
  5. system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向remote Service进程发送scheduleCreateService请求;
  6. Remote Service进程的binder线程在收到请求后,通过handler向主线程发送CREATE_SERVICE消息;
  7. 主线程在收到Message后,通过发射机制创建目标Service,并回调Service.onCreate()方法。

到此,服务便正式启动完成。当创建的是本地服务或者服务所属进程已创建时,则无需经过上述步骤2、3,直接创建服务即可。

参考:
startService源码分析

你可能感兴趣的:(startService过程源码分析)