Android服務啟動之StartService源碼分析

在編寫Android應用程序時,我們一般將比較耗時的操作放在一個獨立的進程來處理,這樣主進程仍然可以流暢地響應界面事件,提高用戶體驗。Android系統為我們提供瞭一個Service類,我們可以實現一個以Service為基類的服務子類,在裡面實現自己的計算型邏輯,然後在主進程通過startService函數來啟動這個服務。在本文中,將詳細分析應用程序進程是如何通過startService函數來啟動自定義服務的。

請求啟動Service

frameworks\base\core\java\android\content\Context.java

public abstract ComponentName startService(Intent service);

在Context類中定義瞭抽象方法startService,該函數由Context的子類ContextImpl實現。

frameworks\base\core\java\android\content\ContextWrapper.java

public ComponentName startService(Intent service) {
	return mBase.startService(service);
}

mBase為ContextImpl類型對象

frameworks\base\core\java\android\app\ContextImpl.java

public ComponentName startService(Intent service) {
	try {
		service.setAllowFds(false);
		//調用ActivityManagerService服務的Binder遠程代理發送啟動Service的參數
		ComponentName cn = ActivityManagerNative.getDefault().startService(
			mMainThread.getApplicationThread(), service,
			service.resolveTypeIfNeeded(getContentResolver()));
		if (cn != null && cn.getPackageName().equals("!")) {
			throw new SecurityException(
					"Not allowed to start service " + service
					+ " without permission " + cn.getClassName());
		}
		return cn;
	} catch (RemoteException e) {
		return null;
	}
}

ActivityManagerNative.getDefault()將得到ActivityManagerProxy對象,參數mMainThread.getApplicationThread()表示為當前啟動服務進程的ApplicationThread對象,參數service.resolveTypeIfNeeded(getContentResolver())返回當前傳輸的Intent的MEMI號,關於Binder進程間RPC調用過程這裡不在詳細分析,有興趣可以參考Android服務函數遠程調用源碼分析。通過ActivityManagerNative.getDefault().startService()調用,將Service的啟動交給SystemServer進程的ActivityManagerService服務來完成。

frameworks\base\services\java\com\android\server\am\ActivityManagerService.java

public ComponentName startService(IApplicationThread caller, Intent service,
		String resolvedType) {
	// Refuse possible leaked file descriptors
	if (service != null && service.hasFileDescriptors() == true) {
		throw new IllegalArgumentException("File descriptors passed in Intent");
	}

	synchronized(this) {
		//讀取啟動服務的應用程序進程的PID和UID
		final int callingPid = Binder.getCallingPid();
		final int callingUid = Binder.getCallingUid();
		final long origId = Binder.clearCallingIdentity();
		ComponentName res = startServiceLocked(caller, service,
				resolvedType, callingPid, callingUid);
		Binder.restoreCallingIdentity(origId);
		return res;
	}
}

參數caller是啟動服務的應用程序進程的ApplicationThread實例,比如說Launcher啟動服務,那麼這個caller就是Launcher進程的ApplicationThread實例,每一個Android應用程序進程都有且隻有一個ActivityThread實例,每一個ActivityThread實例中又定義瞭一個ApplicationThread對象。接下來調用startServiceLocked函數來啟動服務

frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

