Android進階知識樹——Android四大組件啓動過程

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. 註釋1處調用IActivityManager代理類,IActivityManager是系統的服務接口,在此處採用Binder通信,ActivityManager.getService() 獲取到的是它代理實現類ActivityManagerService,然後調用ActivityManagerService.startActivity()方法啓動活動
  2. 在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過程中:

  1. 賦值appClass指向要執行的類android.app.Application
  2. 創建Application 中的ContextImpl對象
  3. 調用mInstrumentation.newApplication()實例化Application,並執行attach()綁定Context
static public Application newApplication(Class<?> clazz, Context context){
        Application app = (Application)clazz.newInstance();
        app.attach(context);
        return app;
    }
  1. 執行Application的onCreate()
  • . 調用Activity的attach()完成Window的創建個初始化
  1. 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中的創建過程:
  1. 使用類加載器加載類Service並創建Service實例
  2. 使用Instrumentation創建Application實例,並調用onCreate()初始化
  3. 創建ContextImpl實例,並通過attach與Service建立聯繫()(詳情見Android插件化——Context機制
  4. 調用Service的onCreate()初始化Service
  5. 使用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對象外,還執行一下邏輯:

  1. 以鍵值對的形式保存保存ServiceConnection和ServiceDispatcher的實例在緩存mService中,並返回InnerConnection實例;
  2. 調用AMS.bindService(),bindService()中又調用ActiveServices.bindServiceLocked()實現服務的啓動,整個啓動過程和上 面一致;
  3. 在執行服務啓動時,如果此時服務已經在運行,則直接回調綁定方法
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()

  1. 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()中,執行一下邏輯:

  1. 從已連接的mActiveConnections中獲取之前的連接
  2. 爲Service設置死亡監聽
  3. 對老的綁定回掉之前連接的死亡通知,並回掉ServiceConnection斷開連接方法
  4. 對新的連接回掉連接成功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執行以下操作:
  1. 根據Service的Token取出Service對象,並根據是否爲第一次綁定和重新綁定回調Service的onBind()和onReBind()
  2. 對第一次綁定的先調用onBinder回去Binder對象,然後調用AMS的publishService(),publishService最終交給ActivityServices.publishServiceLocked()方法
  3. 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;
}
  1. 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

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);
}

實現註冊的流程:

  1. 從AMS的已註冊Receiver列表中查找此廣播對象,判斷是否是註冊過的廣播
  2. 對於新註冊的廣播創建ReceiverList實例保存receiver對象以及程序的身份和進程信息
  3. 緩存當前的Receiver保存在mRegisteredReceivers中
  4. 緩存當前的ReceiverList和註冊的IntentFilter保存在BroadcastFilter中
  5. 將BroadcastFilter添加到ReceiverList內部的集合中保存(內部可保存多個)
  6. 將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)); 
    }
}

執行流程:

  1. 獲取當前應用發送的粘性事件的Map集合
  2. 從Map 集合中獲取當前廣播Action 的Intent集合
  3. 遍歷此用戶已經發送的廣播集合,查找屬否已經保存,如果系統中已緩存了此粘性Intent則替換
  4. 系統中沒有此粘性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();
}

執行流程:

  1. 根據發送的廣播確定廣播的接收用戶:所有用戶、單一用戶
  2. 從mReceiverResolver中查詢所有符合條件的bf集合,每個bf對象就是一個廣播接收者
  3. 創建BroadcastQueue和BroadcastRecord對象保存廣播和接收者信息
  4. 執行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);
}
  1. 發送BROADCAST_INTENT_MSG事件在handleMessage()中調用processNextBroadcast()
  2. processNextBroadcast()中取出BroadCastRecord,mParallelBroadcasts中保存着無序廣播
  3. 獲取符合傳入Intent 的bf的集合
  4. 遍歷所有的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);
  }
}

執行流程:

  1. 創建Args對象保存發送的Intent信息
  2. 調用mActivityThread.post(args.getRunnable())發送事件
  3. 在Runnable.run()方法中獲取目標Receiver
  4. 執行Receiver的onReceive(mContext, intent)實現廣播接收

到此四大組件的啓動過程介紹完畢了,這些執行流程在開發中至關重要,尤其在插件化開發中只有連接其原理和過程,才能合理的找到插件化的地方!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章