本文主要是介绍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;}
}
接下来会调用startServiceLocked
。startServiceLocked
的逻辑稍微显得复杂一些,主要的难点是获取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和ClipDataint 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从等待启动列表中删除,最终会调用会进入bringupServiceLocked
,bringupServiceLocked
函数中包含了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信息去启动一个新的进程,新进程启动完成后则去启动Serviceif ((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篇文章分别取分析这三种不同的启动方式。
这篇关于Service启动流程(startService)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!