轉載請標明出處:【顧林海的博客】
本篇文章已授權微信公衆號 顧林海 獨家發佈
Service啓動方式有兩種,一種是通過Context的startService啓動Service,另一種是通過Context的bindService綁定Service,下面對這兩種啓動方式的啓動流程進行詳細的講解。
startService的啓動流程
通過startService方法啓動Service會調用ContextWrapper的startService方法,如下所示:
//路徑:/frameworks/base/core/java/android/content/ContextWrapper.java
public class ContextWrapper extends Context {
Context mBase;
...
@Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
...
}
在ContextWrapper的startService方法中調用mBase的startService方法,mBase的類型是Context,而Context是一個抽象類,內部定義了很多方法以及靜態常量,它的具體實現類是ContextImpl,進入ContextImpl的startService方法:
//路徑:/frameworks/base/core/java/android/app/ContextImpl.java
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}
ContextImpl的startService方法中又調用了startServiceCommon方法:
//路徑:/frameworks/base/core/java/android/app/ContextImpl.java
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
//註釋1
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), requireForeground,
getOpPackageName(), user.getIdentifier());
...
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
註釋1處通過ActivityManager的getService方法獲取ActivityManagerService的代理類IActivityManager,進入ActivityManager的getService方法:
//路徑:/frameworks/base/core/java/android/app/ActivityManager.java
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;
}
};
getService方法通過IActivityManagerSingleton的get方法獲取IActivityManager對象,IActivityManagerSingleton是一個單例類,在create方法中從ServiceManager中獲取一個名叫“activity”的Service引用,同時也是IBinder類型的ActivityManagerService的引用,最後通過IActivityManager.Stub.asInterface方法將它轉換成IActivityManager,看到IActivityManager.Stub.asInterface這段代碼時可以知道這裏採用的是AIDL方式來實現進程間通信,也就是說服務端ActivityManagerService會實現IActivityManager.Stub類並實現相應的方法。
繼續回到ContextImpl的startServiceCommon方法:
//路徑:/frameworks/base/core/java/android/app/ContextImpl.java
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
//註釋1
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), requireForeground,
getOpPackageName(), user.getIdentifier());
...
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
在註釋1處獲取到ActivityManagerService的代理類IActivityManager,接着通過這個代理類向ActivityManagerService發送startActivity的消息。
將上面的知識點進行總結,如下圖所示:
之前的操作是在應用程序進程中進行的,ActivityManagerService屬於SystemServer進程,因此兩者通過Binder通信,進入ActivityManagerService的startService方法:
//路徑:/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 {
...
synchronized(this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res;
try {
//註釋1
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
註釋1處調用mServices的startServiceLocked方法,mServices的類型是ActiveServices,進入ActiveServices的startServiceLocked方法:
//路徑:/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)
throws TransactionTooLargeException {
...
//註釋1
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false);
if (res == null) {
return null;
}
...
//註釋2
ServiceRecord r = res.record;
...
//註釋3
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
return cmp;
}
註釋1處retrieveServiceLocked方法獲取與參數service對應的ServiceRecord,如果沒有對應的就會從PackageManagerService中查找與service對應的Service信息,並封裝成ServiceRecord中,最後將ServiceRecord賦值給ServiceLookupResult的成員變量record,ServiceRecord是一個用於描述Service相關信息的類,在註釋2處將ServiceLookupResult中的成員變量record賦值給r,同時將ServiceRecord作爲參數傳遞給註釋3處的startServiceInnerLocked。
startServiceInnerLocked方法如下所示:
//路徑:/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
...
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
...
return r.name;
}
接着調用bringUpServiceLocked方法,如下所示:
//路徑:/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 {
...
final String procName = r.processName;
String hostingType = "service";
ProcessRecord app;
if (!isolated) {
//註釋1
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
...
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
//註釋2
realStartServiceLocked(r, app, execInFg);
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
...
}
}
} else {
...
}
//註釋3
if (app == null && !permissionsReviewRequired) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingType, r.name, false, isolated, false)) == null) {
...
}
...
}
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
...
return null;
}
啓動Service時會在註釋3處判斷app==null,app的類型是ProcessRecord,用來描述運行的應用程序進程的信息,在註釋1處將Service運行的進程名和uid傳遞給ActivityManagerService的getProcessRecordLocked方法,從而獲取運行Service的應用程序進程信息ProcessRecord,如果用來運行Service的應用程序進程不存在,就會調用ActivityManagerService的startProcessLocked方法來創建對應的應用程序進程;如果用來運行Service的應用程序進程存在,會調用註釋2處的realStartServiceLocked方法。
進入realStartServiceLocked方法:
//路徑:/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
...
try {
...
//註釋1
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
r.postNotification();
created = true;
} catch (DeadObjectException e) {
...
} finally {
...
}
}
註釋2處調用了app.thread的scheduleCreateService方法,app.thread是IApplicationThread類型,它的實現類ActivityThread的內部類ApplicationThread,通過ApplicationThread與應用程序進程進行Binder通信。
進入ApplicationThread的scheduleCreateService方法:
//路徑:/frameworks/base/core/java/android/app/ActivityThread.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);
}
將啓動Service的參數封裝成CreateServiceData對象併發送CREATE_SERVICE消息。
sendMessage方法如下所示:
//路徑:/frameworks/base/core/java/android/app/ActivityThread.java
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
向mH類發送CREATE_SERVICE類型的消息,並將CreateServiceData傳遞過去,mH指的是H,它是ActivityThread的內部類並繼承自Handler,AMS通過IApplicationThread嚮應用程序進程發送消息,接受消息的操作是在應用程序進程的Binder線程池中進行,因此需要Handler來發送消息切換到主線程,查看H的handleMessage方法:
//路徑:/frameworks/base/core/java/android/app/ActivityThread.java
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: " + String.valueOf(msg.obj)));
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
}
...
}
根據消息類型CREATE_SERVICE,調用handleCreateService方法:
//路徑:/frameworks/base/core/java/android/app/ActivityThread.java
private void handleCreateService(CreateServiceData data) {
...
//註釋1
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
//獲取類加載器
java.lang.ClassLoader cl = packageInfo.getClassLoader();
//註釋2
service = (Service) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {
...
}
try {
//註釋3
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
Application app = packageInfo.makeApplication(false, mInstrumentation);
//註釋4
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
//註釋5
service.onCreate();
//註釋6
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) {
...
}
}
註釋1處獲取啓動Service的應用程序的LoadedApk,LoadedApk是一個APK文件的描述類,從中獲取類加載器並在註釋2處加載Service類,在註釋5處調用Service的onCreate方法,Service就被啓動了,同時在註釋6處將啓動的Service加入到ActivityThread的成員變量mServices中。其中註釋3處通過ContextImpl的createAppContext方法創建ContextImpl也就是Service的上下文,並將該ContextImpl傳入註釋2處service的attach方法中,如下所示:
路徑:/frameworks/base/core/java/android/app/Service.java
public final void attach(
Context context,
ActivityThread thread, String className, IBinder token,
Application application, Object activityManager) {
attachBaseContext(context);//註釋1
mThread = thread; // NOTE: unused - remove?
mClassName = className;
mToken = token;
mApplication = application;
mActivityManager = (IActivityManager)activityManager;
mStartCompatibility = getApplicationInfo().targetSdkVersion
< Build.VERSION_CODES.ECLAIR;
}
在註釋1處調用ContextWrapper的attachBaseContext方法,如下所示:
路徑:/frameworks/base/core/java/android/content/ContextWrapper.java
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
Service的ContextImpl最終被賦值給ContextWrapper的成員變量mBase,由於Service繼承自ContextWrapper,因此Service也可以使用Context的方法。
總結如下:
bindService的綁定流程
通過bindService方法綁定Service會調用ContextWrapper的bindService方法,如下所示:
//路徑:/frameworks/base/core/java/android/content/ContextWrapper.java
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
mBase具體實現類是ContextImpl,ContextImpl的bindService方法:
//路徑:/frameworks/base/core/java/android/app/ContextImpl.java
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
Process.myUserHandle());
}
bindService方法又調用了bindServiceCommon方法:
//路徑:/frameworks/base/core/java/android/app/ContextImpl.java
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
//註釋1
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
} else {
throw new RuntimeException("Not supported in system context");
}
validateServiceIntent(service);
try {
...
//註釋2
int res = ActivityManager.getService().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
if (res < 0) {
throw new SecurityException(
"Not allowed to bind to service " + service);
}
return res != 0;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
註釋1處將ServiceConnection封裝成IServiceConnection類型的對象sd,IServiceConnection實現了Binder機制,這樣Service的綁定就支持跨進程通信了,在註釋2處獲取ActivityManagerService的代理類IActivityManager,向ActivityManagerService發送bindService消息。
到這裏總結如下:
ActivityManagerService的bindService方法如下所示:
//路徑:/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
final ActiveServices mServices;
public int bindService(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, IServiceConnection connection, int flags, String callingPackage,
int userId) throws TransactionTooLargeException {
...
synchronized(this) {
return mServices.bindServiceLocked(caller, token, service,
resolvedType, connection, flags, callingPackage, userId);
}
}
最後在同步代碼塊中調用了mServices的bindServiceLocked方法,mServices的類型是ActiveServices,ActiveServices的bindServiceLocked方法如下:
//路徑:/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String callingPackage, final int userId) throws TransactionTooLargeException {
...
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
//註釋1
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}
...
if (s.app != null && b.intent.received) {
...
} else if (!b.intent.requested) {
//註釋2
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
}
註釋1處會調用bringUpServiceLocked方法,最終會調用realStartServiceLocked方法,在該方法中通過ApplicationThread與應用程序進程進行Binder通信,調用ApplicationThread的scheduleCreateService方法以此來創建並啓動Service,關於創建和啓動Service已經在第一部分講過了。
註釋2處當Service沒有綁定時調用requestServiceBindingLocked方法:
//路徑:/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind) throws TransactionTooLargeException {
...
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
bumpServiceExecutingLocked(r, execInFg, "bind");
r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
//註釋1
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.repProcState);
if (!rebind) {
i.requested = true;
}
i.hasBound = true;
i.doRebind = false;
} catch (TransactionTooLargeException e) {
...
} catch (RemoteException e) {
...
}
}
return true;
}
註釋1處,r.app.thread的類型是IApplicationThread,實現類是ActivityThread的內部類ApplicationThread,通過Binder機制調用ApplicationThread的scheduleBindService方法:
//路徑:/frameworks/base/core/java/android/app/ActivityThread.java
public final void scheduleBindService(IBinder token, Intent intent,
boolean rebind, int processState) {
updateProcessState(processState, false);
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());
sendMessage(H.BIND_SERVICE, s);
}
scheduleBindService放中將Service信息封裝成BindServiceData對象,並通過H類發送BIND_SERVICE消息。
//路徑:/frameworks/base/core/java/android/app/ActivityThread.java
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;
...
}
H類在處理BIND_SERVICE消息時調用了handleBindService方法:
//路徑:/frameworks/base/core/java/android/app/ActivityThread.java
private void handleBindService(BindServiceData data) {
//註釋1
Service s = mServices.get(data.token);
...
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
try {
if (!data.rebind) {
//註釋2
IBinder binder = s.onBind(data.intent);
ActivityManager.getService().publishService(
data.token, data.intent, binder);
} else {
...
}
ensureJitEnabled();
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} catch (Exception e) {
...
}
}
}
註釋1處獲取要綁定的Service,註釋2處當Service還沒綁定時調用Service的onBind方法進行綁定並調用ActivityManagerService的publishService方法:
//路徑:/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void publishService(IBinder token, Intent intent, IBinder service) {
...
synchronized(this) {
if (!(token instanceof ServiceRecord)) {
throw new IllegalArgumentException("Invalid service token");
}
mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}
}
進入mServices的publishServiceLocked方法:
//路徑:/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
...
try {
...
if (r != null) {
...
if (b != null && !b.received) {
b.binder = service;
b.requested = true;
b.received = true;
for (int conni=r.connections.size()-1; conni>=0; conni--) {
...
for (int i=0; i<clist.size(); i++) {
...
try {
//註釋1
c.conn.connected(r.name, service, false);
} catch (Exception e) {
...
}
}
}
}
...
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
註釋1處的c.conn的類型是IServiceConnection,它是ServiceConnection在本地的代理,用於解決當前應用程序進程和Service跨進程通信的問題,IServiceConnection的具體實現類是ServiceDispatcher.InnerConnection,ServiceDispatcher是LoadedApk的內部類。ServiceDispatcher.InnerConnection的connected方法如下所示:
//路徑:/frameworks/base/core/java/android/app/LoadedApk.java
static final class ServiceDispatcher {
...
private final Handler mActivityThread;
...
private static class InnerConnection extends IServiceConnection.Stub {
final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
public void connected(ComponentName name, IBinder service, boolean dead)
throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
//註釋1
sd.connected(name, service, dead);
}
}
}
...
public void connected(ComponentName name, IBinder service, boolean dead) {
if (mActivityThread != null) {
//註釋2
mActivityThread.post(new RunConnection(name, service, 0, dead));
} else {
doConnected(name, service, dead);
}
}
...
}
註釋1處獲取ServiceDispatcher類型sd的connected,也是就是調用註釋2處的connected方法,並調用Handler類型的對象mActivityThread的post方法,mActivityThread實際指向的是ActivityThread的內部類H,最終通過H類的post方法將RunConnection對象的內容運行在主線程中,RunConnections是LoadedApk的內部類。代碼如下所示:
//路徑:/frameworks/base/core/java/android/app/LoadedApk.java
private final class RunConnection implements Runnable {
RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
mName = name;
mService = service;
mCommand = command;
mDead = dead;
}
public void run() {
if (mCommand == 0) {
//註釋1
doConnected(mName, mService, mDead);
} else if (mCommand == 1) {
doDeath(mName, mService);
}
}
final ComponentName mName;
final IBinder mService;
final int mCommand;
final boolean mDead;
}
在run方法中調用註釋1處的doConnected方法:
//路徑:/frameworks/base/core/java/android/app/LoadedApk.java
public void doConnected(ComponentName name, IBinder service, boolean dead) {
...
if (service != null) {
//註釋1
mConnection.onServiceConnected(name, service);
}
}
註釋1處調用mConnection的onServiceConnected,mConnection的類型是ServiceConnection,這樣客戶端實現ServiceConnection接口類的onServiceConnected方法就會被調用。
最後總結如下: