深入理解Activity啟動流程和AMS框架(二)

最好不过如今發表於2024-07-29

連結https://mp.weixin.qq.com/s?__biz=MzIwNjQ1NzQxNA==&mid=2247484150&idx=1&sn=4007a9cff85df88941e73869b89b1ed4&chksm=97201ddfa05794c9e33c8d0d9e83f407922d24282dc9bd8d67c72debf9713abb1b0586f00bc9&scene=21#wechat_redirect

深入理解Activity啟動流程和AMS框架(一)

由此我們可以得到ActivityThread框架圖:

圖片

通常ApplicationThread中的介面方法都是以“schedule”開頭,而ActivityThread中對應的處理方法則以“handle”開頭。

6、Activity的建立並回撥onCreate()

ActivityThread中的成員變數mActivities中儲存了所有ActivityClientRecord物件,該類中重要的成員變數如下:

static final class ActivityClientRecord {
    IBinder token;                // Activity物件的全域性唯一標示
    Intent intent;                // 啟動Activity的Intent
    Activity activity;            // Activity物件
    Window window;                // Activity的視窗物件
    boolean paused;               // 是否在暫停狀態的標誌
    boolean stopped;              // 是否在停止狀態的標誌
    ActivityInfo activityInfo;    // Activity的資訊
    LoadedApk packageInfo;        // 包的資訊
}

token的型別是IBinder,在ActivityManagerService中會為每個應用程式中的Activity物件建立了一個對應的ActivityRecord物件,ActivityRecord會建立一個token物件來作為Activity的標識。這個token是個Binder物件,但是它不是為提供Binder服務而建立的,這裡只是利用Binder物件的 系統全域性唯一性 來作為識別符號。 每一個Activity都包含了一個Window物件,Window物件關聯著應用框架的一大塊內容。

從上面的框架圖我們可以得知:啟動一個Activity,首先會經過AMS和ActivityThread之間又長又臭的呼叫和回撥,最終才會調到ActivityThread的handleLaunchActivity()方法。下面我們看一下接下來的流程。

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
      ......
      // 執行Activity建立和onCreate流程
      Activity a = performLaunchActivity(r, customIntent);

      if (a != null) {
          r.createdConfig = new Configuration(mConfiguration);
          Bundle oldState = r.state;
          // 執行Activity的onResume流程
          handleResumeActivity(r.token, false, r.isForward,
                  !r.activity.mFinished && !r.startsNotResumed);
          ......
      } else {
          // If there was an error, for any reason, tell the activity
          // manager to stop us.
          try {
              ActivityManagerNative.getDefault()
                  .finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
          } catch (RemoteException ex) {
              // Ignore
          }
      }
  }

handleLaunchActivity()再呼叫performLaunchActivity()方法來建立Activity並執行onCreate流程,返回後再執行Activity的onResume流程。繼續深入,不要慫。

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
     // 首先,從ActivityClientRecord中獲取待啟動的Activity的元件資訊            
     ActivityInfo aInfo = r.activityInfo;
     if (r.packageInfo == null) {
         // 獲取Activity的packageInfo 
         r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                 Context.CONTEXT_INCLUDE_CODE);
     }

     ComponentName component = r.intent.getComponent();
     if (component == null) {
         // 獲取Activity的ComponentName 
         component = r.intent.resolveActivity(
             mInitialApplication.getPackageManager());
         r.intent.setComponent(component);
     }

     if (r.activityInfo.targetActivity != null) {
         component = new ComponentName(r.activityInfo.packageName,
                 r.activityInfo.targetActivity);
     }

     Activity activity = null;
     try {
         // 拿到載入Activity的ClassLoader, 建立Activity物件 
         java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
         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) {
         if (!mInstrumentation.onException(activity, e)) {
             throw new RuntimeException(
                 "Unable to instantiate activity " + component
                 + ": " + e.toString(), e);
         }
     }

     try {
         // 拿到當前程序中的Application物件
         Application app = r.packageInfo.makeApplication(false, mInstrumentation);

         if (activity != null) {
             // 建立Activity的ApplicationContext
             Context appContext = createBaseContextForActivity(r, activity);
             CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
             Configuration config = new Configuration(mCompatConfiguration);
             // 呼叫Activity的attach方法在其內部儲存一些ActivityClientRecord內的屬性
             // 來完成一些重要的資料初始化
             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);
             ......
             // 透過mInstrumentation呼叫Activity的onCreate方法
             if (r.isPersistable()) {  
                 mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
             } else {
                 mInstrumentation.callActivityOnCreate(activity, r.state);
             }
             ...
             // 將ActivityClientRecord中的activity屬性設定為當前activity
             r.activity = activity;
             ......
         }
         r.paused = true;

         // 以ActivityClientRecord中的token為key,mActivities中新增待啟動的activity
         mActivities.put(r.token, r);

     } catch (SuperNotCalledException e) {
         throw e;

     } catch (Exception e) {
         if (!mInstrumentation.onException(activity, e)) {
             throw new RuntimeException(
                 "Unable to start activity " + component
                 + ": " + e.toString(), e);
         }
     }

     return activity;
 }

從上面程式碼我們發現,ActivityThread最後呼叫了mInstrumentation變數的newActivity()方法來建立Activity物件,並回撥了callActivityOnCreate()方法,走完Activity的onCreate流程。

public class Instrumentation {
    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
        activity.performCreate(icicle); // 回撥Activity.onCreate()
        postPerformCreate(activity);
    }

    public void callActivityOnCreate(Activity activity, Bundle icicle,
            PersistableBundle persistentState) {
        prePerformCreate(activity);
        activity.performCreate(icicle, persistentState); // 回撥Activity.onCreate()
        postPerformCreate(activity);
    }
}

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback {

    final void performCreate(Bundle icicle) {
        onCreate(icicle);
        mActivityTransitionState.readState(icicle);
        performCreateCommon();
    }

    final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        onCreate(icicle, persistentState);
        mActivityTransitionState.readState(icicle);
        performCreateCommon();
    }
}

這樣Activity在應用端程序ActivityThread的啟動流程和生命週期回撥流程都簡單分析完了。

Instrumentation是什麼?和ActivityThread是什麼關係?

Instrumentation可以理解為應用程序的管家,ActivityThread要執行建立或暫停某個Activity等操作時,都需要透過Instrumentation來進行具體的實現(回撥Activity的生命週期)。每一個應用程式只有一個Instrumentation物件,每個Activity內都有一個對該物件的引用。 另外,當我們在Activity中呼叫startActivity()的 時候,實際上呼叫的還是Instrumentation的相關的方法mInstrumentation.execStartActivity()。

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, String target,
        Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    if (mActivityMonitors != null) {
        synchronized (mSync) {
            final int N = mActivityMonitors.size();
            for (int i=0; i<N; i++) {
                final ActivityMonitor am = mActivityMonitors.get(i);
                if (am.match(who, null, intent)) {
                    am.mHits++;
                    if (am.isBlocking()) {
                        return requestCode >= 0 ? am.getResult() : null;
                    }
                    break;
                }
            }
        }
    }
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess();
        // 通知AMS執行startActivity的流程
        int result = ActivityManagerNative.getDefault()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target, requestCode, 0, null, options);
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

ActivityManagerNative.getDefault返回的就是ActivityManagerService的遠端介面,即ActivityManagerProxy。 除了啟動Activity之外,還有很多方法,有興趣的可以深入瞭解一下:

圖片

通俗的理解,ActivityThread負責建立這個“家庭”,並負責對外打交道,比如接收AMS的通知等。Instrumentation負責管理這個家庭,安排每個Activity的日常流程等工作。

四、小結

