Android Frameworks系列(一) startService啟動
之前寫過一篇從AIDL看Android跨程式通訊 從Java層次去分析AIDL執行的原理,當時主要是為了學習Binder機制而寫的,但是Binder機制比較複雜,打算過段時間單獨的寫一篇來分析。本篇文章分析startService的啟動過程,也會涉及到使用Binder機制來進行跨程式通訊,但是不會分析Binder機制的細節。不過還是強烈建議大家學習Binder機制,至少要了解Binder的基本架構,Android經常使用Binder來進行跨程式通訊。
在Android中啟動Service和Activity統一由ActivityManagerService(簡稱AMS)管理,AMS在系統啟動時,就已經在ServiceManager中註冊了,存活於system_server程式中。先來了解一下ActivityManagerService相關的類:
從類圖可以看到這是典型的Binder機制,如果使用過AIDL的話,對IBinder,IInterface應該很熟悉。IActivityManager繼承自IInterface,是用來管理Activity和Service的介面。ActivityManagerProxy從名字可以看出其是代理,並且是AMS在普通應用程式中的代理,通過它可以使用AMS的功能。ActivityManagerNative則可以看做AMS和Binder之間的中介,這樣AMS就可以通過它向客戶端提供服務了。
一 :從客戶程式啟動Service
我們還是使用從AIDL看Android跨程式通訊 中的例子,從MainActivity來呼叫startService,一步一步分析:
1.1 ContextWrapper.java
@Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
這裡的mBase實際是ContextImpl的例項,所以接著看
1.2 ContextImpl.java
/frameworks/base/core/java/android/app/ContextImpl.java
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, mUser);
}
...省略...
private ComponentName startServiceCommon(Intent service, UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), 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());
}
}
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
在startServiceCommon()方法中首先驗證intent是否合法,然後重點看第11~13行。想要繼續跟下去就得先搞清楚ActivityManagerNative.getDefault()
是個什麼鬼。
1.3 ActivityManagerNative.java
/frameworks/base/core/java/android/app/ActivityManagerNative.java
/**
* Cast a Binder object into an activity manager interface, generating
* a proxy if needed.
*/
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ActivityManagerProxy(obj);
}
/**
* Retrieve the system's default/global activity manager.
*/
static public IActivityManager getDefault() {
return gDefault.get();
}
...省略...
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
第22行,將會回撥Singleton的create()方法,對應28~38行程式碼,第29行通過ServiceManager.getService("activity")
可以獲取一個IBinder,AMS在系統啟動的時候已經在ServiceManager中註冊過,這裡我們只用知道通過這個IBinder物件(具體是BinderProxy物件)我們可以發起遠端呼叫。通過第15行生成了一個ActivityManagerProxy並且將其作為單例儲存起來,下次呼叫可以直接使用了。
![這裡寫圖片描述]
上圖也可以印證我們的分析。ActivityManagerNative.getDefault()
返回的是ActivityManagerProxy例項,那麼1.2中將會呼叫ActivityManagerProxy.startService()方法。
1.4 ActivityManagerProxy.java
該類是在ActivityMangerNative中宣告。
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, String callingPackage, int userId) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
service.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeString(callingPackage);
data.writeInt(userId);
mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
ComponentName res = ComponentName.readFromParcel(reply);
data.recycle();
reply.recycle();
return res;
}
第12行mRemote是在ActivityManagerProxy的構造方法中賦值的,還記得剛剛new ActivityManagerProxy時傳入了一個IBinder(BinderProxy)嗎?通過它的transact()方法像遠端AMS發起請求。
二 system_server程式中AMS響應
根據Binder機制,ActivityManagerNative的onTransact()方法將會回撥,因為這個方法比較長,我只擷取了響應startService動作的程式碼。
2.1 ActivityManagerNative.java
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
...省略...
case START_SERVICE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
Intent service = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
String callingPackage = data.readString();
int userId = data.readInt();
ComponentName cn = startService(app, service, resolvedType, callingPackage, userId);
reply.writeNoException();
ComponentName.writeToParcel(cn, reply);
return true;
}
...省略...
}
}
第9行,這裡將要涉及到另外一個跨程式通訊,主要是幹什麼的呢,我們知道MainActivity所在程式A通過IActivityManager介面可以呼叫AMS的服務,那麼如果AMS想要訪問程式A的服務該怎麼辦呢,通過這裡的IApplicationThread介面可以做到。下面是相關類圖:
和之前的IActivityManager類似,使用IApplicationThread也是基於Binder架構的,所以它們的結構都很像,所以這裡的ApplicationThreadProxy就是A程式在AMS的一個Binder代理,通過它AMS就可以呼叫A程式的服務。
第14行startService()是IActivityManager介面的方法,因為ActivityManagerNative是一個抽象類,並且AMS繼承了ActivityManagerNative,所以這裡startService()的真正實現在ActivityManagerService中。
2.2 ActivityManagerService.java
/frameworks/base/services/core/java/com/android/server/am
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, 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);
synchronized(this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid, callingPackage, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}
重點看第21,22行
mServices.startServiceLocked(caller, service,resolvedType, callingPid, callingUid, callingPackage, userId);
mServices是ActiveServices的例項,所以將要執行ActiveServices的startServiceLocked()方法,一般帶有Locked字尾的都是需要保證執行緒安全的。
2.3 ActiveServices.java
/frameworks/base/services/core/java/com/android/server/am
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, String callingPackage, final int userId)
throws TransactionTooLargeException {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service
+ " type=" + resolvedType + " args=" + service.getExtras());
final boolean callerFg;
if (caller != null) {
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
if (callerApp == null) {
throw new SecurityException(
"Unable to find app for caller " + caller
+ " (pid=" + Binder.getCallingPid()
+ ") when starting service " + service);
}
callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
} else {
callerFg = true;
}
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false);
if (res == null) {
return null;
}
if (res.record == null) {
return new ComponentName("!", res.permission != null
? res.permission : "private to package");
}
ServiceRecord r = res.record;
if (!mAm.mUserController.exists(r.userId)) {
Slog.w(TAG, "Trying to start service with non-existent user! " + r.userId);
return null;
}
if (!r.startRequested) {
final long token = Binder.clearCallingIdentity();
try {
// Before going further -- if this app is not allowed to run in the
// background, then at this point we aren't going to let it period.
final int allowed = mAm.checkAllowBackgroundLocked(
r.appInfo.uid, r.packageName, callingPid, true);
if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
Slog.w(TAG, "Background start not allowed: service "
+ service + " to " + r.name.flattenToShortString()
+ " from pid=" + callingPid + " uid=" + callingUid
+ " pkg=" + callingPackage);
return null;
}
} finally {
Binder.restoreCallingIdentity(token);
}
}
NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked(
callingUid, r.packageName, service, service.getFlags(), null, r.userId);
// If permissions need a review before any of the app components can run,
// we do not start the service and launch a review activity if the calling app
// is in the foreground passing it a pending intent to start the service when
// review is completed.
if (Build.PERMISSIONS_REVIEW_REQUIRED) {
if (!requestStartTargetPermissionsReviewIfNeededLocked(r, callingPackage,
callingUid, service, callerFg, userId)) {
return null;
}
}
if (unscheduleServiceRestartLocked(r, callingUid, false)) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "START SERVICE WHILE RESTART PENDING: " + r);
}
r.lastActivity = SystemClock.uptimeMillis();
r.startRequested = true;
r.delayedStop = false;
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
service, neededGrants));
final ServiceMap smap = getServiceMap(r.userId);
boolean addToStarting = false;
if (!callerFg && r.app == null
&& mAm.mUserController.hasStartedUserState(r.userId)) {
ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);
if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) {
// If this is not coming from a foreground caller, then we may want
// to delay the start if there are already other background services
// that are starting. This is to avoid process start spam when lots
// of applications are all handling things like connectivity broadcasts.
// We only do this for cached processes, because otherwise an application
// can have assumptions about calling startService() for a service to run
// in its own process, and for that process to not be killed before the
// service is started. This is especially the case for receivers, which
// may start a service in onReceive() to do some additional work and have
// initialized some global state as part of that.
if (DEBUG_DELAYED_SERVICE) Slog.v(TAG_SERVICE, "Potential start delay of "
+ r + " in " + proc);
if (r.delayed) {
// This service is already scheduled for a delayed start; just leave
// it still waiting.
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Continuing to delay: " + r);
return r.name;
}
if (smap.mStartingBackground.size() >= mMaxStartingBackground) {
// Something else is starting, delay!
Slog.i(TAG_SERVICE, "Delaying start of: " + r);
smap.mDelayedStartList.add(r);
r.delayed = true;
return r.name;
}
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Not delaying: " + r);
addToStarting = true;
} else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) {
// We slightly loosen when we will enqueue this new service as a background
// starting service we are waiting for, to also include processes that are
// currently running other services or receivers.
addToStarting = true;
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
"Not delaying, but counting as bg: " + r);
} else if (DEBUG_DELAYED_STARTS) {
StringBuilder sb = new StringBuilder(128);
sb.append("Not potential delay (state=").append(proc.curProcState)
.append(' ').append(proc.adjType);
String reason = proc.makeAdjReason();
if (reason != null) {
sb.append(' ');
sb.append(reason);
}
sb.append("): ");
sb.append(r.toString());
Slog.v(TAG_SERVICE, sb.toString());
}
} else if (DEBUG_DELAYED_STARTS) {
if (callerFg) {
Slog.v(TAG_SERVICE, "Not potential delay (callerFg=" + callerFg + " uid="
+ callingUid + " pid=" + callingPid + "): " + r);
} else if (r.app != null) {
Slog.v(TAG_SERVICE, "Not potential delay (cur app=" + r.app + "): " + r);
} else {
Slog.v(TAG_SERVICE,
"Not potential delay (user " + r.userId + " not started): " + r);
}
}
return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
}
這個方法比較長,為了方便分析,先把介紹一下方法的引數:
caller:IApplicationThread型別,這裡具體是ApplicationThreadProxy型別,通過它可以和應用程式進行通訊。
service:Intent型別,主要包含了將要啟動service的資訊
resolvedType:String 型別,這裡為null
callingPid:發起call的程式的pid
callingUid:發起call程式的uid
callingPackage:發起call程式的package資訊
userId:這裡為0
如圖:
第22、23行程式碼主要是檢索服務資訊,可以獲取到ServiceRecord和相應的許可權資訊。84~145行主要是對非前臺程式的排程。最終會呼叫第147行startServiceInnerLocked()方法。
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
ServiceState stracker = r.getTracker();
if (stracker != null) {
stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
}
r.callStart = false;
synchronized (r.stats.getBatteryStats()) {
r.stats.startRunningLocked();
}
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
if (error != null) {
return new ComponentName("!!", error);
}
if (r.startRequested && addToStarting) {
boolean first = smap.mStartingBackground.size() == 0;
smap.mStartingBackground.add(r);
r.startingBgTimeout = SystemClock.uptimeMillis() + BG_START_TIMEOUT;
if (DEBUG_DELAYED_SERVICE) {
RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r, here);
} else if (DEBUG_DELAYED_STARTS) {
Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r);
}
if (first) {
smap.rescheduleDelayedStarts();
}
} else if (callerFg) {
smap.ensureNotStartingBackground(r);
}
return r.name;
}
第11行程式碼會呼叫bringUpServiceLocked(),從名字可以看出,這裡應該會生成目標Service,並且會判斷目標Service的程式是否存在,如果存在則直接去生成,如果不存在,則從Zygote fork一個程式,然後在生成相應的Service例項。
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
//Slog.i(TAG, "Bring up service:");
//r.dump(" ");
if (r.app != null && r.app.thread != null) {
sendServiceArgsLocked(r, execInFg, false);
return null;
}
if (!whileRestarting && r.restartDelay > 0) {
// If waiting for a restart, then do nothing.
return null;
}
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing up " + r + " " + r.intent);
// We are now bringing the service up, so no longer in the
// restarting state.
if (mRestartingServices.remove(r)) {
r.resetRestartCounter();
clearRestartingIfNeededLocked(r);
}
// Make sure this service is no longer considered delayed, we are starting it now.
if (r.delayed) {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (bring up): " + r);
getServiceMap(r.userId).mDelayedStartList.remove(r);
r.delayed = false;
}
// Make sure that the user who owns this service is started. If not,
// we don't want to allow it to run.
if (!mAm.mUserController.hasStartedUserState(r.userId)) {
String msg = "Unable to launch app "
+ r.appInfo.packageName + "/"
+ r.appInfo.uid + " for service "
+ r.intent.getIntent() + ": user " + r.userId + " is stopped";
Slog.w(TAG, msg);
bringDownServiceLocked(r);
return msg;
}
// 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);
}
final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
final String procName = r.processName;
ProcessRecord app;
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
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.versionCode, mAm.mProcessStats);
realStartServiceLocked(r, app, execInFg);
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortName, e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
} 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 && !permissionsReviewRequired) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
"service", r.name, 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;
}
}
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
if (r.delayedStop) {
// Oh and hey we've already been asked to stop!
r.delayedStop = false;
if (r.startRequested) {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
"Applying delayed stop (in bring up): " + r);
stopServiceLocked(r);
}
}
return null;
}
程式會執行到第60行會獲取目標程式的資訊,63行會判斷程式是否存在,如果存在直接會執行第66行realStartServiceLocked(從方法名可以看出真正的啟動Service應該就在這個方法中)方法,並返回。如果不存在則會執行到第89行的mAm.startProcessLocked方法,這裡的mAm是AMS的例項,所以程式會回到AMS的startProcessLocked方法。通過分析我們驗證了之前的判斷。並且還可以預測,將來在目標程式生成之後,還是會呼叫realStartServiceLocked方法去生成Service。
三 AMS通知Zygote孵化目標程式
根據之前的分析,到這一步,AMS將會通知Zygote去孵化目標程式。這個過程也是一個跨程式的通訊,但是並不是Binder去實現的,而是使用的Socket,Zygote孵化程式將來也會去寫一篇文章去分析,這裡只用知道通過其生成了一個目標程式。目標程式又會通過Binder向system_server程式發起attachApplication請求。那麼此時又會回撥到AMS的attachApplication方法。
四 AMS通知目標程式建立並啟動Service
4.1 ActivityManagerService.java
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
基於第三節的分析,在Zygote孵化目標程式成功後,目標程式會通過Binder請求呼叫attachApplication服務,所以用呼叫上邊的程式碼。第6行程式碼會接著呼叫attachApplicationLocked(之前已經說過方法名帶Locked一般表示執行緒安全)方法,由於這個方法比較長,由於篇幅限制,我只擷取最重要的一部分
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
...省略...
boolean badApp = false;
boolean didSomething = false;
// See if the top visible activity is waiting to run in this process...
if (normalMode) {
try {
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
// Find any services that should be running in this process...
if (!badApp) {
try {
didSomething |= mServices.attachApplicationLocked(app, processName);
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
badApp = true;
}
}
...省略...
}
第22行 mServices.attachApplicationLocked(),mServices我們已經遇到過了,就是ActiveServices,那麼又會執行其對應的方法。
4.2 ActiveServices.java
boolean attachApplicationLocked(ProcessRecord proc, String processName)
throws RemoteException {
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--;
proc.addPackage(sr.appInfo.packageName, sr.appInfo.versionCode,
mAm.mProcessStats);
realStartServiceLocked(sr, proc, sr.createdFromFg);
didSomething = true;
if (!isServiceNeeded(sr, false, false)) {
// We were waiting for this service to start, but it is actually no
// longer needed. This could happen because bringDownServiceIfNeeded
// won't bring down a service that is pending... so now the pending
// is done, so let's drop it.
bringDownServiceLocked(sr);
}
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting service "
+ sr.shortName, e);
throw e;
}
}
// Also, if there are any services that are waiting to restart and
// would run in this process, now is a good time to start them. It would
// be weird to bring up the process but arbitrarily not let the services
// run at this point just because their restart time hasn't come up.
if (mRestartingServices.size() > 0) {
ServiceRecord sr;
for (int i=0; i<mRestartingServices.size(); i++) {
sr = mRestartingServices.get(i);
if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
|| !processName.equals(sr.processName))) {
continue;
}
mAm.mHandler.removeCallbacks(sr.restarter);
mAm.mHandler.post(sr.restarter);
}
}
return didSomething;
}
第19行realStartServiceLocked(sr, proc, sr.createdFromFg);還記得麼,在第二節最後,我們分析了孵化目標程式後,最後還是會執行realStartServiceLocked,在這裡得到了印證。
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) 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);
r.app = app;
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
final boolean newService = app.services.add(r);
bumpServiceExecutingLocked(r, execInFg, "create");
mAm.updateLruProcessLocked(app, false, null);
mAm.updateOomAdjLocked();
boolean created = false;
try {
if (LOG_SERVICE_START_STOP) {
String nameTerm;
int lastPeriod = r.shortName.lastIndexOf('.');
nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName;
EventLogTags.writeAmCreateService(
r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
}
synchronized (r.stats.getBatteryStats()) {
r.stats.startLaunchedLocked();
}
mAm.notifyPackageUse(r.serviceInfo.packageName,
PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
r.postNotification();
created = true;
} catch (DeadObjectException e) {
Slog.w(TAG, "Application dead when creating service " + r);
mAm.appDiedLocked(app);
throw e;
} finally {
if (!created) {
// Keep the executeNesting count accurate.
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying);
// Cleanup.
if (newService) {
app.services.remove(r);
r.app = null;
}
// Retry.
if (!inDestroying) {
scheduleServiceRestartLocked(r, false);
}
}
}
if (r.whitelistManager) {
app.whitelistManager = true;
}
requestServiceBindingsLocked(r, execInFg);
updateServiceClientActivitiesLocked(app, null, true);
// 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));
}
sendServiceArgsLocked(r, execInFg, true);
if (r.delayed) {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r);
getServiceMap(r.userId).mDelayedStartList.remove(r);
r.delayed = false;
}
if (r.delayedStop) {
// Oh and hey we've already been asked to stop!
r.delayedStop = false;
if (r.startRequested) {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
"Applying delayed stop (from start): " + r);
stopServiceLocked(r);
}
}
}
這裡主要看32~34行 app.thread.scheduleCreateService()其中app.thread是IApplicationThread,可見這裡是system_server程式需要呼叫目標程式scheduleCreateService,那麼在第二節分析,其實IApplicationThread的具體實現也就是ApplicationThreadProxy,通過它發起Binder通訊。
4.3 ApplicationThreadProxy.java
public final void scheduleCreateService(IBinder token, ServiceInfo info,
CompatibilityInfo compatInfo, int processState) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(token);
info.writeToParcel(data, 0);
compatInfo.writeToParcel(data, 0);
data.writeInt(processState);
try {
mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
} catch (TransactionTooLargeException e) {
Log.e("CREATE_SERVICE", "Binder failure starting service; service=" + info);
throw e;
}
data.recycle();
}
第10~11行,發起遠端Binder通訊,標識為SCHEDULE_CREATE_SERVICE_TRANSACTION,通過binder機制,最終將在ApplicationThreadNative的onTransact中響應。
4.4 ApplicationThreadNative.java
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
......
case SCHEDULE_CREATE_SERVICE_TRANSACTION: {
data.enforceInterface(IApplicationThread.descriptor);
IBinder token = data.readStrongBinder();
ServiceInfo info = ServiceInfo.CREATOR.createFromParcel(data);
CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data);
int processState = data.readInt();
scheduleCreateService(token, info, compatInfo, processState);
return true;
}
......
}
return super.onTransact(code, data, reply, flags);
}
第12行scheduleCreateService方法,真正的實現是在ApplicationThread,原因是ApplicationThreadNative是個抽象類,ApplicationThread是其實現類。
4.5 ActivityThread::ApplicationThread.java
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);
}
第9行,sendMessage()傳送了一個tag為H.CREATE_SERVICE的訊息,這裡H類繼承自Handler,是ActivityThread中的內部類,主要用於處理各種訊息
4.6 ActivityThread::H.java
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);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
}
}
第5行,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);
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,
ActivityManagerNative.getDefault());
service.onCreate();
mServices.put(data.token, service);
try {
ActivityManagerNative.getDefault().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);
}
}
}
第6~7行獲取apk的資訊,包括路徑,包名。
第10~11行通過ClassLoader將對應名字的Service載入到記憶體中來,這樣就獲取到了Service的物件。
第23~24行獲取ContextImpl物件。
第26行獲取Application物件。
第27~28行通過attach方法將contextImpl,Application與Service物件關聯起來。
第29行呼叫onCreate方法,一般我們在使用Service時會重寫該方法。這裡Service的生命週期就開始了。
第32~33行通過IActivityManager通知AMS 我們需要的Service已經啟動了。
上述整個啟動過程的時序圖:
相關文章
- 圖解 Android 系列(一)揭祕 Android 系統啟動過程圖解Android
- Android LocationManagerService啟動(一)Android
- Android App應用啟動流程(一)AndroidAPP
- android app 啟動第一個頁面AndroidAPP
- Android啟動模式Android模式
- Android 8.0 原始碼分析 (一) SystemServer 程式啟動Android原始碼Server
- 擼擼Android的羊毛(一)----Activity啟動模式Android模式
- 梳理一下Android 系統啟動流程Android
- KDE Frameworks 5.55 釋出Framework
- FlutterEngin啟動流程&androidFlutterAndroid
- Android ContentProvider 啟動分析AndroidIDE
- JVM系列(一):jvm啟動過程速覽JVM
- Android系統啟動自動開啟mtklogAndroid
- Android效能優化筆記(一)——啟動優化Android優化筆記
- Flutter Android端啟動白屏FlutterAndroid
- Android APP 冷啟動流程AndroidAPP
- Android 系統啟動流程Android
- Android 9.0 init 啟動流程Android
- Android 應用啟動流程Android
- Android App啟動過程AndroidAPP
- Android四種啟動模式Android模式
- 【android 7.1.2】系統啟動Android
- Android效能優化之啟動過程(冷啟動和熱啟動)Android優化
- SpringBoot 系列-啟動過程Spring Boot
- Spring容器系列-啟動原理Spring
- 原創:Android怎麼讓一個service開機自動啟動Android
- React Native Android 啟動異常React NativeAndroid
- Android-Activity的啟動模式Android模式
- Android開機自啟動程式Android
- Android應用啟動流程分析Android
- Android Architecture Components 系列一(初識)Android
- Android全面屏啟動頁適配的一些坑Android
- (連載)Android 8.0 : 系統啟動流程之init程式(一)Android
- Android系統啟動流程(四)Launcher啟動過程與系統啟動流程Android
- 深入理解Android 之 Activity啟動流程(Android 10)Android
- Oracle叢集技術 | 叢集的自啟動系列(一)Oracle
- 詳解Tomcat系列(一)-從原始碼分析Tomcat的啟動Tomcat原始碼
- 純Swift專案-JSON(Basic.frameworks)SwiftJSONFramework
- Android Activity啟動流程原始碼分析Android原始碼