ComponentName startServiceLocked(IApplicationThread caller,
		Intent service, String resolvedType,
		int callingPid, int callingUid) {
	synchronized(this) {
		if (DEBUG_SERVICE) Slog.v(TAG, "startService: " + service
				+ " type=" + resolvedType + " args=" + service.getExtras());
		if (caller != null) {
			//通過ApplicationThread對象從ActivityManagerService的成員變量mLruProcesses列表中查找啟動服務的進程在ActivityManagerService中的ProcessRecord對象,變量mLruProcesses的說明:
			 /**
			 * List of running applications, sorted by recent usage.
			 * The first entry in the list is the least recently used.
			 * It contains ApplicationRecord objects.  This list does NOT include
			 * any persistent application records (since we never want to exit them).
			 */
			final ProcessRecord callerApp = getRecordForAppLocked(caller);
			if (callerApp == null) {
				throw new SecurityException(
						"Unable to find app for caller " + caller
						+ " (pid=" + Binder.getCallingPid()
						+ ") when starting service " + service);
			}
		}
        //解析service這個Intent
         /**
         * private final class ServiceLookupResult {
		 *		final ServiceRecord record; ServiceRecord用於在服務端描述一個Service信息
		 *		final String permission;
		 *		ServiceLookupResult(ServiceRecord _record, String _permission) {
		 *			record = _record;
		 *			permission = _permission;
		 *		}
		 * };
         */
		ServiceLookupResult res = retrieveServiceLocked(service, resolvedType,
					callingPid, callingUid, UserId.getUserId(callingUid));
		//系統中沒有註冊此Service
		if (res == null) {
			return null;
		}
		if (res.record == null) {
			return new ComponentName("!", res.permission != null ? res.permission : "private to package");
		}
		//權限檢查
		ServiceRecord r = res.record;
		NeededUriGrants neededGrants = checkGrantUriPermissionFromIntentLocked(
				callingUid, r.packageName, service, service.getFlags(), null);
		if (unscheduleServiceRestartLocked(r)) {
			if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
		}
		//初始化服務端的ServiceRecord信息
		r.startRequested = true;
		r.callStart = false;
		r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
				service, neededGrants));
		r.lastActivity = SystemClock.uptimeMillis();
		synchronized (r.stats.getBatteryStats()) {
			r.stats.startRunningLocked();
		}
		//進一步啟動Service
		if (!bringUpServiceLocked(r, service.getFlags(), false)) {
			return new ComponentName("!", "Service process is bad");
		}
		return r.name;
	}
}

ActivityManagerService在請求Zygote進程孵化新的應用程序進程時,在ActivityManagerService服務端為每一個應用程序進程創建瞭對應的ProcessRecord對象來描述新的應用程序進程信息,關於ActivityManagerService請求孵化新應用程序過程請參考Android
應用進程啟動過程的源碼分析。函數首先根據應用程序進程中的IApplicationThread對象在最近啟動的應用程序列表mLruProcesses中為服務啟動進程查找對應的ProcessRecord對象,如果啟動Service的應用程序進程還未啟動,則拋出SecurityException異常。然後調用retrieveServiceLocked函數為當前啟動的Service在ActivityManagerService服務端創建一個ServiceRecord對象來描述當前Service的信息。

frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