AMS透過Binder進行IPC通訊,通知應用程序ActivityThread啟動指定Activity

  • 呼叫ApplicationThread.scheduleLaunchActivity()。

  • 經過Handler訊息傳動,呼叫ActivityThread.handleLaunchActivity()。

  • 呼叫ActivityThread.performLaunchActivity()完成Activity的載入,並最終呼叫Activity生命週期的onCreate()方法

  • performLaunchActivity返回,繼續呼叫ActivityThread.handleResumeActivity(),該方法內部又呼叫ActivityThread.performResumeActivity(),其內部僅僅呼叫了目標Activity的onResume()方法。到此Activity啟動完成。

  • Activity的其他生命週期方法onRestart等,可以根據onCreate流程為類推,舉一反三。

五、ActivitymanagerService(AMS)框架

ActivitymanagerService是Android Framework的一個核心繫統服務,它管理著Android系統中的4大元件:Activity、Service、ContentProvider和BroadcastReceiver。前面已經介紹了,Android希望模糊程序的作用,取而代之以元件的概念,AMS正是這一理念的實現。AMS除了管理這4大元件之外,同時也管理和排程所有使用者程序。

1、ActivityManager、ActivityManagerService、ActivityManagerNative、ActivityManagerProxy的關係

AMS是一個Binder服務,但是AMS的Binder框架程式碼不是透過AIDL自動生成的。AMS從ActivityManagerNative類派生,這個類加上IActivityManager、ActivityManagerProxy和ActivityManager共同實現了AMS Binder框架。它們的關係如下圖:

圖片

  • ActivityManagerNative類的程式碼雖然也很龐大,但只是實現Binder的框架,我們可以不用關心這個類的實現細節。

  • ActivityManagerProxy類是作為ActivityManagerNative的嵌入類來實現的,它是代理物件,起介面作用。

  • ActivityManager透過呼叫ActivityManagerNative的getDefault()方法來得到ActivityManagerProxy物件的引用。

理解了AMS的Binder框架類的作用,後面分析AMS服務的時候,可以不用關係這些類,只需要集中精力在AMS類的本身上。

2、AMS的初始化

AMS執行在SystemServer程序中,物件的建立是在SystemServer類初始化時完成的。

public final class SystemServer {
    ......
    private ActivityManagerService mActivityManagerService;
    private void startBootstrapServices() {
        ...
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();  // 建立AMS服務
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
        ...
    }
    ......
}

從程式碼中可以看到,這裡呼叫了mSystemServiceManager.startService()方法,這個方法將根據傳入的引數(類的class)來建立類的例項物件,並註冊到ServiceManager中。 接下來我們看一下AMS的構造方法做了些什麼:

public ActivityManagerService(Context systemContext) {
    mContext = systemContext;
    mFactoryTest = FactoryTest.getMode();
    // 獲取執行在SystemServer中的ActivityThread物件
    mSystemThread = ActivityThread.currentActivityThread();
    // 建立用於處理訊息的執行緒和Handler物件
    mHandlerThread = new ServiceThread(TAG,
            android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
    mHandlerThread.start();
    mHandler = new MainHandler(mHandlerThread.getLooper());
    // 建立用於UI操作相關的Handler物件
    mUiHandler = new UiHandler();

    // 建立管理廣播的資料結構
    mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
            "foreground", BROADCAST_FG_TIMEOUT, false);
    mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
            "background", BROADCAST_BG_TIMEOUT, true);
    mBroadcastQueues[0] = mFgBroadcastQueue;
    mBroadcastQueues[1] = mBgBroadcastQueue;

    mServices = new ActiveServices(this);  // 建立管理元件Service的物件
    mProviderMap = new ProviderMap(this);  // 建立管理元件Provider的物件

    // 獲取系統的data和system目錄
    File dataDir = Environment.getDataDirectory();
    File systemDir = new File(dataDir, "system");
    systemDir.mkdirs();

    // 建立BatteryStatsService服務
    mBatteryStatsService = new BatteryStatsService(systemDir, mHandler);
    mBatteryStatsService.getActiveStatistics().readLocked();
    mBatteryStatsService.scheduleWriteToDisk();
    mOnBattery = DEBUG_POWER ? true
            : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
    mBatteryStatsService.getActiveStatistics().setCallback(this);
    // 建立ProcessStatsService服務
    mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));
    // 建立AppOpsService應用許可權管理服務
    mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml"), mHandler);
    // 開啟檔案urigrants.xml
    mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"));

    // 設定0號使用者作為第一個使用者
    mStartedUsers.put(UserHandle.USER_OWNER, new UserState(UserHandle.OWNER, true));
    mUserLru.add(UserHandle.USER_OWNER);
    updateStartedUserArrayLocked();
    // 獲取OpenglES的版本
    GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
        ConfigurationInfo.GL_ES_VERSION_UNDEFINED);

    mTrackingAssociations = "1".equals(SystemProperties.get("debug.track-associations"));
    // 設定mConfiguration配置項為系統預設值
    mConfiguration.setToDefaults();
    mConfiguration.setLocale(Locale.getDefault());

    mConfigurationSeq = mConfiguration.seq = 1;
    mProcessCpuTracker.init();

    mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
    // 建立Intent “防火牆”
    mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
    // 建立最近工作列的棧管理物件
    mRecentTasks = new RecentTasks(this);
    // 建立Activity棧的管理物件mStackSupervisor 
    mStackSupervisor = new ActivityStackSupervisor(this, mRecentTasks); 
    mTaskPersister = new TaskPersister(systemDir, mStackSupervisor, mRecentTasks);
    // 建立統計CPU使用情況的執行緒
    mProcessCpuThread = new Thread("CpuTracker") {
        ......
    }

    // 把服務加到watchdog的監控中
    Watchdog.getInstance().addMonitor(this);
    Watchdog.getInstance().addThread(mHandler);
}

