Service 是一种可在后台执行长时间运行操作而不提供界面的应用组件。服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行。此外,组件可通过绑定到服务与之进行交互,甚至是执行进程间通信 (IPC)(截取自官文文档)。服务使用方式有两种,分别是startService和bindService,接下来通过分析源码了解服务启动过程。(本文源码基于Android 10 )
frameworks/base/core/java/android/content/ContextWrapper.java
Context mBase; /** * Set the base context for this ContextWrapper. All calls will then be * delegated to the base context. Throws * IllegalStateException if a base context has already been set. * * @param base The new base context for this wrapper. */ protected void attachBaseContext(Context base) { if (mBase != null) { throw new IllegalStateException("Base context already set"); } mBase = base;//2 } @Override public ComponentName startService(Intent service) { return mBase.startService(service);//1 } 复制代码
frameworks/base/core/java/android/app/ActivityThread.java
/** Core implementation of activity launch. */ private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ...... ContextImpl appContext = createBaseContextForActivity(r);//1 ....... appContext.setOuterContext(activity); activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor, window, r.configCallback, r.assistToken); //2 ...... return activity; } 复制代码
frameworks/base/core/java/android/app/Activity.java
@UnsupportedAppUsage final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config, String referrer, IVoiceInteractor voiceInteractor, Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) { attachBaseContext(context);//1 ....... } @Override protected void attachBaseContext(Context newBase) { super.attachBaseContext(newBase); //2 if (newBase != null) { newBase.setAutofillClient(this); newBase.setContentCaptureOptions(getContentCaptureOptions()); } } 复制代码
frameworks/base/core/java/android/app/ContextImpl.java
@Override public ComponentName startService(Intent service) { warnIfCallingFromSystemProcess(); return startServiceCommon(service, false, mUser);//1 } 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());//2 ....... return cn; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } 复制代码
frameworks/base/core/java/android/app/ActivityManager.java
/** * @hide */ @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); //1 return am; } }; 复制代码
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@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);//1 } finally { Binder.restoreCallingIdentity(origId); } return res; } } 复制代码
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId, boolean allowBackgroundActivityStarts) throws TransactionTooLargeException { ....... ServiceLookupResult res = retrieveServiceLocked(service, null, resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg, false, false);//1 ....... ServiceRecord r = res.record;//2 ....... ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);//3 return cmp; } 复制代码
frameworks/base/core/java/android/app/ActivityManager.java
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r, boolean callerFg, boolean addToStarting) throws TransactionTooLargeException { String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);//1 if (error != null) { return new ComponentName("!!", error); } ..... return r.name; } 复制代码
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
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); //1 ..... if (app != null && app.thread != null) {//2 try { app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats); realStartServiceLocked(r, app, execInFg);//3 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. } } ...... } ........ return null; } 复制代码
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
/** * Note the name of this method should not be confused with the started services concept. * The "start" here means bring up the instance in the client, and this method is called * from bindService() as well. */ private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { ...... r.setProcess(app);//1 ...... try { ...... app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo), app.getReportedProcState());//2 r.postNotification(); created = true; } catch (DeadObjectException e) { ..... } finally { ........ } 复制代码
frameworks/base/core/java/android/app/ActivityThread.java
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;//1 sendMessage(H.CREATE_SERVICE, s);//2 } ....... } 复制代码
frameworks/base/core/java/android/app/ActivityThread.java
class H extends Handler { ..... public void handleMessage(Message msg) { ..... switch (msg.what) { case CREATE_SERVICE: ...... handleCreateService((CreateServiceData)msg.obj);//1 .... break; .... } } 复制代码
frameworks/base/core/java/android/app/ActivityThread.java
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 packageInfo = getPackageInfoNoCheck( data.info.applicationInfo, data.compatInfo);//1 Service service = null; try { java.lang.ClassLoader cl = packageInfo.getClassLoader(); service = packageInfo.getAppFactory() .instantiateService(cl, data.info.name, data.intent);//2 } catch (Exception e) { ...... } try { ...... ContextImpl context = ContextImpl.createAppContext(this, packageInfo);//3 context.setOuterContext(service); Application app = packageInfo.makeApplication(false, mInstrumentation); service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService());//4 service.onCreate();//5 mServices.put(data.token, service);//6 ..... } catch (Exception e) { if (!mInstrumentation.onException(service, e)) { throw new RuntimeException( "Unable to create service " + data.info.name + ": " + e.toString(), e); } } } 复制代码