private ServiceLookupResult retrieveServiceLocked(Intent service,
		String resolvedType, int callingPid, int callingUid, int userId) {
	ServiceRecord r = null;
	if (DEBUG_SERVICE)
		Slog.v(TAG, "retrieveServiceLocked: " + service + " type=" + resolvedType
				+ " callingUid=" + callingUid);
	//根據Service的包名從ActivityManagerService的成員變量mServiceMap中查找對應的ServiceRecord對象
	if (service.getComponent() != null) {
		r = mServiceMap.getServiceByName(service.getComponent(), userId);
	}
	//根據啟動Service的Intent信息從成員變量mServiceMap中查找對應的ServiceRecord對象
	if (r == null) {
		Intent.FilterComparison filter = new Intent.FilterComparison(service);
		r = mServiceMap.getServiceByIntent(filter, userId);
	}
	//如果mServiceMap中不存在當前啟動的Service對應的ServiceRecord對象
	if (r == null) {
		try {
			//從PackageManager服務中獲取當前啟動Service的相關信息,並構造ResolveInfo對象
			ResolveInfo rInfo =AppGlobals.getPackageManager().resolveService(
							service, resolvedType, STOCK_PM_FLAGS, userId);
			//獲取Service信息對象
			ServiceInfo sInfo = rInfo != null ? rInfo.serviceInfo : null;
			if (sInfo == null) {
				Slog.w(TAG, "Unable to start service " + service +
					  ": not found");
				return null;
			}
			if (userId > 0) {
				if (isSingleton(sInfo.processName, sInfo.applicationInfo)) {
					userId = 0;
				}
				sInfo.applicationInfo = getAppInfoForUser(sInfo.applicationInfo, userId);
			}
			ComponentName name = new ComponentName(
					sInfo.applicationInfo.packageName, sInfo.name);
			//再次根據Service的包名從成員變量mServiceMap中查找對應的ServiceRecord對象
			r = mServiceMap.getServiceByName(name, userId);
			//依然查找不到
			if (r == null) {
				Intent.FilterComparison filter = new Intent.FilterComparison(
						service.cloneFilter());
				//為當前Service構造一個重啟服務的Runnable對象
				ServiceRestarter res = new ServiceRestarter();
				BatteryStatsImpl.Uid.Pkg.Serv ss = null;
				BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
				synchronized (stats) {
					ss = stats.getServiceStatsLocked(
							sInfo.applicationInfo.uid, sInfo.packageName,
							sInfo.name);
				}
				//為當前Service構造ServiceRecord對象
				r = new ServiceRecord(this, ss, name, filter, sInfo, res);
				//設置ServiceRestarter重啟的服務為當前Service
				res.setService(r);
				//將當前Service的服務端描述符ServiceRecord保存到mServiceMap中
				mServiceMap.putServiceByName(name, UserId.getUserId(r.appInfo.uid), r);
				mServiceMap.putServiceByIntent(filter, UserId.getUserId(r.appInfo.uid), r);
				//通過服務名稱查找mPendingServices服務列表中是否存在當前Service
				int N = mPendingServices.size();
				for (int i=0; i<N; i++) {
					ServiceRecord pr = mPendingServices.get(i);
					if (pr.name.equals(name)) {
						mPendingServices.remove(i);
						i--;
						N--;
					}
				}
			}
		} catch (RemoteException ex) {
			// pm is in same process, this will never happen.
		}
	}
	if (r != null) {
		//檢查服務權限
		if (checkComponentPermission(r.permission,
				callingPid, callingUid, r.appInfo.uid, r.exported)
				!= PackageManager.PERMISSION_GRANTED) {
			if (!r.exported) {
				Slog.w(TAG, "Permission Denial: Accessing service " + r.name
						+ " from pid=" + callingPid
						+ ", uid=" + callingUid
						+ " that is not exported from uid " + r.appInfo.uid);
				return new ServiceLookupResult(null, "not exported from uid "
						+ r.appInfo.uid);
			}
			Slog.w(TAG, "Permission Denial: Accessing service " + r.name
					+ " from pid=" + callingPid
					+ ", uid=" + callingUid
					+ " requires " + r.permission);
			return new ServiceLookupResult(null, r.permission);
		}
		//返回ServiceLookupResult對象
		return new ServiceLookupResult(r, null);
	}
	return null;
}

該函數通過一系列處理後,為當前啟動的Service構造瞭對應的ServiceRecord對象,並保存到ActivityManagerService的成員變量mServiceMap中,這樣就相當於在ActivityManagerService服務端完成瞭服務登記工作,接下來將調用bringUpServiceLocked函數正式啟動這個已經記錄在案的Service。

frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

private final boolean bringUpServiceLocked(ServiceRecord r,
		int intentFlags, boolean whileRestarting) {
	//如果該Service服務已經創建,再次調用startService時,隻調用該Service的onStartCommand來運行該Service
	if (r.app != null && r.app.thread != null) {
		//啟動Service
		sendServiceArgsLocked(r, false);
		return true;
	}
	if (!whileRestarting && r.restartDelay > 0) {
		// If waiting for a restart, then do nothing.
		return true;
	}
	if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
	// 將當前啟動的Service從服務重啟列表mRestartingServices中移除
	mRestartingServices.remove(r);
	// Service is now being launched, its package can't be stopped.
	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;
	//得到在XML中設置該Service運行的進程名稱
	final String appName = r.processName;
	ProcessRecord app;
	//當前Service運行在應用程序進程,並非獨立進程
	if (!isolated) {
		//根據進程名稱及UID從ActivityManagerService的成員變量mProcessNames中查找進程對應的描述符ProcessRecord
		app = getProcessRecordLocked(appName, r.appInfo.uid);
		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);
				//在現有的進程中啟動Service
				realStartServiceLocked(r, app);
				return true;
			} catch (RemoteException e) {
				Slog.w(TAG, "Exception when starting service " + r.shortName, e);
			}
		}
	} else {
		// If this service runs in an isolated process, then each time
		// we call startProcessLocked() we will get a new isolated
		// process, starting another process if we are currently waiting
		// for a previous process to come up.  To deal with this, we store
		// in the service any current isolated process it is running in or
		// waiting to have come up.
		app = r.isolatedProc;
	}
	// Not running -- get it started, and enqueue this service record
	// to be executed when the app comes up.
	if (app == null) {
		//啟動應用程序進程
		if ((app=startProcessLocked(appName, r.appInfo, true, intentFlags,
				"service", r.name, false, isolated)) == null) {
			Slog.w(TAG, "Unable to launch app "
					+ r.appInfo.packageName + "/"
					+ r.appInfo.uid + " for service "
					+ r.intent.getIntent() + ": process is bad");
			//強制退出Service
			bringDownServiceLocked(r, true);
			return false;
		}
		if (isolated) {
			r.isolatedProc = app;
		}
	}
	//當ActivityManagerService服務還為準備好時,mPendingServices用於保存客戶進程請求啟動的Servcie
	//保存當前請求啟動的Service
	if (!mPendingServices.contains(r)) {
		mPendingServices.add(r);
	}
	return true;
}

