Android的四大鑽無論對開發者或是用戶都意義重大,對於用戶來說應用就是Activity,用戶所能看到的和交互的都發生在Activity中,對於開發者來說四大組件更是開發功能個展示功能的基礎和媒介,對於初級開發者每天的工作都在和四大組件打交道,它也成爲初級開發者成長的重要一關,本文就從過年源碼的角度分析下四大組件的啓動過程;
1、Activity啓動過程
Activity是我們打交道最多的組件,也是初學者接觸最早的組件,特的使用範圍和頻率也最多,使用如此頻繁的Activity你究竟瞭解多少呢?下面從源碼的角度一起分析一下Activity的啓動過程,在分析源碼之前先介紹兩個系統服務接口IActivityManager和IApplicationThread,它們都是在服務端只用Binder通信,(關於BinderAndroid進階知識樹——Android 多進程、Binder 你必須知道的一切)具體在本地的兩個代理類如下:
- IApplicationThread
class ApplicationThread extends IApplicationThread.Stub{…...}
- IActivityManager
class ActivityManagerService extends IActivityManager.Stub{……}
由上面的兩個代理類知道,系統中使用AIDL實現客戶端和服務端的通信,介紹這兩個代理類後,這裏先介紹下程序在IActivityManager中如何與IApplicationThread交互的,開發者都知道Android程序的開始會執行ActivityThread.main()方法,在main()中創建了ApplicationThread實例並完成了在Ams中的設置
final ApplicationThread mAppThread = new ApplicationThread(); // 實例化ApplicaitonThread
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);//main()中調用attach()
private void attach(boolean system, long startSeq) {
final IActivityManager mgr = ActivityManager.getService();
mgr.attachApplication(mAppThread, startSeq);
}
在main()方法中調用了attach(),attach()中通過ActivityManager.getService()獲取IActivityManager接口的代理類AMS,然後調用AMS.attachApplication()傳入mAppThread對象;
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
}
}
在attachApplication中調用attachApplicationLocked()傳入thread對象,attachApplicationLocked中調用了ProcessRecord.makeActive()在內部保存thread,這樣AMS中就持有了ApplicationThread中代理的Binder對象;
app.makeActive(thread, mProcessStats); //
public void makeActive(IApplicationThread _thread, ProcessStatsService tracker) {
thread = _thread;
}
上面實現了AMS和ApplicationThread的通信,那下面開始進入Activity的啓動過程分析;
- 執行啓動Activity
startActivity()
Activity的啓動是從一句startActivity()開始的,無論是否使用RequestCode啓動,啓動過程最終都會調用Activity的startActivityForResult()
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
}
}
startActivityForResult()中調用會調用Instrumentation.execStartActivity(),Instrumentation在程序的啓動和Activity的啓動中起着重要的作用,而且在插件化中通過Hook系統中的Instrumentation對象還可以實現更多的功能,本篇指分析和Activity啓動相關的
- execStartActivity()
int result = ActivityManager.getService() //1
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent); //2、檢查Activity的啓動結果
- 註釋1處調用IActivityManager代理類,IActivityManager是系統的服務接口,在此處採用Binder通信,ActivityManager.getService() 獲取到的是它代理實現類ActivityManagerService,然後調用ActivityManagerService.startActivity()方法啓動活動
- 在AMS啓動活動後,調用checkStartActivityResult()檢查啓動結果,會根據具體的失敗原因拋出異常
- ActivityManager.getService():獲取IActivityManager的代理類
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;
}
};
此處參照Android 8.1 源碼,在系統中IActivityManager使用Singleton封裝單例提供,在getService()中通過IActivityManagerSingleton.get()獲取,get()會調用Singleton的create()通過ServiceManager獲取對應的Binder,在根據Binder獲取代理對象即ActivityManagerService對象,到此程序進入AMS中
- AMS中的startActivity()中經過一系列的調用代碼最終執行到ActivityStackSupervisor的realStartActivityLocked(),realStartActivityLocked中調用IApplication接口方法處理LaunchActivity
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);
此處IApplication接口的代理類爲ApplicationThread,也就是方法最終進入ApplicationThread類中,ApplicationThread爲ActivityThread中的內部類,它通過Handler發送消息方式與ActivityThread通信;
@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
ActivityClientRecord r = new ActivityClientRecord();
.......
r.overrideConfig = overrideConfig;
sendMessage(H.LAUNCH_ACTIVITY, r);
}
ApplicationThread中創建ActivityClientRecord對象保存活動信息,然後發送Handler消息,handler消息最終被ActivityThread中的Handler子類H所消耗,在H的handleMessage()中最終調用ActivityThread中startActivityNow()方法;
- ActivityThread的startActivityNow()來啓動Activity
public final Activity startActivityNow(){
ActivityClientRecord record = new ActivityClientRecord()// 1
r.token = token;
r.ident = 0;
r.intent = intent;
r.state = state;
r.parent = parent;
r.embeddedID = id;
r.activityInfo = activityInfo;
r.lastNonConfigurationInstances = lastNonConfigurationInstances;
return performLaunchActivity(r, null);//2
}
在startActivityNow()中,首先創建ActivityClientRecord保存activity啓動信息,然後直接調用performLaunchActivity()啓動活動,performLaunchActivity方法至關重要,Activity的一系列的初始化都在其中完成;
1.1、performLaunchActivity()
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ContextImpl appContext = createBaseContextForActivity(r); //1、
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); //2、調用Instrumentation實例的方法
Application app = r.packageInfo.makeApplication(false, mInstrumentation); //3、創建了Application並調用onCreate()初始化
instrumentation.callApplicationOnCreate(app);
//4
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);
//5
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
r.setState(ON_CREATE);
}
performLaunchActivity()方法中執行了很多我們熟悉的過程:
- . 從ActivityClientRecord中獲取Activity的信息
- . 創的ContextImpl實例並完成與Activity綁定,此處就是Activity中使用的context(詳情見Android插件化——Context機制)
- . 使用ClassLoader並調用Instrumentation.newActivity()中方法創建Activity的實例
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
String pkg = intent != null && intent.getComponent() != null
? intent.getComponent().getPackageName() : null; //獲取Package
return getFactory(pkg).instantiateActivity(cl, className, intent);
}
public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className,
@Nullable Intent intent)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Activity) cl.loadClass(className).newInstance(); //使用classLoader加載Class並創建實例
}
- . 創建Application實例,並調用Application.create()完成成序的初始化
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
appClass = "android.app.Application";
try {
java.lang.ClassLoader cl = getClassLoader();
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication( //調用Instrumentation創建Application
cl, appClass, appContext);
appContext.setOuterContext(app);
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app); //調用application的onCreate()
}
}
return app;
}
在創建Application過程中:
- 賦值appClass指向要執行的類android.app.Application
- 創建Application 中的ContextImpl對象
- 調用mInstrumentation.newApplication()實例化Application,並執行attach()綁定Context
static public Application newApplication(Class<?> clazz, Context context){
Application app = (Application)clazz.newInstance();
app.attach(context);
return app;
}
- 執行Application的onCreate()
- . 調用Activity的attach()完成Window的創建個初始化
- attach()中創建了PhoneWindow 然後setContentView後有初始化DecorView,加載佈局和視圖,詳情點擊Android進階知識樹——Window & ViewRootImpl
- . 調用onCreate()完成Activity的初始化
在執行onCreate方法之後,Activity的啓動就完成了,可此時Activity的內容只是添加到attach()中創建的PhoneWindow中了,但此時的PhoneWindow併爲顯示在界面上,PhoneWindow的真正添加顯示的過程實在處理resume()方法中,詳細點擊查看上面的Window & ViewRootImpl的連接;
2、Service的啓動過程
2.1、 startService():啓動服務
@Override
public ComponentName startService(Intent service) {
return mBase.startService(service); //mBase是ContextImpl的實例
}
startService()中直接調用mBase中的方法,此處的mBase是Activity中的啓動過程中創建的ContextImpl對象,他在執行attach是會和Activity綁定並賦值父類的mBase,所以此處調用的是ContextImpl中的方法
- ContextImpl.startService()
@Override
public ComponentName startForegroundService(Intent service) {
return startServiceCommon(service, true, mUser);
}
private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user) {
try {
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), requireForeground,
getOpPackageName(), user.getIdentifier());
return cn;
}
}
在startService()直接調用startServiceCommon()方法,startServiceCommon中用同樣的方法獲取AMS對象,並調用AMS的startActivity對象,AMS中會繼續調用ActivityServices中的startServiceLocked()創建ServiceRecord記錄服務信息,然後調用startServiceInnerLocked(),startServiceInnerLocked()中又調用bringUpServiceLocked()最終程序執行到realStartServiceLocked()方法中
- realStartServiceLocked()
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
realStartServiceLocked()中用同樣的方法調用IApplication中方法,由上面分析知道執行的是代理類ApplicationThread中的scheduleCreateService()方法,scheduleCreateService中同樣使用Handler機制調用ActivityThread中的放啊
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_SERVICE息後,調用ActivityThread.handleCreateService()
Service service = null;
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance(); (1)
Application app = packageInfo.makeApplication(false, mInstrumentation);(2)
service.attach(context, this, data.info.name, data.token, app,ActivityManager.getService());(3)
service.onCreate();(4)
mServices.put(data.token, service); //緩存當前服務
- handleCreateService做了以下事情,具體細節參照上面Activity中的創建過程:
- 使用類加載器加載類Service並創建Service實例
- 使用Instrumentation創建Application實例,並調用onCreate()初始化
- 創建ContextImpl實例,並通過attach與Service建立聯繫()(詳情見Android插件化——Context機制)
- 調用Service的onCreate()初始化Service
- 使用mServices緩存已經啓動的Service對象
2.2、 Service的參數處理
-
前面只分析了Service 的啓動過程忽略了一些細節,在ActivityServices的realStartServiceLocked()完成啓動後,會調用sendServiceArgsLocked(),在sendServiceArgsLocked()中調用IApplication.scheduleServiceArgs()處理參數,程序最終調用ActivityThread的handleServiceArgs(),從方法名稱就可以看出這裏處理的是服務的請求參數
-
ActivityThread.handleServiceArgs()
Service s = mServices.get(data.token); // 獲取啓動的服務
try {
int res;
if (!data.taskRemoved) {
res = s.onStartCommand(data.args, data.flags, data.startId); // 執行onStartCommand傳入參數信息
} else {
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}
}
在handleServiceArgs()中首先從緩存mServices中獲取啓動的服務,然後調用服務的onStartCommand()傳入參數,到此服務的啓動和傳參過程就執行結束了
2.3、 停止服務
服務的停止過程執行流程個路徑和啓動基本一致,通過ContextImpl、AMS、ApplicationThread最終進入ActivityThread的handleStopService(),handleStopService()中直接衝緩存中獲取對應的服務並調用onDestroy()
private void handleStopService(IBinder token) {
Service s = mServices.remove(token); // 獲取啓動的Service
s.onDestroy();
}
從上面分析Service的啓動過程發現,整個過程和執行的類基本和活動的執行一致,都是通過ContextImpl開始執行操作,經過Binder機制與服務端通信,然後執行服務段的代理AMS類,最後利用IApplication類的代理回到客戶端的ActivityThread類中,再使用Handler機制切回主線程執行真正的操作任務;
2.4、 綁定服務
綁定服務從調用ContextWrapper.bindService()開始,然後調用ContextImpl的bindServiceCommom()方法
- bindServiceCommon()
IServiceConnection sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags); (1)
int res = ActivityManager.getService().bindService( //(2)調用AMS.bindService()
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
//getServiceDispatcher()
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Handler handler, int flags) {
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context); //從緩存中獲取ArrayMap
if (map != null) {
sd = map.get(c); //緩存獲取
}
sd = new ServiceDispatcher(c, context, handler, flags);
if (map == null) {
map = new ArrayMap<>();
mServices.put(context, map); //緩存ArrayMap
}
map.put(c, sd); //以ServiceConnect爲Key保存 sd
return sd.getIServiceConnection(); //返回Sd中保存的InnerConnection實例
}
在bindServiceCommon()中調用getServiceDispatcher()獲取IServiceConnection對象,首先從緩存mServices中獲取換粗的ServicDispatcher實例,如果緩存不存在則創建ServiceDispatcher實例,ServiceDispatcher中會自動創建並保存內部類InnerConnection的實例,InnerConnection其實是IServiceConnection的代理類;
因爲綁定服務可能是跨進程的,所以必須使用跨進程的Binder通信,這裏採用IServiceConnection接口實現,ServiceDispatcher的作用是保存進程通信Binder的代理類InnerConnection和ServiceConnection的對應關係,從而使消息能跨進程傳遞
static final class ServiceDispatcher {
private final ServiceDispatcher.InnerConnection mIServiceConnection;
private final ServiceConnection mConnection; // 內部保存ServiceConnection
private static class InnerConnection extends IServiceConnection.Stub { // 實現IServiceConnection的Binder接口
final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}
}
}
bindServiceCommon除獲取ServiceDispatcher對象外,還執行一下邏輯:
- 以鍵值對的形式保存保存ServiceConnection和ServiceDispatcher的實例在緩存mService中,並返回InnerConnection實例;
- 調用AMS.bindService(),bindService()中又調用ActiveServices.bindServiceLocked()實現服務的啓動,整個啓動過程和上 面一致;
- 在執行服務啓動時,如果此時服務已經在運行,則直接回調綁定方法
int bindServiceLocked(){ // ActiveServices.bindServiceLocked()
if (s.app != null && b.intent.received) { //如果服務已經在運行直接發佈連接成功
c.conn.connected(s.name, b.intent.binder, false);
if (b.intent.apps.size() == 1 && b.intent.doRebind) { //客戶端重新綁定,並要求回調onRebind()
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
} else if (!b.intent.requested) {
requestServiceBindingLocked(s, b.intent, callerFg, false); //客戶端第一次綁定
}
}
- 對於與綁定成功的客戶端回調 c.conn.connected(),此處回調的就是InnerConnection.connected(),對於客戶端是重新綁定的執行requestServiceBindingLocked()方法回調onRebind() ,這裏對重新綁定要符合兩個因素,當前進程目前是第一個綁定此服務的進程,而且要綁定的服務已經執行過onUnBind()方法,換句話說此服務之前被綁定過又被斷開了,目前處於未綁定狀態,下面先看看已經啓動的服務是是如何回調通知綁定結果的:
public void connected(ComponentName name, IBinder service, boolean dead)throws RemoteException {
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service, dead); //調用ServiceDispatcher。connected()
}
}
public void connected(ComponentName name, IBinder service, boolean dead) {
if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0, dead)); //post發送
} else {
doConnected(name, service, dead);//直接調用
}
}
在InnerConnection.connected()方法中調用內部存儲的ServiceDispatcher.connected()方法,根據mActivityThread是否爲空確定直接執行doConnected()還是post(),post()發送Runnable最終還是調用doConnected()
- RunConnection的run()回調LoadedApk.ServiceDispatcher.doConnected()
public void doConnected(ComponentName name, IBinder service, boolean dead) {
synchronized (this) {
old = mActiveConnections.get(name); //(1)
if (service != null) {
try {
service.linkToDeath(info.deathMonitor, 0); /(2)設置死亡監聽,並緩存服務
mActiveConnections.put(name, info);
} catch (RemoteException e) {
mActiveConnections.remove(name);
return;
}
} else {
mActiveConnections.remove(name);
}
if (old != null) {
old.binder.unlinkToDeath(old.deathMonitor, 0); //(3)
}
}
if (old != null) {
mConnection.onServiceDisconnected(name); //(4)
}
if (service != null) {
mConnection.onServiceConnected(name, service); 、、(5)
}
}
在doConnected()中,執行一下邏輯:
- 從已連接的mActiveConnections中獲取之前的連接
- 爲Service設置死亡監聽
- 對老的綁定回掉之前連接的死亡通知,並回掉ServiceConnection斷開連接方法
- 對新的連接回掉連接成功onServiceConnected()通知綁定結果
上面的部分是針對綁定時服務已經啓動的,此時可以直接回調綁定結果,對於服務第一次綁定或重新綁定時,在服務啓動完成之後會調用requestServiceBindingLocked(),requestServiceBindingLocked會調用IApplication接口
- requestServiceBindingLocked
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.repProcState);
- 最終調用ApplicationThread的scheduleBindService()
BindServiceData s = new BindServiceData();
s.token = token;
s.intent = intent;
s.rebind = rebind;
sendMessage(H.BIND_SERVICE, s);
- H中接收消息後,調用ActivityThread.handleBindService(),
Service s = mServices.get(data.token); (1)
if (!data.rebind) {
IBinder binder = s.onBind(data.intent); // 第一次綁定時執行回調onBind()
ActivityManager.getService().publishService(
data.token, data.intent, binder);
} else {
s.onRebind(data.intent); // 重新綁定時執行onReBind()
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
- handleBindService執行以下操作:
- 根據Service的Token取出Service對象,並根據是否爲第一次綁定和重新綁定回調Service的onBind()和onReBind()
- 對第一次綁定的先調用onBinder回去Binder對象,然後調用AMS的publishService(),publishService最終交給ActivityServices.publishServiceLocked()方法
- publishServiceLocked()中遍歷connections集合,獲取其中的ConnectionRecord對象,在ConnectionRecord對象中保存這每個Service對應的IServiceConnecttion對象,最終調用IServiceConnecttion.Stub的實現類InnerConnection中connected()方法(詳情見上面)
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 {
c.conn.connected(r.name, service, false); // 回調ServiceConnection.onServiceConnected()
} catch (Exception e) {
}
}
}
}
2.4、 解除綁定
- ContextImpl.unBindService()
@Override
public void unbindService(ServiceConnection conn) {
if (mPackageInfo != null) {
//(2)
IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(getOuterContext(), conn);
try {
ActivityManager.getService().unbindService(sd); //(3)調用AMS方法
}
}
首先從緩存中獲取此服務對應的IServiceConnection對象,然後調用AMS方法接觸綁定,方法經過上面的流程後最終執行ActivityThread的handleUnbindService(),在handleUnbindService中取出相應的服務,執行Service的onUnbind()
void handleUnbindService(BindServiceData data) {
Service s = mServices.get(data.token); //取出Serice回調onUnbind()
boolean doRebind = s.onUnbind(data.intent); //回調onUnbind()解除綁定
try {
if (doRebind) { //根據返回確定是否重新綁定
ActivityManager.getService().unbindFinished(
data.token, data.intent, doRebind);
} else {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
}
- 死亡代理
在使用綁定服務時,爲了獲取服務的運行狀態和斷開通知,一般會爲服務設置死亡監聽,在服務死亡時會獲取通知及時的做相應的處理,這裏DeathMonitor在收到死亡信號時執行death()
private final class DeathMonitor implements IBinder.DeathRecipient{
DeathMonitor(ComponentName name, IBinder service) {
mName = name;
mService = service;
}
public void binderDied() {
death(mName, mService); //處理death事假
}
final ComponentName mName;
final IBinder mService;
}
- death():在服務死亡時會調用death(),death中又調用SeriviceDiapatcher.doDeath()處理服務的解綁和回調
public void death(ComponentName name, IBinder service) {
if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 1, false));
} else {
doDeath(name, service);
}
}
/處理解除綁定服務
public void doDeath(ComponentName name, IBinder service) {
synchronized (this) {
ConnectionInfo old = mActiveConnections.get(name);
mActiveConnections.remove(name);
old.binder.unlinkToDeath(old.deathMonitor, 0); //移除死亡代理
}
mConnection.onServiceDisconnected(name); //回調斷開連接
}
3、ContentProvider
- 關於ContentProvider使用和源碼啓動過程見Android進階知識樹——ContentProvider使用和工作過程詳解
4、BroadcastReceiver
4.1 註冊廣播
registerBroadCast()
和上面的Activity、Service一樣,registerBroadCast()最終調用ContextImpl的registerBroadCast(),registerBroadCast()中調用registerReceiverInternal()方法
- registerReceiverInternal()
if (receiver != null) {
if (mPackageInfo != null && context != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true); //獲取的是IIntentReceiver實例
} else {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver(); //創建IIntentReceiver實例
}
}
final Intent intent = ActivityManager.getService().registerReceiver( //(2)調用AMS註冊廣播
mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
broadcastPermission, userId, flags);
registerReceiverInternal()中調用getReceiverDispatcher()獲取ReceiverDispatcher的實例,ReceiverDispatcher中封裝者BroadCastReceiver對象和IIntentReceiver的代理類InnerReceiver(和Service原理一致),然後調用AMS中方法完成註冊;
- IIntentReceiver:一個Binder接口,用於進行跨進程的通信,和Service的處理方式相似
LoadedApk.ReceiverDispatcher.InnerReceiver
static final class ReceiverDispatcher {
final static class InnerReceiver extends IIntentReceiver.Stub {
…….
}
}
ActivityManager.getService().registerReceiver()調用的是ActivityManagerService.registerReceiver()
- ActivityManagerService.registerReceiver()
Iterator<String> actions = filter.actionsIterator(); //(1)遍歷IntentFilter中的Action
//(2)獲取當前註冊用戶和所有用戶
int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };
while (actions.hasNext()) {
String action = actions.next(); //獲取每個Action
for (int id : userIds) { //遍歷UserIds
// (3)取出每個用戶所發送過的所有粘性廣播
ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(id);
if (stickies != null) {
ArrayList<Intent> intents = stickies.get(action); //取出這個Action的Intent集合
if (intents != null) {
if (stickyIntents == null) {
stickyIntents = new ArrayList<Intent>();
}
stickyIntents.addAll(intents); //將篩選好的粘性廣播保存在stickyIntents中
}
}
}
}
}
ArrayList<Intent> allSticky = null;
if (stickyIntents != null) {
final ContentResolver resolver = mContext.getContentResolver();
for (int i = 0, N = stickyIntents.size(); i < N; i++) {
Intent intent = stickyIntents.get(i);
if (filter.match(resolver, intent, true, TAG) >= 0) { //精準匹配廣播類型參數
if (allSticky == null) {
allSticky = new ArrayList<Intent>();
}
allSticky.add(intent); //將匹配符合的Intent添加至allSticky中
}
}
}
// 取出allSticky中第一個Intent,準備發送
Intent sticky = allSticky != null ? allSticky.get(0) : null;
上面詳細執行過程見註釋,主要從已發送粘性廣播歷史中查找出符合註冊Action的所有Intent的,將Intent保存在sticktIntent集合中,然後在精準匹配Intent的類型和數據等,將符合本次註冊監聽的意圖保存在allSticky中,因爲粘性廣播在註冊完成後會立即發送,所以這裏在註冊時查找保存;
下面繼續廣播註冊過程:
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());//(1)
if (rl == null) {
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver); //(2)
if (rl.app != null) {
rl.app.receivers.add(rl);
}
}
mRegisteredReceivers.put(receiver.asBinder(), rl); //(3)
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId, instantApp, visibleToInstantApps); //(4)
if (rl.containsFilter(filter)) {
} else {
rl.add(bf);
mReceiverResolver.addFilter(bf);
}
實現註冊的流程:
- 從AMS的已註冊Receiver列表中查找此廣播對象,判斷是否是註冊過的廣播
- 對於新註冊的廣播創建ReceiverList實例保存receiver對象以及程序的身份和進程信息
- 緩存當前的Receiver保存在mRegisteredReceivers中
- 緩存當前的ReceiverList和註冊的IntentFilter保存在BroadcastFilter中
- 將BroadcastFilter添加到ReceiverList內部的集合中保存(內部可保存多個)
- 將bf保存到mReceiverResolver中,所以所有註冊的廣播都會保存在mReceiverResolver集合中
到此已經完成了廣播的註冊,對於未匹配粘性廣播的此處的allSticky應該爲null,如果匹配到發動過的粘性廣播,要在廣播註冊完成後執行一次廣播發送,這裏到此結束,關於廣播發送的詳細過程見下一節
- 發送廣播:AMS.sendBroadCast()
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES); //設置默認不發送給Stop狀態的應用
final String action = intent.getAction(); // 取出Action
try { // 校驗如果是保護的系統廣播則直接return SUCCESS
isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action);
} catch (RemoteException e) {
return ActivityManager.BROADCAST_SUCCESS;
}
switch (action) { // 優先處理PMS發送的廣播
case Intent.ACTION_UID_REMOVED:
case Intent.ACTION_PACKAGE_REMOVED:
case Intent.ACTION_PACKAGE_CHANGED:
廣播發送後會執行系列的檢查,檢查廣播的合法性等,其中系統廣播會優先發送;廣播發送的第一步就是保存粘性廣播
- . 處理髮送的粘性廣播
if (sticky) {
if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
callingPid, callingUid)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException(msg);
}
ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
ArrayList<Intent> list = stickies.get(intent.getAction());
final int stickiesCount = list.size();
int i;
for (i = 0; i < stickiesCount; i++) {
if (intent.filterEquals(list.get(i))) {
list.set(i, new Intent(intent));
break;
}
}
if (i >= stickiesCount) {
list.add(new Intent(intent));
}
}
執行流程:
- 獲取當前應用發送的粘性事件的Map集合
- 從Map 集合中獲取當前廣播Action 的Intent集合
- 遍歷此用戶已經發送的廣播集合,查找屬否已經保存,如果系統中已緩存了此粘性Intent則替換
- 系統中沒有此粘性Intent則直接添加新的廣播
- . 處理廣播接接收
int[] users;
if (userId == UserHandle.USER_ALL) {
users = mUserController.getStartedUserArray(); // 所有用戶
} else {
users = new int[] {userId}; // 單一用戶
}
//
registeredReceivers = mReceiverResolver.queryIntent(intent,
resolvedType, false, userId);
6. 處理併發送廣播
final BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
resultCode, resultData, resultExtras, ordered, sticky, false, userId);
final boolean replaced = replacePending && (queue.replaceParallelBroadcastLocked(r) != null);
if (!replaced) {
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
執行流程:
- 根據發送的廣播確定廣播的接收用戶:所有用戶、單一用戶
- 從mReceiverResolver中查詢所有符合條件的bf集合,每個bf對象就是一個廣播接收者
- 創建BroadcastQueue和BroadcastRecord對象保存廣播和接收者信息
- 執行queue.scheduleBroadcastsLocked()發送廣播
- . scheduleBroadcastsLocked()
public void scheduleBroadcastsLocked() {
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this)); //發送事件
mBroadcastsScheduled = true;
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BROADCAST_INTENT_MSG: {
processNextBroadcast(true);
} break;
case BROADCAST_TIMEOUT_MSG: {
synchronized (mService) {
broadcastTimeoutLocked(true);
}
} break;
}
}
//processNextBroadcast
while (mParallelBroadcasts.size() > 0) {
r = mParallelBroadcasts.remove(0); //
final int N = r.receivers.size(); //
for (int i=0; i<N; i++) {
Object target = r.receivers.get(i); // 取出每個bf
//代碼最終調用app.thread.shceduleRegisterRecivier
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
}
addBroadcastToHistoryLocked(r);
}
- 發送BROADCAST_INTENT_MSG事件在handleMessage()中調用processNextBroadcast()
- processNextBroadcast()中取出BroadCastRecord,mParallelBroadcasts中保存着無序廣播
- 獲取符合傳入Intent 的bf的集合
- 遍歷所有的bf,執行app.thread.shceduleRegisterRecivier
- app.thread.shceduleRegisterReceiver
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered,
boolean sticky, int sendingUser, int processState) throws RemoteException {
updateProcessState(processState, false);
receiver.performReceive(intent, resultCode, dataStr, extras, ordered,sticky, sendingUser);
}
- receiver.performReceive()
@Override
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
rd = mDispatcher.get();
if (rd != null) {
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky, sendingUser);
} else {
mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
}
}
這裏執行IIntentReceiver的代理類InnerReceiver中方法,InnerReceiver中首次調用mDispatcher.get()獲取內部保存的LoadedApk.ReceiverDispatcher對象,然後調用LoadedApk.ReceiverDispatcher.performReceive()方法
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
final Args args = new Args(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
if (intent == null || !mActivityThread.post(args.getRunnable())) {
if (mRegistered && ordered) {
IActivityManager mgr = ActivityManager.getService();
args.sendFinished(mgr);
}
}
}
public final Runnable getRunnable() {
return () -> {
final BroadcastReceiver receiver = mReceiver; //執行receiver的onReceiver()
receiver.setPendingResult(this);
receiver.onReceive(mContext, intent);
}
}
執行流程:
- 創建Args對象保存發送的Intent信息
- 調用mActivityThread.post(args.getRunnable())發送事件
- 在Runnable.run()方法中獲取目標Receiver
- 執行Receiver的onReceive(mContext, intent)實現廣播接收
到此四大組件的啓動過程介紹完畢了,這些執行流程在開發中至關重要,尤其在插件化開發中只有連接其原理和過程,才能合理的找到插件化的地方!