AMS構造方法的主要作用是建立了4大元件Activity、Service、BroadcastReceiver和ContentProvider的管理物件以及一些內部物件,邏輯比較簡單。

3、如何啟動程序

AMS中啟動一個程序呼叫的是addAppLocked()方法。

final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated,
            String abiOverride) {
      ProcessRecord app;
      // isolated為true表示要啟動一個新程序
      if (!isolated) { // 在已經啟動的程序列表中查詢
          app = getProcessRecordLocked(info.processName, info.uid, true);
      } else {
          app = null;
      }

      if (app == null) {
          // 建立一個ProcessRecord物件
          app = newProcessRecordLocked(info, null, isolated, 0);
          updateLruProcessLocked(app, false, null);
          updateOomAdjLocked();
      }
      ......
      if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
          mPersistentStartingProcesses.add(app);
          // 啟動程序
          startProcessLocked(app, "added application", app.processName, abiOverride,
                  null /* entryPoint */, null /* entryPointArgs */);
      }

      return app;
  }

addAppLocked()方法會根據引數isolated來決定是否啟動一個新程序,如果為true,即使系統中可能已經有一個同名的程序存在,也會再建立一個新程序。getProcessRecordLocked()方法用來在當前執行的程序列表中查詢程序。newProcessRecordLocked()方法用來建立一個ProcessRecord的資料結構。updateLruProcessLocked方法用來更新執行中的程序的狀態,updateOomAdjLocked用來更新程序的優先順序,這兩個方法是Process管理的核心。篇幅有限,這裡不再展開分析咯。

4、ActivityRecord、TaskRecord、ActivityStack的關係

(1)、ActivityRecord

final class ActivityRecord {
    // AMS的引用  
    final ActivityManagerService service; // owner  
    // token用來和WMS互動  
    final IApplicationToken.Stub appToken; // window manager token  
    final ActivityInfo info; // all about me  
    final ApplicationInfo appInfo; // information about activity's app  
    final ComponentName realActivity;  // the intent component, or target of an alias.
    ...  

    //Activity資源資訊  
    CharSequence nonLocalizedLabel;  // the label information from the package mgr.  
    int labelRes;           // the label information from the package mgr.  
    int icon;               // resource identifier of activity's icon.  
    int logo;               // resource identifier of activity's logo.  
    int theme;              // resource identifier of activity's theme.  
    int realTheme;          // actual theme resource we will use, never 0.  
    int windowFlags;        // custom window flags for preview window.  