如果當前系統中已經存在運行該Service的進程,則調用函數realStartServiceLocked來進一步啟動Service,realStartServiceLocked函數的第一個參數是當前啟動的Service在ActivityManagerService服務中的描述符對象ServiceRecord,第二個參數則是運行該Service的進程在ActivityManagerService服務中的描述符對象ProcessRecord,有瞭啟動的Service和運行該Service的進程,接下來就可以真正啟動該Service瞭。

frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

private final void realStartServiceLocked(ServiceRecord r,ProcessRecord app) throws  RemoteException {
	if (app.thread == null) {
		throw new RemoteException();
	}
	if (DEBUG_MU)
		Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid
				+ ", ProcessRecord.uid = " + app.uid);
	// LC_RAM_SUPPORT
	if (LC_RAM_SUPPORT) {
		r.appAdj = ProcessRecord.TMP_CUR_ADJ_DEFAULT;
		r.hasFixAdj = (app.fixAdj != ProcessRecord.TMP_FIX_ADJ_DEFAULT);
	}
	r.app = app;
	r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
	//在ActivityManagerService服務中記錄當前進程中運行的所有Service
	app.services.add(r);
	bumpServiceExecutingLocked(r, "create");
	//mLruProcesses保存系統最近運行的應用程序進程信息,更新當前ProcessRecord在mLruProcesses變量中的狀態
	updateLruProcessLocked(app, true, true);
	boolean created = false;
	try {
		mStringBuilder.setLength(0);
		r.intent.getIntent().toShortString(mStringBuilder, true, false, true, false);
		EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,
				System.identityHashCode(r), r.shortName,
				mStringBuilder.toString(), r.app.pid);
		synchronized (r.stats.getBatteryStats()) {
			r.stats.startLaunchedLocked();
		}
		//檢查當前Service所在包是否經過Dex優化過
		ensurePackageDexOpt(r.serviceInfo.packageName);
		//創建Service服務
		app.thread.scheduleCreateService(r, r.serviceInfo,compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));
		r.postNotification();
		created = true;
	} finally {
		if (!created) {
			app.services.remove(r);
			scheduleServiceRestartLocked(r, false);
		}
	}
	//綁定該Service服務
	requestServiceBindingsLocked(r);
	// If the service is in the started state, and there are no
	// pending arguments, then fake up one so its onStartCommand() will
	// be called.
	if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
		r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
				null, null));
	}
	//啟動該Service服務
	sendServiceArgsLocked(r, true);
}

在該函數中完成瞭Service的創建,Service的綁定,Service的啟動。無論是Service的創建,綁定還是啟動過程,都是由ActivityManagerService服務調度應用程序進程來完成的,通過Binder跨進程調用來實現。在此之前Service啟動的前期工作都是在ActivityManagerService中完成,主要是實現Service的備案:

Service創建過程

ActivityManagerService通過Binder跨進程調用應用程序進程中的ApplicationThread的scheduleCreateService函數在應用程序進程中加載Service類,並創建Service對象。
frameworks\base\core\java\android\app\ActivityThread.$ApplicationThread

