startService的启动过程

2018-04-10  本文已影响57人  Jesse_zhao

Service的启动

一、概要

service的启动相对activity的启动来说比较简单。这里以startService来分析它的启动流程。

1、涉及主要类

android.app.ContextImpl.java 
android.app.ActivityThread.java
com.android.server.am.ActivityManagerService.java
com.android.server.am.ActiveServices.java

2、流程图


startService启动过程

二、具体流程

1、ContextImpl.startService()

最后会调用startServiceCommon()方法:

    private ComponentName startServiceCommon(Intent service, boolean requireForeground,
        UserHandle user) {
    try {
        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();
    }
}

这里就直接通过binder调用了AMS的startService()方法,这里有几个参数第一个是当前进程对应的ActivityThread实例、第二个参数是启动的Intent实例、第三个参数是resolveType数据类型,包名以及用户id。接着我们看下AMS中的startServive()方法:

2、ActivityManagerService.startService()
@Override
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);
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
        return res;
    }
}

这里没啥很简单,直接看下一步:

3.1、ActiveServices.startServiceLocked()
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
        int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
        throws TransactionTooLargeException {
   // 省略部分代码
    //查找相对应注册的service
    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");
    }

    ServiceRecord r = res.record;
    //省略部分代码...
    r.lastActivity = SystemClock.uptimeMillis();
    r.startRequested = true;
    r.delayedStop = false;
    r.fgRequired = fgRequired;
    r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
            service, neededGrants, callingUid));

    final ServiceMap smap = getServiceMapLocked(r.userId);
    boolean addToStarting = false;
   //省略部分代码...
    ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
    return cmp;
}

首先获取查找相对应注册的service信息,返回一个记录该service的信息对象ServiceRecord和相应的权限,然后接着调用了startServiceInnerLocked()方法,接着调用了bringUpServiceLocked()方法

3.2、ActiveServices.bringUpServiceLocked()
    private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
        boolean whileRestarting, boolean permissionsReviewRequired)
        throws TransactionTooLargeException {
    //当service已经启动时,再次调用时只会通过ActivityThread调用Service的onStartCommand方法传递参数
    if (r.app != null && r.app.thread != null) {
        sendServiceArgsLocked(r, execInFg, false);
        return null;
    }
    //省略部分代码
    final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
    final String procName = r.processName;
    String hostingType = "service";
    ProcessRecord app;
    // 如果当前service不是在单独的进程中
    if (!isolated) {
        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.
        }
    } 
    // 省略部分代码...
    return null;
}

这里面可以看到,如果是已经启动过的service,再次启动时之后调用service的onStartCommand()方法。当service是在单独的进程中时则通过AMS.startProcessLocked()来启动该进程。接着来看realStartServiceLocked方法:

3.3、ActiveServices.realStartServiceLocked()
 private final void realStartServiceLocked(ServiceRecord r,
        ProcessRecord app, boolean execInFg) throws RemoteException {
    if (app.thread == null) {
        throw new RemoteException();
    }
         r.app = app;
    r.restartTime = r.lastActivity = SystemClock.uptimeMillis();

    final boolean newService = app.services.add(r);
    bumpServiceExecutingLocked(r, execInFg, "create");
    mAm.updateLruProcessLocked(app, false, null);
    updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
    mAm.updateOomAdjLocked();

    boolean created = false;
    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);
        //通过ActivityThread完成Service的创建
        app.thread.scheduleCreateService(r, r.serviceInfo,
                mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                app.repProcState);
        r.postNotification();
        created = true;
    } catch (DeadObjectException e) {
        Slog.w(TAG, "Application dead when creating service " + r);
        mAm.appDiedLocked(app);
        throw e;
    } finally {
         //省略部分代码
               }
      //省略部分代码
    //通过ActivityThread执行onstartCommand()
    sendServiceArgsLocked(r, execInFg, true);
    //省略部分代码
}

执行到这framework层才完成对Service创建的准备工作,之后通过ActivityThread来完成对Service的创建:

4、ActivityTHread.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();

    LoadedApk loadedApk = getLoadedApkNoCheck(
            data.info.applicationInfo, data.compatInfo);
    Service service = null;
    try {
    //通过反射创建Service实例
        java.lang.ClassLoader cl = loadedApk.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 context = ContextImpl.createAppContext(this, loadedApk);
        context.setOuterContext(service);

        Application app = loadedApk.makeApplication(false, mInstrumentation);
        service.attach(context, this, data.info.name, data.token, app,
                ActivityManager.getService()); 
           //调用Service的oncreate()方法
        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);
        }
    }
}

至此就完成了对Service的创建和启动。

三、总结

startService的启动和Activity的启动相类似,但是Android 8.0对后台service的启动做了些改变。

上一篇下一篇

猜你喜欢

热点阅读