咱們熟知通常 Android 工程師都是在應用層上開發,不會涉及系統源碼,可是若是你想往底層發展,或者深刻插件化、Framework 系統層等開發工做,若是不瞭解 Android 源碼但是不行的,那麼接下來我基於本身的理解跟學習來記錄跟 Android 開發息息相關的源碼分析,大概從 Android 中的 SystemServer 啓動、四大組件啓動、AMS、PMS 等幾個維度來介紹,下面是個人計劃,固然在將來也有可能改變。java
尚未關注的小夥伴,能夠先關注一波,系列文章會持續更新。android
Android 8.0 源碼分析 (一) SystemServer 進程啓動緩存
Android 8.0 源碼分析 (二) Launcher 啓動app
Android 8.0 源碼分析 (三) 應用程序進程建立到應用程序啓動的過程async
Android 8.0 源碼分析 (四) Activity 啓動ide
Android 8.0 源碼分析 (五) Service 啓動函數
Android 8.0 源碼分析 (六) BroadcastReceiver 啓動源碼分析
Android 8.0 源碼分析 (七) ContentProvider 啓動post
上一篇文章咱們講解了 Activity 的啓動,那麼這一篇將爲你們分析四大組件中的 Service 的 startService 和 bindService 啓動原理。在實際開發中,運用 Service 組件有不少場景,好比,後臺播放音樂,後臺下載文件等等,只要你想把些任務邏輯放在後臺執行的,那麼均可以開啓一個服務。在如今這個開發環境中,會運用 Service 可不行,得懂點內部運行原理才行,好了,廢話很少說了,下面先來分析 startService。學習
下面先看一張在 Activity 中調用 startService 的時序圖
當咱們在 Activity 中調用 startActivity 函數的時候,點擊 startActivity 看源碼實現會發現它是在 ContextWrapper 類中實現的。
//ContextWrappaer
Context mBase;
@Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
複製代碼
那麼 ContextWrapper 是什麼呢?下面咱們以一張圖片看下它的繼承關係
經過上面的層級,能明白了吧,咱們繼續看 Context 的 startService 實現,代碼以下:
//Context.java
public abstract class Context {
...
@Nullable
public abstract ComponentName startService(Intent service);
...
}
複製代碼
經過上面代碼能夠看到 Context 是一個抽象類,那麼它具體實現是哪一個類?在上一篇文章咱們介紹了 Activity 的啓動,那麼在啓動的時候,就會建立 Context ,注意看下面代碼,以下:
//ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
/** * 1. 經過封裝啓動 Activity 信息類 ActivityClientRecord 來獲取到 ActivityInfo */
ActivityInfo aInfo = r.activityInfo;
/** * 2. 若是 r.packageInfo == null 就獲取 LoadedApk 實例 */
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
/** * 3. 經過封裝啓動 Activity 信息類 ActivityClientRecord 來獲取啓動 Activity 組件的 ComponentName */
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
/** * 4. 建立Activity 中的上下文環境 */
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
/** * 拿到當前上下文加載的 ClassLoader 加載器 */
java.lang.ClassLoader cl = appContext.getClassLoader();
/** * 5. 調用 Instrumentation.newActivity 函數 ,內部經過 ClassLoader 類加載器來建立 Activity 的實例 */
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
...
}
try {
/** * 6. 獲得 Application 對象 */
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
....
/** * 7. 將 appContext 等對象依附在 Activity 的 attach 函數中,進行 Activity attach 初始化 */
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback);
...
return activity;
}
複製代碼
經過上面代碼,咱們只關注註釋 4 跟註釋 7,咱們看下注釋 4 的實現,代碼以下:
//ActivityThread.java
private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
...
//1.建立 Activity 的 Context 對象
ContextImpl appContext = ContextImpl.createActivityContext(
this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
...
return appContext;
}
複製代碼
//ContextImpl.java
static ContextImpl createActivityContext(ActivityThread mainThread, LoadedApk packageInfo, ActivityInfo activityInfo, IBinder activityToken, int displayId, Configuration overrideConfiguration) {
...
//2. 實例化 Context 的實現類 ContextImpl
ContextImpl context = new ContextImpl(null, mainThread, packageInfo, activityInfo.splitName,
activityToken, null, 0, classLoader);
...
return context;
}
複製代碼
經過上面代碼咱們知道,最後在 createActivityContext 函數中實例化了 ContextImpl 對象,如今咱們回到 ActivityThread performLaunchActivity 函數的註釋 7 ,代碼以下
//ActivityThread.java
/** * 7. 將 appContext 等對象依附在 Activity 的 attach 函數中,進行 Activity attach 初始化 */
activity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback);
複製代碼
//Activity.java
final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config, String referrer, IVoiceInteractor voiceInteractor, Window window, ActivityConfigCallback activityConfigCallback) {
//調用父類函數
attachBaseContext(context);
....
}
複製代碼
attachBaseContext 是父類函數,代碼以下:
//ContextThemeWrapper
public class ContextThemeWrapper extends ContextWrapper {
...
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(newBase);
}
...
}
複製代碼
繼續調用父類,代碼以下:
public class ContextWrapper extends Context {
Context mBase;
public ContextWrapper(Context base) {
mBase = base;
}
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
//賦值給 Context
mBase = base;
}
複製代碼
到最後咱們看到 Context 的實現類 ContextImpl 賦值給了 ContextWrapper 的成員變量 mBase,如今咱們直接去 ContextImpl 的 startService 看它具體實現,代碼以下:
//ContextImpl
class ContextImpl extends Context {
...
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
/** * 調用內部 startServiceCommon 函數 */
return startServiceCommon(service, false, mUser);
}
...
}
複製代碼
繼續調用內部函數,代碼以下:
//ContextImpl
private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
/** * 調用 AMS 代理的 IActivityManager 的 startService 函數 */
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), requireForeground,
getOpPackageName(), user.getIdentifier());
...
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
複製代碼
在啓動 Activity 源碼講解中,咱們已經見過了這種調用方式,其內部就是經過 aidl 來進行應用進程與 AMS(SystemServer) 進程通訊,最後回調到 AMS 的 startService 函數
調用過程按照老規矩,看看整體時序圖:
經過上一小節咱們知道最後會回到 AMS 的 startService 函數中,那麼咱們直接看 AMS 中的具體實現,代碼以下:
//AMS.java
/** * 這裏是 ContextImpl 經過進程間通訊調用的 * @param caller * @param service * @param resolvedType * @param requireForeground * @param callingPackage * @param userId * @return * @throws TransactionTooLargeException */
@Override
public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, boolean requireForeground, String callingPackage, int userId) throws TransactionTooLargeException {
...
try {
/** * 1. 調用 ActiveService 的 startServiceLocked 函數 */
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}
複製代碼
註釋 1 的代碼具體實現是經過 ActiveService 類調用 startServiceLocked 函數,代碼以下:
//ActiveService.java
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId) throws TransactionTooLargeException {
...
/** * 1. 查找是否有與參數 Service 對應的 ServiceRecord */
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");
}
/** * 2. 經過 ServiceLookupResult 獲得參數 Service 對應的 ServiceRecord ,並傳入到註釋 3 處的 startServiceInnerLocked 中 */
ServiceRecord r = res.record;
...
/** * 3. 調用內部 startServiceInnerLocked 函數 */
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
return cmp;
}
複製代碼
在註釋 1 處的 retrieveServiceLocked 函數會查找是否有與參數 service 對應的 ServiceRecord, 若是沒有找到,就會調用 PMS 去獲取參數 service 對應的 Service 信息,並封裝到 ServiceRecord 中,最後將 ServiceRecord 封裝爲 ServiceLookupResult 返回。其中 ServiceRecord 用於描述一個 Service, 和此前講過的 ActivityRecord 相似,在註釋 2 中將獲得的 ServiceRecord 賦值給註釋 3 ,最後調用內部 startServiceInnerLocked 函數,代碼以下:
//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 函數
//ActiveServices.java
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired) throws TransactionTooLargeException {
....
/** * 1. 獲取 Service 想要在哪一個進程中運行 */
final String procName = r.processName;
String hostingType = "service";
ProcessRecord app;
if (!isolated) {
/** * 2. 將 procname 和 Service 的 uid 傳入到 AMS 的getProcessRecordLocked 函數,查詢是否已經存在了當前啓動的 Service */
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
/** * 3. 若是運行 Service 的應用程序進程已經存在 */
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
/** * 3.1 啓動 Service */
realStartServiceLocked(r, app, execInFg);
return null;
...
}
} else {
...
/** * 4. 若是用來運行的 Service 的應用程序進程不存在 */
if (app == null && !permissionsReviewRequired) {
/** * 5. 建立應用程序進程 */
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingType, 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;
}
....
return null;
}
複製代碼
上面代碼主要邏輯就是經過在 AMS 查詢須要啓動的 Service 所在的進程是否已經存在,若是存在則啓動 Service, 若是不存在就調用 註釋 5 內部函數,建立一個應用程序進程,那麼咱們直接看註釋 3.1 啓動 Service 函數,代碼以下:
//ActiveService.java
private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException {
...
/** * 1. 調用 app.thread 函數,其實就是調用 IApplicationThread 的 scheduleCreateService 函數 */
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
r.postNotification();
created = true;
} catch (DeadObjectException e) {
...
}
複製代碼
這裏的函數若是調用了 scheduleCreateService 說明已經離開了 AMS 進程,那麼 app.thread 究竟是什麼了?它其實就是跟上一篇我們介紹 Activity 啓動模式同樣,app.thread 就是 IApplicationThread 它是一個 aidl 文件,具體實如今 ActivityThread 的非靜態內部類,具體看以下代碼吧:
//ActivityThread.java
public final class ActivityThread {
...
private class ApplicationThread extends IApplicationThread.Stub {
...
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);
}
...
}
複製代碼
這裏調用內部重載函數這裏只需記住 H.CREATE_SERVIC 標記,具體實現代碼以下:
//ActivityThread.java
private void sendMessage(int what, Object obj) {
/** * 1. 繼續調用內部重載函數 what = H.CREATE_SERVIC */
sendMessage(what, obj, 0, 0, false);
}
....
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
/** * 2. 經過 H 的 Handler 將 what = H.CREATE_SERVIC 消息 what 發送出去 */
mH.sendMessage(msg);
}
複製代碼
這裏直接看註釋 2 經過 H 類的 sendMessage 將標誌爲 H.CREATE_SERVIC 發送出去。這裏的 H 類就是繼承的 Handler ,具體實現代碼以下:
//ActivityThread.java
public final class ActivityThread {
//初始化 H 類
final H mH = new H();
/** * H 繼承自 handler 是應用程序進程中主線程的消息管理類 */
private class H extends Handler {
...
public static final int CREATE_SERVICE = 114;
....
public void handleMessage(Message msg) {
...
case CREATE_SERVICE:
//調用 handleCreateService
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
}
}
}
複製代碼
H 的 handleMessage 接收到發送過來的消息,調用 handleCreateService 函數,咱們來看下具體實現:
//ActivityService.java
private void handleCreateService(CreateServiceData data) {
/** * 1. 拿到要啓動 Service 的應用程序的 LoadApk */
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
/** * 2. 拿到類加載器 */
java.lang.ClassLoader cl = packageInfo.getClassLoader();
/** * 3. 建立 Servcie 實例 */
service = (Service) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {
...
}
try {
if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
/** * 4. 建立 Context 實例 */
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
/** * 5. 拿到緩存中的 Application */
Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
/** * 6. 執行 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) {
...
}
}
複製代碼
這個函數裏面的代碼,幾乎每行都很重要,我這裏簡單歸納下,主要經過 ClassLoader 加載 Service 類,與 service 綁定 Application 和 Context 一個是應用級別,一個是服務級別,最後執行 Service 生命週期 onCreate 函數,這樣服務就啓動了,那麼剩下的生命週期就都大同小異,小夥伴感興趣的話,能夠本身翻閱源碼進行查閱,下一小節帶給你們是另外一種方式啓動服務。
下面仍是以一張時序圖先看下 ContextImpl 到 AMS 調用過程:
ContextWrapper 的關係這裏再也不過多講解,若是忘記了能夠看我文章開頭的介紹,咱們直接看 ContextWrapper 類中的 bindService 函數,代碼以下:
//ContextWrapper.java
public class ContextWrapper extends Context {
Context mBase;
...
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
return mBase.bindService(service, conn, flags);
}
...
}
複製代碼
這裏調用方式跟 startService 類似,都是調用 ContextImpl 內部函數,直接看 ContextImpl 的 bindService 函數
//ContextImpl.java
@Override
public boolean bindService(Intent service, ServiceConnection conn, int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
Process.myUserHandle());
}
複製代碼
調用內部重載函數 bindServiceCommon,代碼以下:
//ContextImp.java
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler handler, UserHandle user) {
...
/** * 1. 調用 LoadApk 類型的對象 mPackageInfo 的 getServiceDispatcher 函數,它的主要做用就是將 ServiceConnection 封裝爲 IServiceConncet 類型的對象 sd, 從 IServiceConnection 的名字 * 咱們就能得知它實現了 Binder 機制,這樣 Service 的綁定就支持了跨進程。 */
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
} else {
throw new RuntimeException("Not supported in system context");
}
validateServiceIntent(service);
try {
IBinder token = getActivityToken();
if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
&& mPackageInfo.getApplicationInfo().targetSdkVersion
< android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
flags |= BIND_WAIVE_PRIORITY;
}
service.prepareToLeaveProcess(this);
/** * 2. 得到 AMS 的代理,調用 bindService 函數,將會傳遞到 AMS 中 */
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();
}
}
複製代碼
這裏咱們直接看核心代碼 調用 IActivityManager 的 bindService 函數,最終也仍是會回到 AMS 中 bindService 函數,下一小節將詳細介紹:
收到 ContextImp 向 AMS 發送過來的 bindService 請求,具體代碼以下:
//AMS.java
/** * 經過 ContextImpl 調用,中間進程間通訊傳遞過來的 * @param caller * @param token * @param service * @param resolvedType * @param connection * @param flags * @param callingPackage * @param userId * @return * @throws TransactionTooLargeException */
public int bindService(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, String callingPackage, int userId) throws TransactionTooLargeException {
...
synchronized(this) {
//調用 ActiveService 的 bindServiceLocked 函數
return mServices.bindServiceLocked(caller, token, service,
resolvedType, connection, flags, callingPackage, userId);
}
}
複製代碼
回調到 AMS 的 bindService 函數中,內部又調用 ActiveService 的 bindServiceLocked 函數進行傳遞,這裏能夠看到 ActiveService 不論是 start 仍是 bind 最後都是在 ActiveService 中處理 Service 的啓動邏輯。下面調用代碼以下:
//ActiveServie.java
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, final IServiceConnection connection, int flags, String callingPackage, final int userId) throws TransactionTooLargeException {
....
/** * 1. 調用 ServiceRecord 的 retrieveAppBindingLocked 函數來獲取 AppBindRecord , * retrieveAppBindingLocked 函數內部建立 IntentBindRecord ,並對 IntentBindRecord 的成員變量進行賦值。 */
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent);
IBinder binder = connection.asBinder();
...
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
/** * 2. 在 bringUpServiceLocked 函數的內部中調用了 realStartServiceLocked 函數,最終由 ActivityThread 來調用 Service 的 onCreate 函數啓動 Service. */
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}
....
/** * 3. 表示 Server 已經運行,其中 s 是 ServiceRecord 對象,app 是 ProcessRecord 類型對象,b.intent.received 表示當前應用程序進程已經接收到綁定服務的 Service 是返回回來的 Binder, */
if (s.app != null && b.intent.received) {
// Service is already running, so we can immediately
// publish the connection.
try {
/** * 4. 調用 IServiceConnect 的connected 函數,具體實如今 @see ServiceDispatcher.InnerConnection, */
c.conn.connected(s.name, b.intent.binder, false);
} catch (Exception e) {
...
}
/** * 5. 若是當前應用程序進程是第一個與 Service 進行綁定的,而且 Service 已經調用過 onUnBind 函數,則須要調用註釋 6 */
if (b.intent.apps.size() == 1 && b.intent.doRebind) {
/** * 6. 調用內部 requestServiceBindingLocked 函數 */
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
} else if (!b.intent.requested) {//7. 若是應用程序進程的 Client 端沒有發送過綁定 Service 的請求,則會調用註釋 8
/** * 8.表示不是從新綁定 */
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
getServiceMapLocked(s.userId).ensureNotStartingBackgroundLocked(s);
} finally {
Binder.restoreCallingIdentity(origId);
}
return 1;
}
複製代碼
當前函數中的處理邏輯比較多,涉及到了與 Service 相關的幾個對象,這裏先說明下;
這裏就不在介紹上面代碼具體意思了,每一步都標註了詳細註釋,這裏提一下上面註釋 2 ,這裏內部會調用 onCreate 步驟跟 startService 同樣,而後咱們看註釋 6 若是當前應用程序進程是第一個與 Service 進行綁定的,而且 Service 已經調用過 onUnBind 函數。代碼以下:
//ActiveServices.java
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i, boolean execInFg, boolean rebind) throws TransactionTooLargeException {
if (r.app == null || r.app.thread == null) {
// If service is not currently running, can't yet bind.
return false;
}
if (DEBUG_SERVICE) Slog.d(TAG_SERVICE, "requestBind " + i + ": requested=" + i.requested
+ " rebind=" + rebind);
/** * 1. i.requested 表示是否發送過綁定的請求,這裏上上一步知道是發送過的,由於 爲 false, rebind 爲true ,因此前面爲 true, * i.apps.size() 其中 i 是 IntentBindRecord 對象,AMS 會爲每一個綁定 Service 的Intent 分配一個 IntentBindRecord 類型的對象。 */
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
bumpServiceExecutingLocked(r, execInFg, "bind");
r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
//2. 調用 IApplicationThread 對象
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) {
...
throw e;
} catch (RemoteException e) {
...
return false;
}
}
return true;
}
複製代碼
根據上面代碼,最後會調用註釋 2 ,經過 IApplicationThread 與 ActivityThread 應用程序進程通訊,代碼以下:
//ActivityThread#ApplicationThread.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;
...
//1.
sendMessage(H.BIND_SERVICE, s);
}
複製代碼
調用內部函數:
//ActivityThread.java
private void sendMessage(int what, Object obj) {
/** * 繼續調用內部重載函數 what = H.LAUNCH_ACTIVITY */
sendMessage(what, obj, 0, 0, false);
}
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
/** * 2. 經過 H 的 Handler 將 what = H.LAUNCH_ACTIVITY 消息 what 發送出去 */
mH.sendMessage(msg);
}
複製代碼
這裏跟 startService 同樣最後都是 經過 H 來通知bindService,下面代碼以下:
//ActivityThread.java
//ActivityThread.java
public final class ActivityThread {
//初始化 H 類
final H mH = new H();
/** * H 繼承自 handler 是應用程序進程中主線程的消息管理類 */
private class H extends Handler {
...
public static final int CREATE_SERVICE = 114;
....
public void handleMessage(Message msg) {
...
case BIND_SERVICE:
//調用 handleBindService
handleBindService((BindServiceData)msg.obj);
break;
...
}
}
}
複製代碼
接下來咱們看 handleUnbindService 函數具體實現:
//ActivityThread.java
private void handleBindService(BindServiceData data) {
/** * 1. 獲取須要綁定的 Service */
Service s = mServices.get(data.token);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
try {
/** * 2.沒有通過綁定 */
if (!data.rebind) {
/** * 3. 調動 Service 生命週期 onBind 函數 */
IBinder binder = s.onBind(data.intent);
/** * 4. 調用 AMS 的 publishService 函數 */
ActivityManager.getService().publishService(
data.token, data.intent, binder);
} else {
/** * 5.若是已經通過綁定調用 onRebind 生命週期函數 */
s.onRebind(data.intent);
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
ensureJitEnabled();
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} catch (Exception e) {
...
}
}
}
複製代碼
這一步算是對 Service 進行開始執行生命週期函數了,若是 data.rebind 爲 false 那麼說明沒有綁定,執行 s.onBind(data.intent); 生命週期函數,下面咱們來看註釋 4 調用 AMS 的 publishService ,代碼以下:
//AMS.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");
}
mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}
}
複製代碼
內部調用 ActiveServices 的 publishServiceLocked 函數
//ActiveServices.java
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
final long origId = Binder.clearCallingIdentity();
try {
...
if (r != null) {
Intent.FilterComparison filter
= new Intent.FilterComparison(intent);
IntentBindRecord b = r.bindings.get(filter);
...
for (int conni=r.connections.size()-1; conni>=0; conni--) {
ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
for (int i=0; i<clist.size(); i++) {
ConnectionRecord c = clist.get(i);
.....
try {
//1.
c.conn.connected(r.name, service, false);
} catch (Exception e) {
...
}
}
}
}
serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
複製代碼
在註釋1 處調用了 ServiceDispatcher 類型的 sd 對象的 connected 函數,代碼以下:
//LoadedApk.java
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);
}
}
複製代碼
這裏首先經過進程間通訊 AMS 發到 InnerConnection 的 connected 函數,而後調用 LoadedApk 的 connected 函數,最後執行 註釋 2 的 post 函數, 代碼以下:
//LoadedApk.java
private final class RunConnection implements Runnable {
RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
mName = name;
...
}
public void run() {
if (mCommand == 0) {
doConnected(mName, mService, mDead);
} else if (mCommand == 1) {
doDeath(mName, mService);
}
}
}
複製代碼
調用 doConnected 函數,代碼以下:
public void doConnected(ComponentName name, IBinder service, boolean dead) {
ServiceDispatcher.ConnectionInfo old;
ServiceDispatcher.ConnectionInfo info;
synchronized (this) {
...
// If there was an old service, it is now disconnected.
if (old != null) {
mConnection.onServiceDisconnected(name);
}
if (dead) {
mConnection.onBindingDied(name);
}
// If there is a new service, it is now connected.
if (service != null) {
/** * 1. 調用了 ServiceConnection 類型的對象 mConnection 的 onServiceConnected 函數,這樣在客戶端實現了 ServiceConnection 接口,那麼就會被執行。 */
mConnection.onServiceConnected(name, service);
}
}
複製代碼
經過上面代碼的註釋 1 咱們知道,只要客戶端經過以下代碼綁定,那麼就會回調到 onServiceConnected 回調,
bindService(new Intent(XXXX,XXXX), new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG,"綁定成功");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG,"綁定失敗,或者取消綁定");
}
})
複製代碼
至此,整個 bindService 過程就分析完成。最後給出一個 AMS 到 ServiceConnection 時序圖。
這裏咱們能夠分爲 3 個階段來進行服務的綁定,下面仍是以一張圖來表述(ps: 這裏給處較難的 bindService 大概流程)。