public final void scheduleCreateService(IBinder token,
		ServiceInfo info, CompatibilityInfo compatInfo) {
	CreateServiceData s = new CreateServiceData();
	s.token = token;//ServiceRecord Binder本地對象
	s.info = info;
	s.compatInfo = compatInfo;
	queueOrSendMessage(H.CREATE_SERVICE, s);
}

在ActivityThread類中定義瞭一個內部類H,繼承於Handler,在Android應用程序進程啟動過程中,我們介紹瞭Zygote進程通過復制一份自身進程地址空間來實現子進程的創建過程,孵化出來新的應用程序進程通過加載ActivityThread類,並調用該類的main函數為應用程序主線程建立消息循環,而定義的H這個Handler正是向主線程消息循環發送消息的通道,在這個函數中,將ActivityManagerService服務通過Binder跨進程調用Service運行進程的scheduleCreateService函數轉換為本地的一個異步調用。在該函數中,將函數調用參數信息封裝為CreateServiceData對象,然後通過queueOrSendMessage函數向應用程序主線程消息循環中發送一個CREATE_SERVICE消息,在H的handleMessage()函數中,完成對該消息的處理:
frameworks\base\core\java\android\app\ActivityThread.$H

public void handleMessage(Message msg) {
	if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
	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;
	}
}

這裡又將Service的創建工作交給H的外部類ActivityThread的handleCreateService()函數來完成。
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();
	//加載啟動的Service類
	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);
		//為該Service創建一個上下文ContextImpl對象
		ContextImpl context = new ContextImpl();
		context.init(packageInfo, null, this);

		Application app = packageInfo.makeApplication(false, mInstrumentation);
		context.setOuterContext(service);
		//將Application,ActivityManagerService,當前Service在SystemServer進程中的ServiceRecord引用保存到當前Service的成員變量中
		service.attach(context, this, data.info.name, data.token, app,ActivityManagerNative.getDefault());
		//回調當前啟動Service的onCreate函數
		service.onCreate();
		//變量mServices保存瞭應用程序進程中運行的所有Service
		mServices.put(data.token, service);
		//從應用程序進程進入SystemServer進程
		try {
			//通知ActivityManagerService服務,當前Service創建完成
			ActivityManagerNative.getDefault().serviceDoneExecuting(data.token, 0, 0, 0);
		} catch (RemoteException e) {
			// nothing to do.
		}
	} catch (Exception e) {
		if (!mInstrumentation.onException(service, e)) {
			throw new RuntimeException(
				"Unable to create service " + data.info.name
				+ ": " + e.toString(), e);
		}
	}
}

在前面我們已經知道當前啟動的Service在ActivityManagerService中已經記錄在mServiceMap成員變量中瞭,對於運行Service的應用程序進程來說,仍然需要記錄該進程中運行的Service信息,並保存在ActivityThread的成員變量mServices中。在該函數中加載啟動Service的類,並為Service創建一個上下文對象,同時回調Service的onCreate()函數完成Service的創建過程。

Service綁定過程

frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

private final void requestServiceBindingsLocked(ServiceRecord r) {
	//遍歷當前Service的成員變量bindings
	Iterator bindings = r.bindings.values().iterator();
	while (bindings.hasNext()) {
		IntentBindRecord i = bindings.next();
		//調用requestServiceBindingLocked()函數綁定前Service
		if (!requestServiceBindingLocked(r, i, false)) {
			break;
		}
	}
}

ServiceRecord的成員變量bindings中保存瞭需要綁定當前Service的IntentBindRecord對象,在該函數中就是遍歷bindings列表,然後調用requestServiceBindingLocked()函數來與當前Service綁定
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

private final boolean requestServiceBindingLocked(ServiceRecord r,
		IntentBindRecord i, boolean rebind) {
	if (r.app == null || r.app.thread == null) {
		// If service is not currently running, can't yet bind.
		return false;
	}
	if ((!i.requested || rebind) && i.apps.size() > 0) {
		try {
			bumpServiceExecutingLocked(r, "bind");
			//請求綁定服務
			r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
			if (!rebind) {
				i.requested = true;
			}
			i.hasBound = true;
			i.doRebind = false;
		} catch (RemoteException e) {
			if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
			return false;
		}
	}
	return true;
}

