Service 的啟動過程
看完Activity
的啟動過程,發現Service
的啟動過程相對來說就比較簡單了。
要說起啟動過程,就得從startService
開始:
1.startService
根據原始碼的跳轉,發現跳轉到ContextWrapper
這個類中,程式碼如下:
@Override public ComponentName startService(Intent service) { return mBase.startService(service); }
其中mBase
是型別是:Context
型別,如下:
public class ContextWrapper extends Context { Context mBase; ...... }
而我們又知道Context
是一個抽象類 ,實現者是ContextImpl
,所以我們應該是檢視ContextImpl
這個類中的startService(service)
方法。
ContextImpl
中的方法定義如下:
@Override public ComponentName startService(Intent service) { warnIfCallingFromSystemProcess(); return startServiceCommon(service, false, mUser); }
在startService
中又呼叫了startServiceCommon(service,(requirForeground:false),mUser)
這個方法,繼續跟進:
2.startServiceCommon
startServiceCommon
方法如下:
private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) { try { //校驗要啟動的service validateServiceIntent(service); service.prepareToLeaveProcess(this); ComponentName cn = ActivityManager.getService().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded( getContentResolver()), requireForeground, 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()); } else if (cn.getPackageName().equals("?")) { throw new IllegalStateException( "Not allowed to start service " + service + ": " + cn.getClassName()); } } return cn; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
這裡面有幾個需要說明一下:
-
ActivityManager.getService()
點進去檢視
/** * @hide */ public static IActivityManager getService() { return IActivityManagerSingleton.get(); } 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; } };
首先是返回的型別是IActivityManager
型別,其中在create
方法中,拿到遠端服務的Binder
物件,其中IActivityManager.Stub.asInterface(b)
不知道大家有沒有想起AIDL
這就很熟悉了,就是拿到遠端服務的代理物件:IActivityManager
,通過代理物件呼叫遠端的方法,是應用程序與服務程序通訊的媒介,如果沒猜錯的話就是在ActivityManagerService
中實現了,檢視ActivityManagerService
類:
public class ActivityManagerService extends IActivityManager.Stub implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback { ..... }
果然不出所料,AMS extend IActivityManager.Stub
.
-
mMainThread.getApplicationThread()
首先明白mMainThread
是ActivityThread
類的例項變數,通過getApplicationThread()
方法拿到一個ApplicationThread
類的例項:
public ApplicationThread getApplicationThread() { return mAppThread; }
而ApplicationThread
類定義如下:
private class ApplicationThread extends IApplicationThread.Stub { ..... }
發現ApplicationThread
是ActivityThread
的一個內部類.並且實現了IApplicationThread.Stub
,而我們又把這個型別傳入給了AMS
,相當於遠端服務拿到了一個訪問應用程序的代理,型別為:IApplicationThread
總結:到目前為止,客戶端拿到了遠端服務的代理(IActivityManager)
, 服務端拿到了客戶端的代理(IApplicationThread)
,它們互相拿到各自程序的代理類,是它們進行程序間通訊的基礎。
ok ,我們回到最初那個地方:
ComponentName cn = ActivityManager.getService().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded( getContentResolver()), requireForeground, getOpPackageName(), user.getIdentifier());
通過前面的分析我們知道:ActivityManager.getService().
實際就是AMS
遠端代理,最終在AMS
中完成,我們去AMS
程式碼中檢視下startService
程式碼:
3.ActivityManagerService.startService
@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 if (service != null && service.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } if (callingPackage == null) { throw new IllegalArgumentException("callingPackage cannot be null"); } if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "*** startService: " + service + " type=" + resolvedType + " fg=" + requireForeground); synchronized(this) { final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); ComponentName res; try { // 又呼叫了startServiceLocked 方法 res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid, requireForeground, callingPackage, userId); } finally { Binder.restoreCallingIdentity(origId); } return res; } }
startServiceLocked
方法很複雜,大概如下:
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId) throws TransactionTooLargeException { ..... ServiceRecord r = res.record;//啟動service的資訊儲存在 serviceRecord 中 .... ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting); return cmp; ..... }
內部又呼叫了:startServiceInnerLocked
方法
4.startServiceInnerLocked
如下:
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r, boolean callerFg, boolean addToStarting) throws TransactionTooLargeException { ... String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false); ... }
又呼叫:bringUpServiceLocked
5.bringUpServiceLocked
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired) throws TransactionTooLargeException { .... realStartServiceLocked(r, app, execInFg); }
而後又呼叫了realStartServiceLocked(r, app, execInFg);
6.realStartServiceLocked
private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { .... app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState); .... }
其中app.thread
是IApplicationThread
型別,就是遠端呼叫客戶端程序裡的方法,scheduleCreateService
,而我們又知道ApplicationThread
實現了IApplicationThread
,所以就檢視ApplicationThread
類中的scheduleCreateService
方法,前面我們說過ApplicationThread
是ActivityThread
的一個內部類,檢視:
7.ApplicationThread.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; sendMessage(H.CREATE_SERVICE, s); }
發現內部通過傳送一個CREATE_SERVICE
的訊息,H
是Handle
,繼續檢視:
handleMessage
方法
case CREATE_SERVICE: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj))); handleCreateService((CreateServiceData)msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break;
到handleCreateService
中:
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); Service service = null; try { java.lang.ClassLoader cl = packageInfo.getClassLoader(); service = (Service) cl.loadClass(data.info.name).newInstance(); } 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); //建立context ContextImpl context = ContextImpl.createAppContext(this, packageInfo); context.setOuterContext(service); //建立Application Application app = packageInfo.makeApplication(false, mInstrumentation); //通過attach 方法,將context application ,service 連線起來 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); } } }
service.onCreate();
ok ,呼叫了onCreate
方法,至此,service
的啟動過程的就完成了。