1、ContextWrapper.startService
startService是Context的方法,Activity、Service都繼承自ContextWrapper,而ContextWrapper又繼承自Context,BroadcastReceiver的onReceive方法中有個參數是Context類型的,所以我們在Activity、Service、BroadcastReceiver中都可以調用startService方法,當在Activity等中調用startService時,首先會調用到ContextWrapper的startService方法:
public ComponentName startService(Intent service) { return mBase.startService(service);}
2、ContextImpl.startService
mBase是ContextImpl的執行個體,從名字也可以看到ContextImpl也是Context的子類,從ContextWrapper的名字也可以看到,它只是Context的封裝類,其函數內部的實現都是通過調用內部ContextImpl類的執行個體mBase來完成實際請求,這被稱為裝飾者模式。
ContextImpl的startService直接調用startServiceAsUser,在startServiceAsUser中調用ActivityManagerNative.getDefault().startService,ActivityManagerNative.getDefault()返回一個IActivityManager對象,典型的Binder通訊。所以接下來會通過ActivityManagerProxy的startService經由Binder調用到ActivityManagerService(繼承自ActivityManagerNative)的startService方法。
public ComponentName startServiceAsUser(Intent service, UserHandle user) { try { service.setAllowFds(false); ComponentName cn = ActivityManagerNative.getDefault().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier()); ... return cn; } catch (RemoteException e) { return null; }}
3、ActivityManagerService.startService與ActiveServices
在ActivityManagerService的startService中,首先檢查Caller的合法性(PID、UID),然後調用ActiveServices的startServiceLocked方法(在舊版本中這個方法在ActivityManagerService中),在startServiceLocked中,首先通過retrieveServiceLocked檢索我們調用startService時傳入的Intent資訊,將結果存入ServiceLookupResult.record中(ServiceRecord),緊接著調用ActiveServices的bringUpServiceLocked方法。
在bringUpServiceLocked中調用ActivityManagerService的startProcessLocked獲得一個ProcessRecord對象並將其加入到mPendingServices隊列中。startServiceLocked、bringUpServiceLocked都是從ActivityManagerService中調用過來的,所以是一直運行在ActivityaManagerService進程中,再調用ActivityManagerService的方法就是直接調用,而不用通過IPC。
ActivityManagerService中有兩個重載形式的startProcessLocked,首先進入參數多的那一個,通過newProcessRecordLocked獲得一個ProcessRecord對象,然後把這個對象作為參數調用另一個形式的startProcessLocked,在這個startProcessLocked中,調用Process.start建立一個新的進程,將返回的Process.ProcessStartResult對象、新進程的PID及獲得的ProcessRecord對象放入mPidSelfLocked列表中。
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName, boolean allowWhileBooting, boolean isolated) { ... app = newProcessRecordLocked(null, info, processName, isolated); ... startProcessLocked(app, hostingType, hostingNameStr); return (app.pid != 0) ? app : null;}private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr) { ... Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread", app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, null, null); ... synchronized (mPidsSelfLocked) { this.mPidsSelfLocked.put(startResult.pid, app); ... } ...}
4、ActivityThread.main
在Process.start中建立了一個進程,然後調用了ActivityThread的main函數。
public static void main(String[] args) { ... Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } ... Looper.loop(); ...}
5、ActivityManagerService.attachApplication
在main中建立一個ActivityThread對象,並調用其attach方法,參數表示是否是系統進程。這裡已經是在新進程裡了。在attach中,又調用了ActivityManagerNative.getDefault().attachApplication(mAppThread)。同樣,經由Binder由ActivityManagerProxy到了ActivityManagerService的attachApplication方法,在attachApplication中直接調用attachApplicationLocked。
在attachApplicationLocked中,通過新進程的PID獲得在第3步中放入mPidSelfLocked列表中的ProcessRecord對象,然後調用ActiveyServices的attachApplicationLocked方法,在這個方法中通過進程PID與進程名找到在第3步中放入mPendingServices中的ServiceRecord對象,再以這個找到的ServiceRecord對象與傳入的ProcessRecord對象為參數調用realStartServiceLocked,這個函數也在ActiveServices中。
private final boolean attachApplicationLocked(IApplicationThread thread, nt pid) { ProcessRecord app; if (pid != MY_PID && pid >= 0) { synchronized (mPidsSelfLocked) { app = mPidsSelfLocked.get(pid); } } else { app = null; } ... mServices.attachApplicationLocked(app, processName); ...}boolean attachApplicationLocked(ProcessRecord proc, String processName) throws Exception { boolean didSomething = false; // Collect any services that are waiting for this process to come up. if (mPendingServices.size() > 0) { ServiceRecord sr = null; try { for (int i=0; i<mPendingServices.size(); i++) { sr = mPendingServices.get(i); if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid || !processName.equals(sr.processName))) { continue; } mPendingServices.remove(i); i--; realStartServiceLocked(sr, proc); didSomething = true; } } catch (Exception e) { Slog.w(TAG, "Exception in new application when starting service " + sr.shortName, e); throw e; } } ...}
6
在realStartServiceLocked中,取得傳入的ProcessRecord對象的IApplicationThread類型的成員變數thread,調用其scheduleCreateService方法,同ActivityManagerProxy一樣,調用的是ApplicationThreadProxy的scheduleCreateService,然後經由Binder到ApplicationThread的scheduleCreateService(ApplicationThread是ActivityThread的私人內部類)。
7、ApplicationThread.scheduleCreateService與ActivityThread.handleCreateService
在ApplicationThread的scheduleCreateService中調用了外部類ActivityThread的queueOrSendMessage方法,向H中sendMessage(H繼承自Handler),接下來肯定到了H的handleMessage,在handleMessage中走CREATE_SERVICE的switch case,調用外部類ActivityThread的handleCreateService方法。
在handleCreateService通過JAVA的ClassLoader load載入要啟動的Service的類,並通過newInstance建立一個Service的執行個體,new ContextImpl,makeApplication並跟建立的Service執行個體attach,然後調用我們熟悉的Service的onCreate方法,至此Service啟動成功。
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) { ... } try { if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name); ContextImpl context = new ContextImpl(); context.init(packageInfo, null, this); Application app = packageInfo.makeApplication(false, mInstrumentation); context.setOuterContext(service); service.attach(context, this, data.info.name, data.token, app, ActivityManagerNative.getDefault()); // 調用Service的onCreate,即要啟動的Service的onCreate service.onCreate(); mServices.put(data.token, service); try { ActivityManagerNative.getDefault().serviceDoneExecuting( data.token, 0, 0, 0); } catch (RemoteException e) { // nothing to do. } } catch (Exception e) { ... }}
總結:
1、調用ContextImpl的startService,通過Binder進入ActivityManagerService的進程執行ActivityManagerService的startService方法。
2、在startService過程中建立一個進程,在建立的進程中建立Looper,調用ActivityThread的attach方法,然後就又進入了ActivityManagerService的進程。
3、擷取要在新進程啟動的服務的相關資訊,在ActivityManagerService中通過ApplicationThreadProxy又進入Service進程,Service的進程啟起來,調用我們熟悉的Service的onCreate方法。