ActivityManagerService通過跨進程調用Service運行進程ApplicationThread的scheduleBindService函數來綁定服務
frameworks\base\core\java\android\app\ActivityThread.$ApplicationThread

public final void scheduleBindService(IBinder token, Intent intent,
		boolean rebind) {
	BindServiceData s = new BindServiceData();
	s.token = token;
	s.intent = intent;
	s.rebind = rebind;
	if (DEBUG_SERVICE)
		Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
				+ Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
	queueOrSendMessage(H.BIND_SERVICE, s);
}

將ActivityManagerService的RPC調用轉換為本地異步調用
frameworks\base\core\java\android\app\ActivityThread.$H

public void handleMessage(Message msg) {
	if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
	switch (msg.what) {
	case BIND_SERVICE:
		Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
		handleBindService((BindServiceData)msg.obj);
		Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
		break;
	}
}

這裡又將Service的創建工作交給H的外部類ActivityThread的handleBindService()函數來完成。
frameworks\base\core\java\android\app\ActivityThread.java

private void handleBindService(BindServiceData data) {
	//data.token為Service在AMS中的ServiceRecord
	Service s = mServices.get(data.token);
	if (DEBUG_SERVICE)
		Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
	if (s != null) {
		try {
			data.intent.setExtrasClassLoader(s.getClassLoader());
			try {
				//是否重新綁定
				if (!data.rebind) {
					//回調Service的onBind函數
					IBinder binder = s.onBind(data.intent);
					//AMS回調ServiceConnection的connected函數
					ActivityManagerNative.getDefault().publishService(
							data.token, data.intent, binder);
				} else {
					//回調Service的onRebind函數
					s.onRebind(data.intent);
					ActivityManagerNative.getDefault().serviceDoneExecuting(
							data.token, 0, 0, 0);
				}
				ensureJitEnabled();
			} catch (RemoteException ex) {
			}
		} catch (Exception e) {
			if (!mInstrumentation.onException(s, e)) {
				throw new RuntimeException(
						"Unable to bind to service " + s
						+ " with " + data.intent + ": " + e.toString(), e);
			}
		}
	}
}

在該函數裡,Service運行的應用程序進程調用Service的onBind函數。
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

public void publishService(IBinder token, Intent intent, IBinder service) {
	// Refuse possible leaked file descriptors
	if (intent != null && intent.hasFileDescriptors() == true) {
		throw new IllegalArgumentException("File descriptors passed in Intent");
	}
	synchronized(this) {
		if (!(token instanceof ServiceRecord)) {
			throw new IllegalArgumentException("Invalid service token");
		}
		ServiceRecord r = (ServiceRecord)token;

		final long origId = Binder.clearCallingIdentity();

		if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
				+ " " + intent + ": " + service);
		if (r != null) {
			Intent.FilterComparison filter
					= new Intent.FilterComparison(intent);
			IntentBindRecord b = r.bindings.get(filter);
			if (b != null && !b.received) {
				b.binder = service;
				b.requested = true;
				b.received = true;
				if (r.connections.size() > 0) {
					Iterator> it
							= r.connections.values().iterator();
					while (it.hasNext()) {
						ArrayList clist = it.next();
						for (int i=0; i<clist.size(); i++) {
							ConnectionRecord c = clist.get(i);
							if (!filter.equals(c.binding.intent.intent)) {
								if (DEBUG_SERVICE) Slog.v(
										TAG, "Not publishing to: " + c);
								if (DEBUG_SERVICE) Slog.v(
										TAG, "Bound intent: " + c.binding.intent.intent);
								if (DEBUG_SERVICE) Slog.v(
										TAG, "Published intent: " + intent);
								continue;
							}
							if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
							try {
								c.conn.connected(r.name, service);
							} catch (Exception e) {
								Slog.w(TAG, "Failure sending service " + r.name +
									  " to connection " + c.conn.asBinder() +
									  " (in " + c.binding.client.processName + ")", e);
							}
						}
					}
				}
			}
			serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
			Binder.restoreCallingIdentity(origId);
		}
	}
}


Service啟動過程

frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

