- CompoundButton 源码分析
- LinearLayout 源码分析
- SearchView 源码解析
- LruCache 源码解析
- ViewDragHelper 源码解析
- BottomSheets 源码解析
- Media Player 源码分析
- NavigationView 源码解析
- Service 源码解析
- Binder 源码分析
- Android 应用 Preference 相关及源码浅析 SharePreferences 篇
- ScrollView 源码解析
- Handler 源码解析
- NestedScrollView 源码解析
- SQLiteOpenHelper/SQLiteDatabase/Cursor 源码解析
- Bundle 源码解析
- LocalBroadcastManager 源码解析
- Toast 源码解析
- TextInputLayout
- LayoutInflater 和 LayoutInflaterCompat 源码解析
- TextView 源码解析
- NestedScrolling 事件机制源码解析
- ViewGroup 源码解析
- StaticLayout 源码分析
- AtomicFile 源码解析
- AtomicFile 源码解析
- Spannable 源码分析
- Notification 之 Android 5.0 实现原理
- CoordinatorLayout 源码分析
- Scroller 源码解析
- SwipeRefreshLayout 源码分析
- FloatingActionButton 源码解析
- AsyncTask 源码分析
- TabLayout 源码解析
Service 启动流程分析
Service 在 客户端
的启动入口位于 ContextImpl.startService(Intent intent)
,因此我们从它入手。
[--> android/app/ContextImpl.java]
public ComponentName startService(Intent service) { //如果当前进程是 system-server 进程, //调用 startService 会通过 Log 打印警告信息。 warnIfCallingFromSystemProcess(); return startServiceCommon(service, mUser); }
startService
通过调用 startServiceCommon
来完成余下的工作,其代码如下:
private ComponentName startServiceCommon(Intent service, UserHandle user) { try { //验证启动目标 Service 的 Intent 的合法性 validateServiceIntent(service); //让 Intent 为跨进程调用做准备 service.prepareToLeaveProcess(); //调用 ActivityManagerNative 的 startService, //这实际上是一个远程调用。 ComponentName cn = ActivityManagerNative.getDefault().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier()); //根据调用结果做对应的处理 if (cn != null) { if (cn.getPackageName().equals("!")) { //不具备调用目标 Service 的权限 throw new SecurityException( "Not allowed to start service " + service + " without permission " + cn.getClassName()); } else if (cn.getPackageName().equals("!!")) { // 无法启动目标 Service 的处理 throw new SecurityException( "Unable to start service " + service + ": " + cn.getClassName()); } } return cn; } catch (RemoteException e) { return null; } }
startServiceCommon
首先验证启动目标 Service 的 Intent 的合法性,然后调用 ActivityManagerNative.startService(...)
来启动 Service,最后做了收尾工作。我们接着来到 ActivityManagerNative
一探究竟:
[-->android/app/ActivityManagerNative.java]
public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(caller != null ? caller.asBinder() : null); service.writeToParcel(data, 0); data.writeString(resolvedType); data.writeInt(userId); mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0); reply.readException(); ComponentName res = ComponentName.readFromParcel(reply); data.recycle(); reply.recycle(); return res; }
相信读者看一看代码就清楚,这是一个 RPC(Remote Procedure Call)
调用,只不过它不是 AIDL 生成的,而是手工实现的。不过还有个疑问,这里的 mRemote 是从哪里来的呢?我们定位到取得这个 IBinder 的位置:
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() { protected IActivityManager create() { IBinder b = ServiceManager.getService("activity"); IActivityManager am = asInterface(b); return am; } };
显然,这个 mRemote
是通过 ServiceManager
来维护的,它对应的是 ActivityManagerService 。 ActivityManagerService
运行在 system-server
进程,它实际上是一个 进程级别
的单例。我们接着分析 startService
在服务端的实现:
[-->com/android/server/am/ActivityManagerService.java]
public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, int userId) { enforceNotIsolatedCaller("startService"); // 拒绝包含可能造成内存泄露的文件描述符的 Intent if (service != null && service.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } synchronized(this) { final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); ComponentName res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid, userId); Binder.restoreCallingIdentity(origId); return res; } }
ActivityManagerService
的 startService
被客户端调用后,首先对 Intent 进行检查,然后跳转到调用 mServices.startServiceLocked(...)
进行余下工作。这里的 mService 的类型是 ActiveServices
,它的作用是什么呢?我们来看看这个类包含了哪些函数:
ActiveServices
的作用显而易见了,它负责处理 Service 的组件调用
和 维护 Service 的状态信息
。那么 startServiceLocked
做了哪些事情呢?我们来看代码:
[-->com/android/server/am/ActiveServices.java]
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, int userId) { final boolean callerFg; //检查调用方身份 if (caller != null) { final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller); //在 ActivityManagerService 中查询不到调用者,直接抛出异常。 if (callerApp == null) { throw new SecurityException( "Unable to find app for caller " + caller + " (pid=" + Binder.getCallingPid() + ") when starting service " + service); } //判断调用方是前台进程还是后台进程 callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE; } else { callerFg = true; } //检索匹配 Service 组件信息 ServiceLookupResult res = retrieveServiceLocked(service, resolvedType, callingPid, callingUid, userId, true, callerFg); //没有匹配到 Service 组件 if (res == null) { return null; } if (res.record == null) { //目标 Service 组的 android:export 属性为 false return new ComponentName("!", res.permission != null ? res.permission : "private to package"); } ServiceRecord r = res.record; if (!mAm.getUserManagerLocked().exists(r.userId)) { //目标 Service 组件不存在于任何 User Slog.d(TAG, "Trying to start service with non-existent user! " + r.userId); return null; } //Uri 权限检查 NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked( callingUid, r.packageName, service, service.getFlags(), null, r.userId); //如果目标的 Service 正在被请求重启,但还未重启,取消这个请求 if (unscheduleServiceRestartLocked(r, callingUid, false)) { if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r); } r.lastActivity = SystemClock.uptimeMillis(); r.startRequested = true; r.delayedStop = false; r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), service, neededGrants)); final ServiceMap smap = getServiceMap(r.userId); boolean addToStarting = false; if (!callerFg && r.app == null && mAm.mStartedUsers.get(r.userId) != null) { ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false); if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) { if (r.delayed) { // 目标 Service 正在启动中,但还没有启动完成。 return r.name; } if (smap.mStartingBackground.size() >= mMaxStartingBackground) { // 该进程有其它组件正在启动,等待它完成后再启动。 Slog.i(TAG, "Delaying start of: " + r); smap.mDelayedStartList.add(r); r.delayed = true; return r.name; } addToStarting = true; } else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) { addToStarting = true; } } return startServiceInnerLocked(smap, service, r, callerFg, addToStarting); }
这里解释一下 startServiceLocked
的工作流程。
- 检查了调用者的身份,以防止
匿名组件攻击
。 - 根据客户端传入的数据
检索
匹配的 Service 组件信息。 - 如果检索成功,进一步检查客户端是否有权限调起目标 Service。对于在
AndroidManifest.xml
将android:export 标签
设为 false 的Service
,只有调用者与目标 Service 包名相同并且 uid 相同时才允许调起。 - 如果目标的 Service 正在被请求重启,但还未重启,取消这个请求。
- 如果目标进程已经创建, 但进程有其它组件正在启动,等待它完成后再启动。
在完成以上流程后,它调用了 startServiceInnerLocked
来完成余下的工作:
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r, boolean callerFg, boolean addToStarting) { ProcessStats.ServiceState stracker = r.getTracker(); if (stracker != null) { //跟踪 Service 的内存消耗 stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity); } r.callStart = false; synchronized (r.stats.getBatteryStats()) { //跟踪 Service 的耗电量 r.stats.startRunningLocked(); } //通知客户端进程启动 Service String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false); if (error != null) { //启动失败 return new ComponentName("!!", error); } if (r.startRequested && addToStarting) { boolean first = smap.mStartingBackground.size() == 0; smap.mStartingBackground.add(r); //设定客户端 Service 启动超时的时间 r.startingBgTimeout = SystemClock.uptimeMillis() + BG_START_TIMEOUT; if (first) { smap.rescheduleDelayedStarts(); } } else if (callerFg) { smap.ensureNotStartingBackground(r); } return r.name; }
这个函数中,启动了对 Service 内存消耗和电量消耗的跟踪,然而到了最关键的一步: 调起目标客户端进程来启动 Service 。它的逻辑实现在 bringUpServiceLocked(...)
中,我们来到这个函数:
private final String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting) { if (r.app != null && r.app.thread != null) { //目标 Service 已经启动 sendServiceArgsLocked(r, execInFg, false); return null; } if (!whileRestarting && r.restartDelay > 0) { // 如果目标 Service 正在等待 restart 完成,什么都不用做,直接返回。 return null; } //从正在重启的 Service 列表中移除目标 Service if (mRestartingServices.remove(r)) { clearRestartingIfNeededLocked(r); } //目标 Service 不再是 delayed 状态 if (r.delayed) { getServiceMap(r.userId).mDelayedStartList.remove(r); r.delayed = false; } // 确保目标 Service 所属的 User 处于 started 状态。 if (mAm.mStartedUsers.get(r.userId) == null) { String msg = "Unable to launch app " + r.appInfo.packageName + "/" + r.appInfo.uid + " for service " + r.intent.getIntent() + ": user " + r.userId + " is stopped"; Slog.w(TAG, msg); bringDownServiceLocked(r); return msg; } //Service 即将被启动,它所属的 Package 不能被停止。 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); } //检查要启动的 Service 是否被隔离 final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0; final String procName = r.processName; ProcessRecord app; if (!isolated) { app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false); //目标进程已经创建 if (app != null && app.thread != null) { try { //该进程又多了一个正在运行的 Package app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats); //在客户端创建并启动目标 Service realStartServiceLocked(r, app, execInFg); return null; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting service " + r.shortName, e); } } } else { app = r.isolatedProc; } //目标进程还未创建 if (app == null) { //通过 ActivityManagerService 来创建目标进程,调用将阻塞到目标进程创建完成为止 if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags, "service", 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; } } //将目标 Service 添加到 正在启动 Service 但未启动完成 的 Service 列表中 if (!mPendingServices.contains(r)) { mPendingServices.add(r); } if (r.delayedStop) { r.delayedStop = false; if (r.startRequested) { stopServiceLocked(r); } } return null; }
这个函数又依次做了以下事情:
- 如果目标 Service 已经启动,直接
sendServiceArgsLocked(...)
并返回。 - 如果目标 Service 正在被重启,但未重启完成,直接返回。
- 从
正在重启的 Service 列表
中移除目标 Service。 - 清除目标 Service 的
delayed 状态
。 - 如果目标 Service 所属的 User 未处于
started 状态
,则不允许启动目标 Service。 - 判断目标 Service 所处的进程是否
已经创建
。 - 如果进程已经创建,通过
realStartServiceLocked(...)
通知客户端创建并启动目标 Service。 - 如果进程还未创建,通过
ActivityManagerService
的startProcessLocked(...)
来创建目标进程。 - 将目标 Service 添加到 正在启动 Service 但未启动完成 的 Service 列表中。
故真正创建和启动 Service 的逻辑在 realStartServiceLocked
,我们来到这个函数:
private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { if (app.thread == null) { throw new RemoteException(); } //填充 ServiceRecord r.app = app; r.restartTime = r.lastActivity = SystemClock.uptimeMillis(); app.services.add(r); bumpServiceExecutingLocked(r, execInFg, "create"); mAm.updateLruProcessLocked(app, false, null); mAm.updateOomAdjLocked(); boolean created = false; try { synchronized (r.stats.getBatteryStats()) { r.stats.startLaunchedLocked(); } //确保目标 App 的 Dex 已经优化完成 mAm.ensurePackageDexOpt(r.serviceInfo.packageName); app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE); //通知客户端的 ApplicationThread 创建和启动目标 Service app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState); r.postNotification(); created = true; } catch (DeadObjectException e) { //在启动 Service 的过程中,目标进程突然挂了 Slog.w(TAG, "Application dead when creating service " + r); mAm.appDiedLocked(app); } finally { if (!created) { app.services.remove(r); r.app = null; scheduleServiceRestartLocked(r, false); return; } } //如果 Service 需要绑定,则绑定目标 Service requestServiceBindingsLocked(r, execInFg); updateServiceClientActivitiesLocked(app, null, true); if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) { r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), null, null)); } //通知客户端 ApplicationThread 调用目标 Service 的 onStartCommand 方法 sendServiceArgsLocked(r, execInFg, true); if (r.delayed) { getServiceMap(r.userId).mDelayedStartList.remove(r); r.delayed = false; } if (r.delayedStop) { r.delayedStop = false; if (r.startRequested) { stopServiceLocked(r); } } }
代码比较简单,服务端首先填充 ServiceRecord 中关于目标 Service 的数据,一切无误后远程调用客户端的 scheduleCreateService
函数来创建目标 Service。 scheduleCreateService
函数位于 android.app.IApplicationThread
接口。那么,它又是何物呢?我们来看看这个接口:
[-->androiod/app/IApplicationThread.java]
/** * System private API for communicating with the application. This is given to * the activity manager by an application when it starts up, for the activity * manager to tell the application about things it needs to do. */ public interface IApplicationThread extends IInterface { //... }
看注释就很清楚了,它是服务端与客户端通信的桥梁,每一个客户端进程都对应一个 IApplicationThread
,它的实例会在进程创建后传递到服务端,方便服务端与客户端通信。 IApplicationThread
接口的部分实现在 android.app.ApplicationThreadNative
,它仍然是一个 抽象类
,但是实现了大部分接口中的方法:
[-->androiod/app/ApplicationThreadNative.java]
public abstract class ApplicationThreadNative extends Binder implements IApplicationThread { static public IApplicationThread asInterface(IBinder obj) { if (obj == null) { return null; } IApplicationThread in = (IApplicationThread) obj.queryLocalInterface(descriptor); if (in != null) { return in; } return new ApplicationThreadProxy(obj); } //... }
真正完整的是 ApplicationThread
。它继承了 ApplicationThreadNative
,并实现了所有的抽象方法。它是 android.app.ActivityThread
的内部类:
[-->androiod/app/ActivityThread.java]
public final class ActivityThread { private class ApplicationThread extends ApplicationThreadNative { public final void scheduleCreateService(IBinder token, ServiceInfo info, CompatibilityInfo compatInfo, int processState) { //... } //... } //... }
它的家族体系如图所示:
由前面的分析可知,远程服务端最终会调用 ApplicationThread。scheduleCreateService
,那么我们来看看 scheduleCreateService
是怎样实现的:
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; 发送请求到 Handler sendMessage(H.CREATE_SERVICE, s); }
scheduleCreateService
中将传递进来的参数包装成了一个 CreateServiceData
,然后通过 sendMessage
传递到 Handler。 这里的 sendMessage
的实现如下:
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) { Message msg = Message.obtain(); msg.what = what; msg.obj = obj; msg.arg1 = arg1; msg.arg2 = arg2; if (async) { msg.setAsynchronous(true); } mH.sendMessage(msg); }
因此,消息发送到的是 ActivityThread
中的 mH
。 mH
的类型为 H ,继承自 Handler:
private class H extends Handler { public static final int CREATE_SERVICE = 114; //... public void handleMessage(Message msg) { switch(msg.what) { case CREATE_SERVICE: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate"); handleCreateService((CreateServiceData)msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; //... } } }
mH
收到 what
为 CREATE_SERVICE
的 Message 后,通过 handleCreateService
做后续处理:
private void handleCreateService(CreateServiceData data) { //停止空闲时自动触发 GC 的机制 unscheduleGcIdler(); //取得 App 对应的 LoadedApk LoadedApk packageInfo = getPackageInfoNoCheck( data.info.applicationInfo, data.compatInfo); //创建 Service Service service = null; try { //通过反射来创建 Service 实例 java.lang.ClassLoader cl = packageInfo.getClassLoader(); service = (Service) cl.loadClass(data.info.name).newInstance(); } catch (Exception e) { //... } try { //创建 Service 的 base context ContextImpl context = ContextImpl.createAppContext(this, packageInfo); context.setOuterContext(service); //取得 Application Application app = packageInfo.makeApplication(false, mInstrumentation); //填充信息到 Service service.attach(context, this, data.info.name, data.token, app, ActivityManagerNative.getDefault()); service.onCreate(); //将创建完成的 Service 放入 mServices 这个 Map 中 mServices.put(data.token, service); try { //通知服务端,Service 启动完成。 ActivityManagerNative.getDefault().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } catch (RemoteException e) { // nothing to do. } } catch (Exception e) { //... } }
代码十分清晰,这个函数做了以下事情:
- 根据
ServiceInfo
中的ApplicationInfo
取得 App 对应的 LoadedApk。 - 通过
LoadedApk
拿到ClassLoader
来反射创建目标 Service 实例。 - 通过
ContextImpl.createAppContext(...)
来创建 base context。前面分析过,Service 继承自 ContextWrapper ,它的attachBaseContext
方法传入的就是这里的context
。 - 填充信息到 Service,这样 Service 才能知道自己的身份。
- 调用
Service.onCreate
方法。 - 将创建完成的 Service 放入
mServices
这个 Map 中。 - 通知服务端,Service 启动完成。如果前面的过程耗时太长,服务端会认为客户端的 Service 启动失败。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论