Service启动流程(startService)

前面分析了Activity的启动流程,下面开始分析Service的启动,本文分析的是startService的流程,android的版本为4.1.2

@Override
public ComponentName startService(Intent service) {
    warnIfCallingFromSystemProcess();
    return startServiceCommon(service, mUser);
}  

这就是startService的入口,mUser就是代表当前的用户,在后面启动Serivce的流程中,会通过此实例获取用户的uid。

private ComponentName startServiceCommon(Intent service, UserHandle user) {
    try {
        ......
        ComponentName cn = ActivityManagerNative.getDefault().startService(
            mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                        getContentResolver()), getOpPackageName(), user.getIdentifier());
        if (cn != null) {
            if (cn.getPackageName().equals("!")) {
                throw new SecurityException(
                        "Not allowed to start service " + service
                        + " without permission " + cn.getClassName());
            } else if (cn.getPackageName().equals("!!")) {
                throw new SecurityException(
                        "Unable to start service " + service
                        + ": " + cn.getClassName());
            }
        }
        return cn;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }

接下来通过binder通信,Service启动流程会进入ActivityManagerService的startService函数中。

public ComponentName startService(IApplicationThread caller, Intent service,
        String resolvedType) {
    ......

    synchronized(this) {
        final int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        ComponentName res = startServiceLocked(caller, service,
                resolvedType, callingPid, callingUid);
        Binder.restoreCallingIdentity(origId);
        return res;
    }
}

接下来会调用startServiceLockedstartServiceLocked的逻辑稍微显得复杂一些,主要的难点是获取Service信息。

ComponentName startServiceLocked(IApplicationThread caller,
        Intent service, String resolvedType,
        int callingPid, int callingUid) {
    synchronized(this) {
        ......

        ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType,
                    callingPid, callingUid);
        if (res == null) {
            return null;
        }
        if (res.record == null) {
            return new ComponentName("!", res.permission != null
                    ? res.permission : "private to package");
        }
        ServiceRecord r = res.record;
        //检测当前用户是否有权限访问Intent中的Data和ClipData
        int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
                callingUid, r.packageName, service);
        //将即将启动的Service从等待启动列表中删除
        if (unscheduleServiceRestartLocked(r)) {
            if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
        }
        ......
        if (!bringUpServiceLocked(r, service.getFlags(), false)) {
            return new ComponentName("!", "Service process is bad");
        }
        return r.name;
    }
}  

系统首先调用retriveServiceLocked 函数获取即将要启动的Service信息,并封装成ServiceLookupResult对象,ServiceLoopupResult对象内部包括了一个ServiceRecord对象和记录Service权限的字符串,retrivveServiceLocked函数的执行过程会在后面分析。获得ServiceLookupResult结果res后会进行判断,如果未找到即将启动的Service的ServiceLookupResult对象,则直接返回;接下来会将即将启动的Service从等待启动列表中删除,最终会调用会进入bringupServiceLockedbringupServiceLocked函数中包含了ActivityManagerService对Service进行不同配置以及系统处于不同状态的不同启动方式。

private final boolean bringUpServiceLocked(ServiceRecord r,
        int intentFlags, boolean whileRestarting) {
    //Slog.i(TAG, "Bring up service:");
    //r.dump("  ");
    //Service已经运行,则执行Service的onStartCommand函数
    if (r.app != null && r.app.thread != null) {
        sendServiceArgsLocked(r, false);
        return true;
    }
    //如果正在等待重启,则直接返回
    if (!whileRestarting && r.restartDelay > 0) {
        // If waiting for a restart, then do nothing.
        return true;
    }
    //从正在重启的服务列表中删除即将启动的服务
    mRestartingServices.remove(r);

    //服务正在启动,当前应用不能被停止
    try {
        AppGlobals.getPackageManager().setPackageStoppedState(
                r.packageName, false, r.userId);
    } catch (RemoteException e) {
    } catch (IllegalArgumentException e) {
        Slog.w(TAG, "Failed trying to unstop package "
                + r.packageName + ": " + e);
    }

    final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
    final String appName = r.processName;
    ProcessRecord app;
    //如果Service不需要运行在单独的进程
    if (!isolated) {
        //尝试获取Service的进程
        app = getProcessRecordLocked(appName, r.appInfo.uid);
        if (DEBUG_MU)
            Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app);
         //如果Service所在进程已经启动,但是Service还未启动,则去执行realStartServiceLocked,在进程内执行Service的启动流程
        if (app != null && app.thread != null) {
            try {
                app.addPackage(r.appInfo.packageName);
                realStartServiceLocked(r, app);
                return true;
            } 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.
        }
    } else {
        // If this service runs in an isolated process, then each time
        // we call startProcessLocked() we will get a new isolated
        // process, starting another process if we are currently waiting
        // for a previous process to come up.  To deal with this, we store
        // in the service any current isolated process it is running in or
        // waiting to have come up.
        app = r.isolatedProc;
    }

    // Not running -- get it started, and enqueue this service record
    // to be executed when the app comes up.
    //Service所在的进程未启动,则启动进程
    if (app == null) {
        //如果Service所在进程并没有被启动,则根据Service信息去启动一个新的进程,新进程启动完成后则去启动Service
        if ((app=startProcessLocked(appName, r.appInfo, true, intentFlags,
                "service", r.name, false, isolated)) == null) {
            Slog.w(TAG, "Unable to launch app "
                    + r.appInfo.packageName + "/"
                    + r.appInfo.uid + " for service "
                    + r.intent.getIntent() + ": process is bad");
            bringDownServiceLocked(r, true);
            return false;
        }
        if (isolated) {
            r.isolatedProc = app;
        }
    }
    //将即将启动的Service添加到pending队列中
    if (!mPendingServices.contains(r)) {
        mPendingServices.add(r);
    }

    return true;
}

这部分的代码描述了调用startService时可能遇到的三种情况:

  • 目标Service已经启动,则去执行onStartCommand
  • 目标Service未启动,但是Service所在的进程已经启动
  • 目标Service未启动且Service所在进程未启动,需要新建进程

本篇的分析到此结束,接下来我会分3篇文章分别取分析这三种不同的启动方式。

猜你喜欢

转载自blog.csdn.net/rockstore/article/details/79920222