private final void sendServiceArgsLocked(ServiceRecord r,
		boolean oomAdjusted) {
	final int N = r.pendingStarts.size();
	if (N == 0) {
		return;
	}
	//遍歷Service啟動參數列表
	while (r.pendingStarts.size() > 0) {
		try {
			//對參數列表中的每一項StartItem都啟動一次Service
			ServiceRecord.StartItem si = r.pendingStarts.remove(0);
			if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
					+ r + " " + r.intent + " args=" + si.intent);
			if (si.intent == null && N > 1) {
				// If somehow we got a dummy null intent in the middle,
				// then skip it.  DO NOT skip a null intent when it is
				// the only one in the list -- this is to support the
				// onStartCommand(null) case.
				continue;
			}
			//設置投遞時間
			si.deliveredTime = SystemClock.uptimeMillis();
			//將已投遞參數項保存到deliveredStarts列表中
			r.deliveredStarts.add(si);
			si.deliveryCount++;
			if (si.neededGrants != null) {
				grantUriPermissionUncheckedFromIntentLocked(si.neededGrants,
						si.getUriPermissionsLocked());
			}
			bumpServiceExecutingLocked(r, "start");
			if (!oomAdjusted) {
				oomAdjusted = true;
				updateOomAdjLocked(r.app);
			}
			int flags = 0;
			if (si.deliveryCount > 1) {
				flags |= Service.START_FLAG_RETRY;
			}
			if (si.doneExecutingCount > 0) {
				flags |= Service.START_FLAG_REDELIVERY;
			}
			//RPC調用Service運行進程的scheduleServiceArgs函數啟動Service服務
			r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
		} catch (RemoteException e) {
			// Remote process gone...  we'll let the normal cleanup take
			// care of this.
			if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
			break;
		} catch (Exception e) {
			Slog.w(TAG, "Unexpected exception", e);
			break;
		}
	}
}

和上面Service創建及綁定過程類似,這裡仍然是通過Binder跨進程函數調用方式調用Service運行進程中的ApplicationThread Binder本地對象的scheduleServiceArgs()函數來啟動Service
frameworks\base\core\java\android\app\ActivityThread.$ApplicationThread

public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
	int flags ,Intent args) {
	ServiceArgsData s = new ServiceArgsData();
	s.token = token;
	s.taskRemoved = taskRemoved;
	s.startId = startId;
	s.flags = flags;
	s.args = args;
	queueOrSendMessage(H.SERVICE_ARGS, s);
}

將RPC函數調用轉換為應用程序進程中的異步調用
frameworks\base\core\java\android\app\ActivityThread.$H

public void handleMessage(Message msg) {
	if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
	switch (msg.what) {
	case SERVICE_ARGS:
		Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStart");
		handleServiceArgs((ServiceArgsData)msg.obj);
		Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
		break;
	}
}

該函數直接調用ActivityThread類的handleServiceArgs()函數來啟動Service
frameworks\base\core\java\android\app\ActivityThread.java

private void handleServiceArgs(ServiceArgsData data) {
	Service s = mServices.get(data.token);
	if (s != null) {
		try {
			if (data.args != null) {
				data.args.setExtrasClassLoader(s.getClassLoader());
			}
			int res;
			if (!data.taskRemoved) {
				//回調Service的onStartCommand函數
				res = s.onStartCommand(data.args, data.flags, data.startId);
			} else {
				s.onTaskRemoved(data.args);
				res = Service.START_TASK_REMOVED_COMPLETE;
			}
			QueuedWork.waitToFinish();
			try {
				//通知ActivityManagerService服務Service啟動完成
				ActivityManagerNative.getDefault().serviceDoneExecuting(
						data.token, 1, data.startId, res);
			} catch (RemoteException e) {
				// nothing to do.
			}
			ensureJitEnabled();
		} catch (Exception e) {
			if (!mInstrumentation.onException(s, e)) {
				throw new RuntimeException(
						"Unable to start service " + s
						+ " with " + data.args + ": " + e.toString(), e);
			}
		}
	}
}

本文完整介紹瞭Service的創建啟動過程,無論是Service的創建還是啟動,Android應用程序進程自身都無法完成,必須通過ActivityManagerService服務調度實現,隻有在ActivityManagerService服務端備案後,由ActivityManagerService服務通知應用程序進程來創建並啟動Service。

發佈留言