    // ActivityRecord所在的TaskRecord  
    TaskRecord task;        // the task this is in.  
    ...  
    // ActivityRecord所在程序  
    ProcessRecord app;      // if non-null, hosting application  
    ActivityState state;    // current state we are in  
    ...  
}

ActivityRecord就是Activity在AMS中的代表,ActivityRecord和應用中的Activity一一對應,並且包含了Activity的所有資訊。(就好比Activity在ActivityThread中對應ActivityClientRecord一樣) 每一個ActivityRecord都會有一個Activity與之對應,一個Activity可能會有多個ActivityRecord,因為Activity可以被多次例項化,取決於其Launchmode。 其中task物件標識了其所歸屬的TaskRecord,這樣ActivityRecord和TaskRecord就聯絡起來了。

(2)TaskRecord

final class TaskRecord {
    // TaskRecord的唯一標識  
    final int taskId;       // Unique identifier for this task.  
    .....  
    // This represents the last resolved activity values for this task  
    // NOTE: This value needs to be persisted with each task  
    TaskDescription lastTaskDescription = new TaskDescription();  

    // TaskRecord裡所有的ActivityRecord資訊  
    /** List of all activities in the task arranged in history order */  
    final ArrayList<ActivityRecord> mActivities;  

    // TaskRecord所在的stack  
    ActivityStack stack;  
    ......
}

TaskRecord中我列出來三個成員變數:

  • taskId:唯一標示的id號

  • mActivities:當前棧中所有的ActivityRecord

  • stack:ActivityStack的引用,為了回撥ActivityStack的方法

從TaskRecord 的資料結構我們可以看到,mActivities儲存了一組ActivityRecord資訊,同時每一個ActivityRecord都有其所在TaskRecord的引用。TaskRecord都有一個唯一標示taskId,還包含了ActivityStack的引用物件。 因此,TaskRecord可以理解為一個mActivities組成的棧,也可以理解為一個由一系列Activity組成的活動。

(3)、 ActivityStack

final class ActivityStack {
    /** 
     * The back history of all previous (and possibly still 
     * running) activities.  It contains #TaskRecord objects. 
     */  
    private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();  

    ...  

    final int mStackId;  
    ...  
    /** Run all ActivityStacks through this */  
    final ActivityStackSupervisor mStackSupervisor; 
}
  • mStackId:唯一標示的id號

  • mTaskHistory:這個記錄的是一組TaskRecord的棧資訊

  • mStackSupervisor:ActivityStack的管理類,也是為了方便管理Task,被AMS呼叫等

從名字上看,ActivityStack更像是一個棧,實際上它就是一個Manager的角色。 ActivityStack負責管理協調ActivityRecord和TaskRecord,透過mStackId來唯一標識,持有ActivityStackSupervisor的引用。

(4)、關係圖

每一個ActivityRecord都會有一個Activity與之對應。一系列相關的ActivityRecord組成了一個TaskRecord,TaskRecord是存在於ActivityStack中,ActivityStackSupervisor是用來管理這些ActivityStack的。 下面是一個簡單的關係圖

圖片

Task 是Activity的集合。Android把使用者一次相關操作用使用的Activity按照先後順序儲存在Task中,這樣當使用者按back鍵的時候就能按照相反的順序依次返回退出。Task像一個棧,以先進後出的方式管理著Activity。系統執行時記憶體中會存在多個Task,當我們檢視最近工作列時,會彈出一個列表讓你選擇,這個列表就是系統中存在的Task集合,選擇一個Task會將它所包含的Activity作為一個整體帶到前臺。Task中的Activity的順序通常是不能改變的,只能壓棧和出棧。

AMS中使用ActivityStack 類來管理Task,它管理的Task都存放在成員變數mTaskHistory中。mTaskHistory也是一個列表,儲存的是TaskRecord物件。TaskRecord物件代表一個Task,他的成員變數mActivities也是一個列表,儲存了屬於該Task中的所有ActivityRecord物件。

相關文章