【 Android(安卓)10 四大组件 】系列 -- Service 的 “ 启动流程 “
# 前言
由于源码分析的代码量比较大,大部分博客网站的内容显示页面都比较窄,显示出来的效果都异常丑陋,所以您也可以直接查看 《 Thinking in Android 》 来阅读这边文章,希望这篇文章能帮你梳理清楚 “Service 的启动流程”。
# 核心源码
关键类 | 路径 |
---|---|
ContextImpl.java | frameworks/base/core/java/android/app/ContextImpl.java |
ContextWrapper.java | frameworks/base/core/java/android/content/ContextWrapper.java |
ContextThemeWrapper.java | frameworks/base/core/java/android/view/ContextThemeWrapper.java |
Activity.java | frameworks/base/core/java/android/app/Activity.java |
ActivityManager.java | frameworks/base/core/java/android/app/ActivityManager.java |
ActivityManagerService.java | frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java |
ActiveServices.java | frameworks/base/services/core/java/com/android/server/am/ActiveServices.java |
ActivityThread.java | frameworks/base/core/java/android/app/ActivityThread.java |
Service
的启动过程相对 Activity
的启动过程来说简单了很多,我们都知道怎么去创建和启动一个 Service,那么你有没有从源码角度研究过 Service 启动后在系统层是如何运作的?
# Activity.startService()
首先我们知道:要启动一个 Service 的时候,一般都是在 Activity 中通过 startService()
来启动:
Intent intent = new Intent(MainActivity.this, xxxService.class);startService(intent);
但是我们在 Activity
源码中并没有实现 startService()
方法,那它在哪里被调用的?找不到我们就去 Activity
的父类中找。
// frameworks/base/core/java/android/app/Activity.javapublic class Activity extends ContextThemeWrapper implements LayoutInflater.Factory2, Window.Callback, KeyEvent.Callback, OnCreateContextMenuListener, ComponentCallbacks2, Window.OnWindowDismissedCallback, WindowControllerCallback, AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient {}// frameworks/base/core/java/android/view/ContextThemeWrapper.javapublic class ContextThemeWrapper extends ContextWrapper {}// frameworks/base/core/java/android/content/ContextWrapper.javapublic class ContextWrapper extends Context {}
Activity
继承了 ContextThemeWrapper
类,ContextThemeWrapper
又继承了 ContextWrapper
类,ContextWrapper
又继承了 Context
类。
# ContextWrapper.startService()
在 ContextWrapper
中实现了 startService()
方法:
// frameworks/base/core/java/android/content/ContextWrapper.javapublic class ContextWrapper extends Context { Context mBase; public ContextWrapper(Context base) { mBase = base; } @Override public ComponentName startService(Intent service) { return mBase.startService(service); }}
所以 startService()
方法其实是由 ContextWrapper
实现的,紧接着又调用了 mBase.startService()
方法,mBase
对象是 Context
的子类 ContextImpl
,所以调用最终进入 ContextImpl
类的 startService()
方法。
# ContextImpl.startService()
// frameworks/base/core/java/android/app/ContextImpl.javaclass ContextImpl extends Context { @Override public ComponentName startService(Intent service) { warnIfCallingFromSystemProcess(); return startServiceCommon(service, false, mUser); } private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) { try { validateServiceIntent(service); service.prepareToLeaveProcess(this); // 通过 Binder 进程间通信进入 ActivityManagerService 的 startService() 方法 ComponentName cn = ActivityManager.getService().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded( getContentResolver()), requireForeground, getOpPackageName(), user.getIdentifier()); ... ... return cn; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }}
# ActivityManager.getService()
// frameworks/base/core/java/android/app/ActivityManager.javapublic class ActivityManager { @UnsupportedAppUsage public static IActivityManager getService() { return IActivityManagerSingleton.get(); } @UnsupportedAppUsage private static final Singleton<IActivityManager> IActivityManagerSingleton = new Singleton<IActivityManager>() { @Override protected IActivityManager create() { final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE); final IActivityManager am = IActivityManager.Stub.asInterface(b); return am; } };}
# ActivityManagerService.startService()
接下来就执行到 ActivityManagerService
的 startService()
方法:
// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.javapublic class ActivityManagerService extends IActivityManager.Stub implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback { final ActiveServices mServices; public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, boolean requireForeground, String callingPackage, int userId) throws TransactionTooLargeException { ... ... synchronized(this) { final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); ComponentName res; try { // 调用 ActiveServices 的 startServiceLocked() 方法 res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid, requireForeground, callingPackage, userId); } finally { Binder.restoreCallingIdentity(origId); } return res; } }}
# ActiveServices.startServiceLocked()
// frameworks/base/services/core/java/com/android/server/am/ActiveServices.javapublic final class ActiveServices { ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId) throws TransactionTooLargeException { return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired, callingPackage, userId, false); } ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId, boolean allowBackgroundActivityStarts) throws TransactionTooLargeException { ... ...// 解析 AndroidManifest.xml 文件中配置 Service 的 intent-filter 相关内容信息 ServiceLookupResult res = retrieveServiceLocked(service, null, resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg, false, false); if (res == null) { return null; } ... ... ServiceRecord r = res.record; ... ... // 调用 startServiceInnerLocked() 方法 ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting); return cmp; }}
通过 retrieveServiceLocked()
方法来解析 AndroidManifest.xml
文件中配置 Service 的 intent-filter
相关内容信息。
当解析完 Service
的 intent-filter
相关内容信息后,解析的结果会保存在 res.record
变量中。而 res 变量是一个 ServiceLookupResult
类型的对象,它的 record 变量则是一个 ServiceRecord
类型对象,用来表示一个 Service
。
# ActiveServices.startServiceInnerLocked()
ActiveServices 的 startServiceLocked() 方法最后调用了 startServiceInnerLocked()
方法:
// frameworks/base/services/core/java/com/android/server/am/ActiveServices.javapublic final class ActiveServices { ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r, boolean callerFg, boolean addToStarting) throws TransactionTooLargeException { ... ... // 调用 bringUpServiceLocked() 方法 String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false); ... ... }}
# ActiveServices.bringUpServiceLocked()
调用 bringUpServiceLocked()
方法进一步处理:
// frameworks/base/services/core/java/com/android/server/am/ActiveServices.javapublic final class ActiveServices { private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired) throws TransactionTooLargeException { ... ... ProcessRecord app; if (!isolated) { app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false); // 获取 app 对象 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.longVersionCode, mAm.mProcessStats); // 运行 service 的进程已经启动,调用 realStartServiceLocked() 方法 realStartServiceLocked(r, app, execInFg); return null; } catch (TransactionTooLargeException e) { throw e; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e); } // If a dead object exception was thrown -- fall through to // restart the application. } } else { ... ... } // Not running -- get it started, and enqueue this service record // to be executed when the app comes up. if (app == null && !permissionsReviewRequired) { if ((app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags, hostingRecord, 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; } } ... ... return null; }}
bringUpServiceLocked()
方法首先通过 getProcessRecordLocked()
方法去获取 app 对象,它是一个 ProcessRecord
类型的对象,如果它不为空,说明 Service
要运行的进程已经存在。
Service 运行的进程有两种:
(1)一种是默认的,即运行在 Activity 启动 Service 的那个进程里,也就是说在哪个进程里调用了 startService() 方法,启动的 service 就运行在哪个进程里。
(2)一种是给 Service 一个单独的进程运行,比如在 AndroidManifest 文件里配置了如下内容:
//<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.documentsui"> <application android:name=".DocumentsApplication" android:label="@string/app_label" android:icon="@drawable/app_icon" android:supportsRtl="true" android:allowBackup="true" android:backupAgent=".prefs.BackupAgent" android:fullBackupOnly="false"> <service android:name=".services.FileOperationService" android:exported="false" android:process=":com.android.documentsui.services"> service> application>manifest>
在这段配置里有 android:process="xxx"
声明,这个声明用来实现 service 单独运行在 “xxx” 进程里。这样做的好处是,即使应用程序无法工作,由于 service 单独运行在一个进程里,所以会继续工作
。
回到前面的方法,如果变量 app 为空,就代表 service 要运行的进程还没有启动,于是调用 startProcessLocked()
方法去启动一个新的进程。
如果 app 不为空,采用默认的方式启动 Service,最终调用到 realStartServiceLocked()
方法:
# ActiveServices.realStartServiceLocked()
// frameworks/base/services/core/java/com/android/server/am/ActiveServices.javapublic final class ActiveServices { private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { ... ... try { ... ... app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo), app.getReportedProcState()); ... ... } ... ... }}
在这个方法中,app 对象的 thread
变量是一个 ApplicationThread
Binder
对象,调用它的 scheduleCreateService()
方法之后,会进入客户端的 ActivityThread
中。
# ActivityThread.scheduleCreateService()
// frameworks/base/core/java/android/app/ActivityThread.javapublic final class ActivityThread extends ClientTransactionHandler { // ApplicationThread 是一个 Binder private class ApplicationThread extends IApplicationThread.Stub { 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; sendMessage(H.CREATE_SERVICE, s); } } }
ApplicationThread
的 scheduleCreateService()
方法通过调用 sendMessage() 方法来发送一个 msg 消息
,当 Handler 接收到了 msg 消息之后,它会调用 handleCreateService()
方法来做进一步处理。
# H.handleMessage()
// frameworks/base/core/java/android/app/ActivityThread.javapublic final class ActivityThread extends ClientTransactionHandler { class H extends Handler { public void handleMessage(Message msg) { switch (msg.what) { case CREATE_SERVICE: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj))); handleCreateService((CreateServiceData)msg.obj); // 调用 handleCreateService() 方法 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; } } }}
# ActivityThread.handleCreateService()
// frameworks/base/core/java/android/app/ActivityThread.javapublic final class ActivityThread extends ClientTransactionHandler { private void handleCreateService(CreateServiceData data) { ... ... LoadedApk packageInfo = getPackageInfoNoCheck(data.info.applicationInfo, data.compatInfo); Service service = null; try { java.lang.ClassLoader cl = packageInfo.getClassLoader(); service = packageInfo.getAppFactory().instantiateService(cl, data.info.name, data.intent); } 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, packageInfo); context.setOuterContext(service); Application app = packageInfo.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); } } }}
在 ActivityThread
类的 handleCreateService()
方法中,首先通过 ClassLoader
类把 Service 加载进来,而参数 data.info.name
表示这个 Service
的名字,instantiateService()
方法是创建一个 Service 实例。接着,创建一个 Context 对象
,作为上下文环境之用。
handleCreateService()
方法最后调用了 service 的 onCreate() 方法
,当这个方法被调用之后,就会进入应用程序里 Service 的 onCreate() 方法
。
至此,Service 的启动就分析完毕,这个过程与启动 Activity 相比简单了很多。
更多相关文章
- android使用AIDL跨进程通信(IPC)
- 聊聊Service(二)
- android的TextView的TextWatcher使用
- flutter 持久化存储-----数据库sqflite
- android在程序中打开另一个程序
- Android(安卓)百度地图使几点始终在合适的屏幕范围内显示
- android中的4种launchmode详解
- ViewGroup中的onInterceptTouchEvent和onTouchEvent调用时序
- Android(安卓)6.0 变更