banner
fwrite

fwrite

好好生活
twitter
github
email

Activityの起動

アクティビティの起動#

  // 指定されたアクティビティを起動する
  
  void startBootActivity() {
      Intent i = new Intent(this, BootActivity.class);
      startActivity(i);   
  }

アクティビティが ActivityTaskManagerService を呼び出す#

アクティビティは直接 ActivityTaskManagerService にアクセスせず、Instrumentation を通じて Activity#startActivity メソッドを呼び出します:最終的には Activity#startActivityForResult メソッドに導かれ、Instrumentation を介してアクティビティを起動するリクエストが行われます。
ここでの重要なポイントは、現在のプロセスの ApplicationThread が渡されることです。もう一つは mToken パラメータで、これは現在のアプリケーションが AMS の中で ActivityManager の代表を示します。

  // Activity.java
  public class Activity extends ContextThemeWrapper
          implements LayoutInflater.Factory2,
          Window.Callback, KeyEvent.Callback,
          ...省略部分のインターフェース {
  
      /*package*/ ActivityThread mMainThread;
      private Instrumentation mInstrumentation;    
  
      @Override
      public void startActivity(Intent intent) {
          this.startActivity(intent, null);
      }
  
      @Override
      public void startActivity(Intent intent, @Nullable Bundle options) {
          if (mIntent != null && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)
                  && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY)) {
                  ... 省略部分
          }
  
          // @ startActivityForResult の分析
          if (options != null) {
              startActivityForResult(intent, -1, options);
          } else {
              startActivityForResult(intent, -1);
          }
      }
  
  
      public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
              @Nullable Bundle options) {
          if (mParent == null) {
              options = transferSpringboardActivityOptions(options);
  
              // @ Instrumentation#execStartActivity 関数を追跡、mMainThread は ActivityThread です。
              Instrumentation.ActivityResult ar =
                  mInstrumentation.execStartActivity(
                      // @ getApplicationThread メソッドを確認
                      this, mMainThread.getApplicationThread(), 
                      mToken,     // IBinder 型、ActivityRecord の代理オブジェクト
                      this,
                      intent, requestCode, options);
              ... 省略部分
  
          } else {
              ... 省略部分
          }
      }
  }
  
  
  // ---------------------------------------------------------
  // ActivityThread .java
  
  public final class ActivityThread extends ClientTransactionHandler
      implements ActivityThreadInternal {
      
      // アプリケーションスレッドは一つだけ
      final ApplicationThread mAppThread = new ApplicationThread();
  
      public ApplicationThread getApplicationThread()
      {
          return mAppThread;
      }
  
      private class ApplicationThread extends IApplicationThread.Stub {
          ... 省略詳細
      }
  }

アクティビティのリクエストはすべて Instrumentation クラスを通じて行われます(これはフックのようなものです)、アプリケーションとシステム AMS のインタラクションプロセスを監視するために使用されます。
Instrumentation#execStartActivity メソッド:最終的に ActivityTaskManager#startActivity メソッドを呼び出し 代理クラスと ATMS プロセス間の通信を取得します(ATMS は SystemServer プロセスに属します)。

 // Instrumentation.java
 
 public class Instrumentation {
 
     public ActivityResult execStartActivity(
             Context who, IBinder contextThread, IBinder token, Activity target,
             Intent intent, int requestCode, Bundle options) {
         
         IApplicationThread whoThread = (IApplicationThread) contextThread;
 
         ... 省略部分
 
         try {
             ...省略部分
             
             // ActivityTaskManager#startActivity 関数を起動しました
             // whoThread は IApplicationThread です
             int result = ActivityTaskManager.getService().startActivity(whoThread,
                     who.getBasePackageName(), who.getAttributionTag(), intent,
                     intent.resolveTypeIfNeeded(who.getContentResolver()), token,
                     target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
             
             // AMS のアクティビティ起動結果のチェック
             checkStartActivityResult(result, intent);
         } catch (RemoteException e) {
             throw new RuntimeException("Failure from system", e);
         }
         return null;
     }
 }

Instrumentation の動作は主に ActivityTaskManager を介して Binder 代理クラスを取得し、ActivityTaskManagerService と通信します。

 // Instrumentation.java
 public static void checkStartActivityResult(int res, Object intent) {
     if (!ActivityManager.isStartResultFatalError(res)) {
         return;
     }
     
     switch (res) {
         // Android Manifest に登録されていない
         case ActivityManager.START_INTENT_NOT_RESOLVED:
         case ActivityManager.START_CLASS_NOT_FOUND:
             if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
                 throw new ActivityNotFoundException(
                         "Unable to find explicit activity class "
                         + ((Intent)intent).getComponent().toShortString()
                         + "; have you declared this activity in your AndroidManifest.xml?");
             throw new ActivityNotFoundException(
                     "No Activity found to handle " + intent);
             
         // 権限が拒否されている
         case ActivityManager.START_PERMISSION_DENIED:
             throw new SecurityException("Not allowed to start activity "
                     + intent);
         // リクエストの競合
         case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
             throw new AndroidRuntimeException(
                     "FORWARD_RESULT_FLAG used while also requesting a result");
             
         ... 省略部分
             
         default:
             throw new AndroidRuntimeException("Unknown error code "
                     + res + " when starting " + intent);
     }
 }

ActivityTaskManager は Binder メカニズムを介して最終的に システムプロセス の ActivityTaskManagerService (AIDL のサーバー側) に到達します。

重要なパラメータ説明
caller呼び出し元
intent呼び出すアクティビティの情報
resultTo呼び出し元の AMS 内の ActivityRecord
  // ActivityTaskManagerService.java
  
  // SystemService によって起動されたシステムプロセス
  // IActivityTaskManager.Stub はサービス側の実装
  public class ActivityTaskManagerService extends IActivityTaskManager.Stub {    // IActivityTaskManager は IDE 自動生成クラス
  
      @Override
      public final int startActivity(IApplicationThread caller, String callingPackage,
              String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
              String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
              Bundle bOptions) {
          
          // @ startActivityAsUser の分析
          return startActivityAsUser(caller,     // 呼び出し元 IApplicationThread
                     callingPackage, 
                     callingFeatureId, 
                     intent,     // 呼び出すアクティビティの情報
                     resolvedType,
                     resultTo,     // 呼び出し元の AMS 内の ActivityRecord
                     resultWho, requestCode, startFlags, profilerInfo, bOptions,
                  UserHandle.getCallingUserId());
      }
  
  }

ActivityStartController - アクティビティの起動準備#

startActivity (ユーザーのプロセス) -> Binder -> startActivityAsUser (システムプロセス)、最終的に ActivityStartController を介して指定されたアクティビティを起動します。

  // ActivityTaskManagerService.java
  
  public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
  
      /**
  	 * @call 呼び出し元の IBinder(アプリケーションプロセスの Binder Server)、
  	 * 対応するのは ActivityThread#ApplicationThread(内部クラス)
       */ 
      @Override
      public final int startActivity(IApplicationThread caller, String callingPackage,
              String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
              String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
              Bundle bOptions) {
  
          // @ startActivityAsUser を確認 
          return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
                  resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
                  UserHandle.getCallingUserId());
      }
  
      @Override
      public int startActivityAsUser(IApplicationThread caller, String callingPackage,
                                     /*省略部分のパラメータ*/) {
  
          // @ startActivityAsUser を確認 
          return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
                  resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
                  true /*validateIncomingUser*/);
      }
  
      private int startActivityAsUser(IApplicationThread caller, String callingPackage, 
                                      /*省略部分のパラメータ*/) {
          assertPackageMatchesCallingUid(callingPackage);
          enforceNotIsolatedCaller("startActivityAsUser");
  
          userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
                  Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
  
          // obtainStarter は ActivityStarter クラスを返します
          return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
                  .setCaller(caller)
                  .setCallingPackage(callingPackage)
                  .setCallingFeatureId(callingFeatureId)
                  .setResolvedType(resolvedType)
                  .setResultTo(resultTo)
                  .setResultWho(resultWho)
                  .setRequestCode(requestCode)
                  .setStartFlags(startFlags)
                  .setProfilerInfo(profilerInfo)
                  .setActivityOptions(bOptions)
                  .setUserId(userId)
                  .execute();        // ActivityStarter#execute 関数を直接確認
  
      }
  
  }

ActivityStartController から再利用(obtain)される ActivityStarter クラスを取得できます。
ここで ActivityStartController は ファクトリーパターン を使用しており、目標は ActivityStarter を生成することです。
ActivityStarterビルダーパターン を使用しており、アクティビティを呼び出すためのオプションを設定できます。
ActivityStarter#execute には主に二つのアクションがあります:

  • 目標アクティビティが重いかどうかを判断する
  • アプリケーション(APP)のプロセスのアクティビティリクエストを実行する
  // ActivityStarter.java
  
  private final ActivityTaskSupervisor mSupervisor;
  
  // Request は内部クラス
  Request mRequest = new Request();
  
  class ActivityStarter {
  
      int execute() {
          try {
              int res;
  
              if (mRequest.activityInfo == null) {
                  // @ resolveActivity メソッドの分析
                  mRequest.resolveActivity(mSupervisor);
              }
  
              // スレッドロック
              synchronized (mService.mGlobalLock) {
                  ... 省略部分
  
  				// 次のセクションでこれらの二つのメソッドを分析します
  				// 1. 目標アクティビティが重いかどうかを判断する
                  res = resolveToHeavyWeightSwitcherIfNeeded();
                  if (res != START_SUCCESS) {
                      return res;
                  }
                  // 2. アクティビティリクエストを実行する
                  res = executeRequest(mRequest);
  
                  ... 省略部分
              }
          } 
      }
  
      static class Request {
  
          ActivityInfo activityInfo;
  
          void resolveActivity(ActivityTaskSupervisor supervisor) {
  
              ...
              // @ resolveIntent メソッドの分析
              resolveInfo = supervisor.resolveIntent(intent, resolvedType, userId,
                      0 /* matchFlags */,
                      computeResolveFilterUid(callingUid, realCallingUid, filterCallingUid));
  
              ...
  
              activityInfo = supervisor.resolveActivity(intent, resolveInfo, startFlags,
                      profilerInfo);
          }
      }
  }

ActivityTaskSupervisor#resolveActivityPackageManagerService で対応するアクティビティ情報(すなわち ActivityInfo)を見つけます。

  // ActivityTaskSupervisor.java
  
  final ActivityTaskManagerService mService;
  
  ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags,
          int filterCallingUid) {
      try {
          
          ... 省略部分
          
          final long token = Binder.clearCallingIdentity();
          try {
              // PKMS を介して ResolveInfo を取得
              return mService.getPackageManagerInternalLocked().resolveIntent(
                      intent, resolvedType, modifiedFlags, privateResolveFlags, userId, true,
                      filterCallingUid);
          } finally {
              Binder.restoreCallingIdentity(token);
          }
      } /* 省略 finally */
  }
  
  
  ActivityInfo resolveActivity(Intent intent, ResolveInfo rInfo, int startFlags,
          ProfilerInfo profilerInfo) {
      
      // ActivityInfo は ResolveInfo 内にあります
      final ActivityInfo aInfo = rInfo != null ? rInfo.activityInfo : null;
      ...
      return aInfo;
  }

ActivityStarter - execute の起動準備#

ActivityStarter#resolveToHeavyWeightSwitcherIfNeeded:目標アクティビティが重いかどうかを判断し、現在システムに存在する重いプロセスがあり、その中に必要なアクティビティがあれば、直接戻ります。
もし起動しようとしているアクティビティが重いプロセスで存在しない場合は、次に進み新しい Intent を与えます。

  // ActivityStarter.java
  
      private final ActivityTaskManagerService mService;
  
      /**
       * もしこれが重いプロセスであり、すでに別の異なる重いプロセスが実行中であれば、
  	 * 重いスイッチのリクエストを更新します
       */
      private int resolveToHeavyWeightSwitcherIfNeeded() {
  
          ... 省略部分
  
          // すでに起動しているかどうかを判断
          final WindowProcessController heavy = mService.mHeavyWeightProcess;
          if (heavy == null || 
              (heavy.mInfo.uid == mRequest.activityInfo.applicationInfo.uid
                  && heavy.mName.equals(mRequest.activityInfo.processName))
             ) {
              return START_SUCCESS;
          }
  
          ... 省略部分
  
          // 新しい Intent を作成
          final Intent newIntent = new Intent();
          if (mRequest.requestCode >= 0) {
              // 呼び出し元が結果を要求しています。
              newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
          }
          newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT, new IntentSender(target));
          heavy.updateIntentForHeavyWeightActivity(newIntent);
  
          newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
                  mRequest.activityInfo.packageName);
          newIntent.setFlags(mRequest.intent.getFlags());
          newIntent.setClassName("android" /* packageName */,
                  HeavyWeightSwitcherActivity.class.getName());
          mRequest.intent = newIntent;
  
          ... 省略部分
  
          return START_SUCCESS;
      }

ActivityStarter#executeRequest:アクティビティ起動アクションを実行します。以下の実行アクションは次のように分けられます。
呼び出し元(呼び出し元プロセス)がまだ生存しているかどうかを判断します。呼び出し元(APP)がシステムによって殺されたり、異常終了したりする可能性があるため、この時点で呼び出し元が消えることがあります。
Intent フラグ FLAG_ACTIVITY_FORWARD_RESULT を処理します。FLAG_ACTIVITY_FORWARD_RESULT は横断的な伝達機能を持ち、これが有効な場合、setResult の結果は元のアクティビティに戻ります。
その Intent がサポートされているかどうかを判断します(複数の判断)。
ActivityTaskManagerService、ActivityTaskSupervisor を介して起動権限を判断します。
ActivityRecord オブジェクトを作成し、startActivityUnchecked メソッドを呼び出します。

  // ActivityStarter.java
  
  private final ActivityTaskManagerService mService;
  private final ActivityTaskSupervisor mSupervisor;
  private int mLastStartActivityResult;
  
      private int executeRequest(Request request) {
  
          // ユーザー APP プロセス
          final IApplicationThread caller = request.caller;
  
          // アクティビティ関連情報
          ActivityInfo aInfo = request.activityInfo;
  
          // このアクティビティが所属するタスク(スタック)
          Task inTask = request.inTask;
  
          // 1. 呼び出し元が存在するかどうかを判断
          WindowProcessController callerApp = null;
          if (caller != null) {
              callerApp = mService.getProcessController(caller);
              if (callerApp != null) {
                  callingPid = callerApp.getPid();
                  callingUid = callerApp.mInfo.uid;
              } else {
                  // 呼び出し元が存在しない場合は START_PERMISSION_DENIED
                  err = ActivityManager.START_PERMISSION_DENIED;
              }
          }
  
          ... 省略部分
  
          ActivityRecord sourceRecord = null;        // 起動元
          ActivityRecord resultRecord = null;        // 目標結果
          if (resultTo != null) {
              sourceRecord = mRootWindowContainer.isInAnyStack(resultTo);
  
              ... デバッグメッセージ
  
              if (sourceRecord != null) {
                  if (requestCode >= 0 && !sourceRecord.finishing) {
                      resultRecord = sourceRecord;
                  }
              }
          }
  
          final int launchFlags = intent.getFlags();
  
          // 2. FLAG_ACTIVITY_FORWARD_RESULT は横断的な伝達機能を持つ
  
          if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
  
              // startActivityForResult メソッドを再利用できません
              if (requestCode >= 0) {
                  // そうでなければ START_FORWARD_AND_REQUEST_CONFLICT エラーが発生します
                  SafeActivityOptions.abort(options);
                  return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
              }
              resultRecord = sourceRecord.resultTo;
              if (resultRecord != null && !resultRecord.isInStackLocked()) {
                  resultRecord = null;
              }
  
              // setResult の結果を元のアクティビティに変換
              resultWho = sourceRecord.resultWho;
              requestCode = sourceRecord.requestCode;
              sourceRecord.resultTo = null;
              if (resultRecord != null) {
                  resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
              }
              if (sourceRecord.launchedFromUid == callingUid) {
                  callingPackage = sourceRecord.launchedFromPackage;
                  callingFeatureId = sourceRecord.launchedFromFeatureId;
              }
          }
  
          ... 省略部分
  
          // 3. この Intent がサポートされているかどうかを判断
          if (err == ActivityManager.START_SUCCESS && aInfo == null) {
              err = ActivityManager.START_CLASS_NOT_FOUND;
          }
  
          if (err == ActivityManager.START_SUCCESS && sourceRecord != null
                  && sourceRecord.getTask().voiceSession != null) {
              // 音声関連
              if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
                      && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
                  try {
                      intent.addCategory(Intent.CATEGORY_VOICE);    // 音声
                      if (!mService.getPackageManager().activitySupportsIntent(
                              intent.getComponent(), intent, resolvedType)) {
                          Slog.w(TAG, "Activity being started in current voice task does not support "
                                  + "voice: " + intent);
                          err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
                      }
                  } catch (RemoteException e) {
                      Slog.w(TAG, "Failure checking voice capabilities", e);
                      err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
                  }
              }
          }
  
          ...省略部分
  
          // 4. 三つの判断を経て、呼び出し元がアクティビティを起動する権限を持っているかを判断
          boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
                  requestCode, /* 省略部分のパラメータ */);
  
          abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
                  callingPid, resolvedType, aInfo.applicationInfo);
          abort |= !mService.getPermissionPolicyInternal().checkStartActivity(intent, callingUid,
                  callingPackage);
  
          boolean restrictedBgActivity = false;
          if (!abort) {
              try {
                  restrictedBgActivity = shouldAbortBackgroundActivityStart(callingUid,
                          callingPid, callingPackage, realCallingUid, realCallingPid, callerApp,
                          request.originatingPendingIntent, request.allowBackgroundActivityStart,
                          intent);
              } /* 省略 finally */
          }
  
          ... 省略部分
  
          // 5. ActivityRecord を作成し、さまざまな判断結果を記録します
          final ActivityRecord r = new ActivityRecord.Builder(mService)
                  .setCaller(callerApp)
                  .setLaunchedFromPid(callingPid)
                  .setLaunchedFromUid(callingUid)
                  .setLaunchedFromPackage(callingPackage)
                  .setLaunchedFromFeature(callingFeatureId)
                  .setIntent(intent)
                  .setResolvedType(resolvedType)
                  .setActivityInfo(aInfo)
                  .setConfiguration(mService.getGlobalConfiguration())
                  .setResultTo(resultRecord)
                  .setResultWho(resultWho)
                  .setRequestCode(requestCode)
                  .setComponentSpecified(request.componentSpecified)
                  .setRootVoiceInteraction(voiceSession != null)
                  .setActivityOptions(checkedOptions)
                  .setSourceRecord(sourceRecord)
                  .build();
          mLastStartActivityRecord = r;
  
          ... 省略部分
  
          final ActivityStack resultStack = resultRecord == null
                  ? null : resultRecord.getRootTask();
  
  
          // @ startActivityUnchecked メソッドの分析
          mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
                  request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,
                  restrictedBgActivity, intentGrants);
  
          ...
  
          return mLastStartActivityResult;
  
      }

ActivityStarter は ActivityRecord#Builder に依存し、ビルダーパターンを介して ActivityRecord オブジェクトを作成します。このアクティビティには呼び出し元、目標アクティビティが記録されます。

説明者代表するアクティビティクラス
PKMSActivityInfo (AndroidManifest 内のノード情報)
AMSActivityRecord

ActivityStarter - アクティビティ起動プロセス#

重要な点には以下が含まれます。

  • アクティビティの目標タスクを決定する
  • アクティビティ起動アニメーションを表示する
  • RootWindowContainer にアクティビティのウィンドウを起動するよう通知する
  • executeRequest 関数内で、最終的に startActivityUnchecked メソッドが呼び出され、以下にこれらのメソッドの機能を簡単に説明します。
ActivityStarter 重要メソッド機能
executeRequest権限、呼び出し元(クライアント側の IBinder)などをチェック
startActivityUncheckedチェック後、アクティビティを起動する準備をし、起動に失敗した場合は削除も担当
startActivityInner主にアクティビティスタックの制御を行い、アクティビティをスタックに追加するか、または Intent に通知します
  // ActivityStarter.java
  
      // executeRequest がこの関数を呼び出します
      private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
                  IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                  int startFlags, boolean doResume, ActivityOptions options, Task inTask,
                  boolean restrictedBgActivity, NeededUriGrants intentGrants) {
          int result = START_CANCELED;
          
          final Task startedActivityRootTask;
          
          ... 
              
          try {
              ...
              // @ startActivityInner メソッドの分析
              result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
                      startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);
              ...
          } finally {
              ...
              startedActivityRootTask = handleStartResult(r, result);
              ...
          }
  
          postStartActivityProcessing(r, result, startedActivityStack);
  
          return result;
      }

ActivityStarter#startActivityInner メソッド:他のフラグが設定されていない場合、最終的に Task#startActivityLocked メソッドが起動されます。このメソッドには二つの重要なポイントがあります。
ActivityStarter の mSourceRootTaskmTargetRootTask メンバーを定義し、アクティビティの出所と目標スタック(タスク)を決定します。

  // ActivityStarter.java
  
  private Task mSourceRootTask;    // 出所
  private Task mTargetRootTask;    // 起動目標
  
  ActivityRecord mStartActivity;
  
  private final ActivityTaskManagerService mService;
  private final RootWindowContainer mRootWindowContainer;
  
  int startActivityInner(final ActivityRecord r, 
                         ActivityRecord sourceRecord, 
                         /* 省略部分のパラメータ */) {
  
      ...省略部分
  
      // 再利用可能なタスクを取得
      final Task reusedTask = getReusableTask();
  
      final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask();
  
      // 新しいタスクを作成するかどうか
      final boolean newTask = targetTask == null;
      mTargetTask = targetTask;
      computeLaunchParams(r, sourceRecord, targetTask);
  
      // 現在の ActivtyRecord が目標タスクで起動できるかどうかを判断
      int startResult = isAllowedToStart(r, newTask, targetTask);
      if (startResult != START_SUCCESS) {
          return startResult;
      }
  
      // もしタスクを再利用する場合、目標スタックのトップアクティビティを取得します(まだ終了していない)
      final ActivityRecord targetTaskTop = newTask
          ? null : targetTask.getTopNonFinishingActivity();
      if (targetTaskTop != null) {
          // タスクを再利用
          startResult = recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants);
          if (startResult != START_SUCCESS) {
              return startResult;
          }
      } else {
          mAddingToTask = true;
      }
  
      ...
  
      if (mTargetRootTask == null) {
          mTargetRootTask = getLaunchRootTask(mStartActivity, mLaunchFlags, targetTask, mOptions);
      }
      
      // 現在の分析状況に応じて、新しいタスクを起動します
      if (newTask) {
          final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
                  ? mSourceRecord.getTask() : null;
          // 新しいタスクを設定
          setNewTask(taskToAffiliate);
      } else if (mAddingToTask) {
          addOrReparentStartingActivity(targetTask, "adding to task");
      }
  
      ...省略部分
  
      return START_SUCCESS;    
  }

Intent を分析し、アクティビティの起動画面を設定する startActivityLocked、アクティビティを起動する resumeFocusedTasksTopActivities を呼び出します。

  // ActivityStarter.java
  
  private Task mSourceRootTask;
  private Task mTargetRootTask;
  
  ActivityRecord mStartActivity;
  
  private final ActivityTaskManagerService mService;
  private final RootWindowContainer mRootWindowContainer;
  
  
  int startActivityInner(final ActivityRecord r, 
                         ActivityRecord sourceRecord,    // 呼び出し元の情報
         /* 省略部分のパラメータ */) {
  
      ...
  
      // @ 1. Intent を分析し、アクティビティの起動画面を設定します(まず分析)
      mTargetRootTask.startActivityLocked(mStartActivity,
              topStack != null ? topStack.getTopNonFinishingActivity() : null, newTask,
              mKeepCurTransition, mOptions);
  
      if (mDoResume) { // このアクティビティが存在する場合
          final ActivityRecord topTaskActivity =
                  mStartActivity.getTask().topRunningActivityLocked();
  
          if (!mTargetRootTask.isTopActivityFocusable()
                  || (topTaskActivity != null && topTaskActivity.isTaskOverlay()
                  && mStartActivity != topTaskActivity)) {
  
  			// もしフォーカス可能でない場合は復帰できませんが、
  			// それでもこのアクティビティを可視化します
  			// つまり、可視の一時停止状態です
              mTargetRootTask.ensureActivitiesVisible(null /* starting */,
                      0 /* configChanges */, !PRESERVE_WINDOWS);
              mTargetRootTask.mDisplayContent.executeAppTransition();
          } else {
  
              // スタックのトップアクティビティがフォーカスされていない場合は、前面に移動します
              if (mTargetRootTask.isTopActivityFocusable()
                      && !mRootWindowContainer.isTopDisplayFocusedRootTask(mTargetRootTask)) {
                  mTargetRootTask.moveToFront("startActivityInner");
              }
  
              // 2. @ 新しいアクティビティを開始します(後で分析)
              mRootWindowContainer.resumeFocusedTasksTopActivities(
                      mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
          }
      }
  
      ...
  
      return START_SUCCESS;    
  }

タスク - Intent の分析 - アクティビティ起動画面の追加#

Task#startActivityLocked メソッド:主に ユーザーが設定した Intent を判断し、アクティビティの初期読み込み画面を設定します。最後に ActivityRecord を介してアクティビティの開始アニメーションを起動します

  // TaskFragment.java
  
  class TaskFragment extends WindowContainer<WindowContainer> {
      final ActivityTaskSupervisor mTaskSupervisor;
      
      ...
  }
  
  // ------------------------------------------------------
  // Task.java
  
  class Task extends TaskFragment {
  
      void startActivityLocked(ActivityRecord r, @Nullable ActivityRecord focusedTopActivity,
          boolean newTask, boolean keepCurTransition, ActivityOptions options,
          @Nullable ActivityRecord sourceRecord) {
          
          Task rTask = r.getTask();
          final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront();
          final boolean isOrhasTask = rTask == this || hasChild(rTask);
  
          ...
  
          final Task activityTask = r.getTask();
          if (task == activityTask && mChildren.indexOf(task) != (getChildCount() - 1)) {
              mStackSupervisor.mUserLeaving = false;
              ...
          }
          task = activityTask;
  
          ... 省略 デバッグメッセージ
  
          // {@code allowMoveToFront} が false の場合、遷移アニメーションと開始ウィンドウは必要ありません。
          // なぜなら、アクティビティは表示されないからです。
          if ((!isHomeOrRecentsStack() || 
               hasActivity()) && allowMoveToFront) {
              
              final DisplayContent dc = getDisplay().mDisplayContent;
  
              ... 省略 デバッグメッセージ
  
              if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
                  // アニメーションなし
                  dc.prepareAppTransition(TRANSIT_NONE, keepCurTransition);
                  // アニメーションなしの intent を追加
                  mStackSupervisor.mNoAnimActivities.add(r);
              } else {
                  // 遷移アニメーションが必要
                  int transit = TRANSIT_ACTIVITY_OPEN;
                  if (newTask) {
                      if (r.mLaunchTaskBehind) {
                          transit = TRANSIT_TASK_OPEN_BEHIND;
  
                      } else if (getDisplay().isSingleTaskInstance()) {
                          transit = TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
                          keepCurTransition = false;
                          
                      } else {
                          if (canEnterPipOnTaskSwitch(focusedTopActivity,
                                  null /* toFrontTask */, r, options)) {
                              focusedTopActivity.supportsEnterPipOnTaskSwitch = true;
                          }
                          transit = TRANSIT_TASK_OPEN;
                      }
                  }
                  dc.prepareAppTransition(transit, keepCurTransition);
                  mStackSupervisor.mNoAnimActivities.remove(r);
              }
              
              
              boolean doShow = true;
              if (newTask) {        // 新しいスタックを起動
                  
                  if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
                      resetTaskIfNeeded(r, r);
                      doShow = topRunningNonDelayedActivityLocked(null) == r;
                  }
              } else if (options != null && options.getAnimationType()
                      == ActivityOptions.ANIM_SCENE_TRANSITION) {
                  doShow = false;
              }
  
              if (r.mLaunchTaskBehind) {
                  ...
              } else if (SHOW_APP_STARTING_PREVIEW && doShow) {
                  ...
  
                  // @ showStartingWindow メソッドを追跡
                  // r は ActivityRecord 
                  r.showStartingWindow(prev, newTask, isTaskSwitch(r, focusedTopActivity));
              }
          } else {
              ...
          }
      }
  
  }

RootWindowContainer - スタックのトップアクティビティを起動#

RootWindowContainer#resumeFocusedTasksTopActivities メソッド:タスクスタックのトップアクティビティを見つけて表示します(フォーカス可能なアクティビティ)。

  // RootWindowContainer.java
  
  ActivityTaskSupervisor mTaskSupervisor;
  
  boolean resumeFocusedTasksTopActivities(
          Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions) {
      // @ resumeFocusedTasksTopActivities を追跡
      return resumeFocusedTasksTopActivities(targetRootTask, target, targetOptions,
              false /* deferPause */);
  }
  
  boolean resumeFocusedTasksTopActivities(
          Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions,
          boolean deferPause) {
  
      if (!mTaskSupervisor.readyToResume()) {
          return false;
      }
      boolean result = false;
      if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()
              || getTopDisplayFocusedRootTask() == targetRootTask)) {
          result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,
                  deferPause);
      }
      for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
          final DisplayContent display = getChildAt(displayNdx);
          final boolean curResult = result;
          boolean[] resumedOnDisplay = new boolean[1];
          display.forAllRootTasks(rootTask -> {
  
              // トップアクティビティ
              final ActivityRecord topRunningActivity = 
                      rootTask.topRunningActivity();
              
              if (!rootTask.isFocusableAndVisible() || topRunningActivity == null) {
                  return;
              }
  
              if (rootTask == targetRootTask) {
                  // すでに resumed 状態である場合、再度 resumed しない
                  resumedOnDisplay[0] |= curResult;
                  return;
              }
  
              if (rootTask.getDisplayArea().isTopRootTask(rootTask)
                      && topRunningActivity.isState(RESUMED)) {
                  // MoveTaskToFront 操作からの遅延アプリ遷移を開始しますが、トップタスクとその表示のルートタスクのみを考慮します。
                  rootTask.executeAppTransition(targetOptions);
              } else {
                  resumedOnDisplay[0] |= topRunningActivity.makeActiveIfNeeded(target);
              }
          });
  
          result |= resumedOnDisplay[0];
          if (!resumedOnDisplay[0]) {        // まだ起動していない
  
              // display は DisplayContent オブジェクトです
              final Task focusedRoot = display.getFocusedRootTask();
              if (focusedRoot != null) {
  
                  // @ resumeTopActivityUncheckedLocked メソッドを続けて分析
                  result |= focusedRoot.resumeTopActivityUncheckedLocked(target, targetOptions);
  
              } else if (targetRootTask == null) {
                  // ... タスクが見つからない場合、HomeActivity を起動します
  
                  result |= resumeHomeActivity(null /* prev */, "no-focusable-task",
                          display.getDefaultTaskDisplayArea());
              }
          }
      }
      return result;
  }

まずタスクとウィンドウの関係を見てみましょう。タスクは ActivityRecord に関連し、複数のタスクを連結し、ActivityRecord は複数のウィンドウ画面を管理できます。
Task#resumeTopActivityUncheckedLocked 関数を呼び出し、その目的はタスクの末端ノードを見つけ、resumeTopActivityInnerLocked 関数を実行します。

  // Task.java
  
  boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options,
          boolean deferPause) {
      if (mInResumeTopActivity) {
          // 再帰を開始しないでください。
          return false;
      }
      boolean someActivityResumed = false;
      try {
          // 再帰を防ぐために保護します。
          mInResumeTopActivity = true;
  
          // 末端ノードを見つける
          if (isLeafTask()) {
              if (isFocusableAndVisible()) {
  				// 再帰が終了し、利用可能なアクティビティが見つかれば起動します
  				// @ resumeTopActivityInnerLocked メソッドの分析
                  someActivityResumed = resumeTopActivityInnerLocked(
                      prev, 
                      options, 
                      deferPause);
              }
          } else {
              int idx = mChildren.size() - 1;
              while (idx >= 0) {
                  final Task child = (Task) getChildAt(idx--);
  
                  // トップでフォーカス可能なアクティビティを見つける
                  if (!child.isTopActivityFocusable()) {
                      continue;
                  }
  
                  // このタスクは表示されていません
                  if (child.getVisibility(null /* starting */) != TASK_VISIBILITY_VISIBLE) {
                      break;
                  }
  
                  // resumeTopActivityUncheckedLocked 関数を再帰的に呼び出します
                  someActivityResumed |= child.resumeTopActivityUncheckedLocked(prev, options,
                          deferPause);
  
                  if (idx >= mChildren.size()) {
                      idx = mChildren.size() - 1;
                  }
              }
          }
  
          // スタックのトップアクティビティ
          final ActivityRecord next = topRunningActivity(true /* focusableOnly */);
          if (next == null || !next.canTurnScreenOn()) {
              checkReadyForSleep();
          }
      } finally {
          mInResumeTopActivity = false;
      }
      return someActivityResumed;
  }

目標の葉ノードを見つけた後、Task#resumeTopActivityInnerLocked メソッドはアクティビティの起動エントリポイントです。この関数は attachedToProcess を介して目標プロセスが接続可能かどうかを判断します。

  • すでに起動している場合は、scheduleTransaction を介してアクティビティを復元します。
  • 起動していない場合は、startSpecificActivity を介してアクティビティを起動します。
  // Task.java
  
  final ActivityTaskManagerService mAtmService;
  final ActivityTaskSupervisor mTaskSupervisor;
  
  private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,
          boolean deferPause) {
  
      ActivityRecord next = topRunningActivity(true /* focusableOnly */);
  
      ... 省略部分
  
      // アプリプロセスに接続できるかどうかを判断
      if(next.attachedToProcess()) {
          // 前のアクティビティが半透明の場合、可視性を強制的に更新し、WM の開いているアプリのリストに追加します。
          final boolean lastActivityTranslucent = lastFocusedRootTask != null
                  && (lastFocusedRootTask.inMultiWindowMode()
                  || (lastFocusedRootTask.mLastPausedActivity != null
                  && !lastFocusedRootTask.mLastPausedActivity.occludesParent()));
  
          if (!next.mVisibleRequested || next.stopped || lastActivityTranslucent) {
              // 可視に設定
              next.setVisibility(true);
          }
          // 遅いアプリに関する情報を収集するために起動 ticks をスケジュールします。
          next.startLaunchTickingLocked();
  
          ActivityRecord lastResumedActivity =
                  lastFocusedRootTask == null ? null : lastFocusedRootTask.getResumedActivity();
          final ActivityState lastState = next.getState();
          mAtmService.updateCpuStats();
  
          ... 省略 Log
  
          // State を Resumed に設定
          next.setState(RESUMED, "resumeTopActivityInnerLocked");
  
          boolean notUpdated = true;
  
          ... 省略部分
  
          try {
  			// クライアント側に送信する情報
  			// next.appToken は目標アプリの ApplicationThread(Binder Server クラス)です
              final ClientTransaction transaction =
                      ClientTransaction.obtain(
                              next.app.getThread(), 
                              next.appToken
              );
              
              // すべての保留中の結果を配信します。
              ArrayList<ResultInfo> a = next.results;
              if (a != null) {
                  final int N = a.size();
                  if (!next.finishing && N > 0) {
                      ... 省略 Log メッセージ
  
                      // コールバックを追加
                      // 注意 ActivityResultItem はアプリ側で呼び出されます
                      transaction.addCallback(ActivityResultItem.obtain(a));
                  }
              }
              if (next.newIntents != null) {
                  transaction.addCallback(
                          NewIntentItem.obtain(next.newIntents, true /* resume */));
              }
  
              // アプリの停止状態をクリアします
              next.notifyAppResumed(next.stopped);
  
              ... 省略 Log
  
              mAtmService.getAppWarningsLocked().onResumeActivity(next);
  
              ... 省略部分
  
              transaction.setLifecycleStateRequest(
                      ResumeActivityItem.obtain(next.app.getReportedProcState(),
                              dc.isNextTransitionForward()));
  
              // @ 1. scheduleTransaction を分析 !!
              mAtmService.getLifecycleManager().scheduleTransaction(transaction);
  
              ... 省略 Log
          } catch (Exception e) {
  
              ... 省略部分
  
              // アクティビティを再起動します
              mTaskSupervisor.startSpecificActivity(next, true, false);
              return true;
          }
  
          ... 省略部分
  
      } else {
          ... 省略部分
  
          // @ 2. startSpecificActivity を分析し、新しいアクティビティを起動します
          mTaskSupervisor.startSpecificActivity(next, true, true);
      }
      return true;
  }

既存のアクティビティを起動#

Task#resumeTopActivityInnerLocked 関数は目標 ActivityRecord がすでに起動しているかどうかを判断し、すでに起動している場合は ClientLifecycleManager#scheduleTransaction を介してアクティビティを復元します。

ClientLifecycleManager - scheduleTransaction#

最初のポイントは Binder クライアントとサーバーの変換 です。ここでは ClientTransaction を介してアプリ側の Binder サーバー(すなわち ActivityThread#ApplicationThread クラス)を呼び出します。

  // ClientLifecycleManager.java
  
  class ClientLifecycleManager {
  
      void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
          // IApplicationThread はアプリ側
          final IApplicationThread client = transaction.getClient();
          transaction.schedule();
  
          if (!(client instanceof Binder)) {
  			// クライアントが Binder でない場合、これはリモート呼び出しです。このオブジェクトは回収できます。
  			// オブジェクトが Binder であれば、クライアント(アプリ)側が自分で回収します。
              transaction.recycle();
          }
      }
  }

ClientTransaction は目標アプリの ApplicationThread(すなわち目標アプリの Binder サーバー)を呼び出します。

  // ClientTransaction.java
  
      /** ターゲットクライアント。 */
      private IApplicationThread mClient;    // IApplicationThread は目標アプリの Binder サーバー
  
      public void schedule() throws RemoteException {
          mClient.scheduleTransaction(this);
      }

ApplicationThread - scheduleTransaction アクティビティを起動#

ApplicationThread は ActivityThread の内部クラスで、Binder サーバーの部分を実装しています(各アプリには ApplicationThread が実装されており、AMS がアクティビティを操作できるようにしています)

  // ActivityThread.java
  public final class ActivityThread extends ClientTransactionHandler
          implements ActivityThreadInternal {
  
      // AIDL の IApplicationThread.Stub クラスを実装
      private class ApplicationThread extends IApplicationThread.Stub {
  
          @Override
          public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
              // ClientTransactionHandler の親クラスを確認
              ActivityThread.this.scheduleTransaction(transaction);
          }
      }
  
  }

ActivityThread の親クラスの scheduleTransaction メソッドを呼び出します(すなわち ClientTransactionHandler、ClientTransactionHandler は AMS からの情報を処理します)。

  // ClientTransactionHandler.java
  public abstract class ClientTransactionHandler {
  
      // 目標アクティビティの起動を準備します
      void scheduleTransaction(ClientTransaction transaction) {
          transaction.preExecute(this);
  
          // 主に sendMessage 関数を見ます
          // ここで EXECUTE_TRANSACTION を渡すと最終的にどう処理されるか見てみましょう
          sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
      }
  
      // ActivityThread が実装
      abstract void sendMessage(int what, Object obj);
  }

ActivityThread は sendMessage メソッドを実装し、アクティビティを起動する場合は Handler に EXECUTE_TRANSACTION 情報を渡し、次に TransactionExecutor#execute 関数が処理します。

  // ActivityThread.java
  
      final H mH = new H();
  
      private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);
  
      // H は Handler 
      class H extends Handler {
  
          public static final int EXECUTE_TRANSACTION = 159;
  
          public void handleMessage(Message msg) {
  
              switch (msg.what) {
                  ... 省略部分
  
                  case EXECUTE_TRANSACTION:
                      // AMS から渡された ClientTransaction オブジェクトに対応
                      final ClientTransaction transaction = (ClientTransaction) msg.obj;
                      mTransactionExecutor.execute(transaction);
                      if (isSystem()) {
  						// もしシステムプロセスであれば、クライアント側でオブジェクトを回収します。
  						// そうでなければ ClientLifecycleManager が回収します。
  						// この関数の情報が処理される前にオブジェクトが回収されないようにします!!
                          transaction.recycle();
                      }
                      break;   
              }
      }
  
      private void sendMessage(int what, 
                               Object obj,  // EXECUTE_TRANSACTION
                               int arg1, int arg2, boolean async) {
          ... 省略 Log メッセージ
  
          Message msg = Message.obtain();
          msg.what = what;
          msg.obj = obj;
          msg.arg1 = arg1;
          msg.arg2 = arg2;
          if (async) {
              msg.setAsynchronous(true);
          }
          mH.sendMessage(msg);
      }
  

TransactionExecutor#execute 関数:すべての ClientTransactionItem (AMS から送られた) の execute 関数を実行します。

  // TransactionExecutor.java
  
      private ClientTransactionHandler mTransactionHandler;
  
      public void execute(ClientTransaction transaction) {
          ... 省略部分
  
          // executeCallbacks を分析
          executeCallbacks(transaction);
          executeLifecycleState(transaction);
  
          ... 省略部分
      }
  
      public void executeCallbacks(ClientTransaction transaction) {
          final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
  
          ...省略部分
  
          for (int i = 0; i < size; ++i) {
              // ClientTransactionItem は抽象で、実装は ActivityResultItem です
              final ClientTransactionItem item = callbacks.get(i);
  
              ... 省略部分
  
              item.execute(mTransactionHandler, token, mPendingActions);
              item.postExecute(mTransactionHandler, token, mPendingActions);
  
              ... 省略部分
          }
      }

ActivityResultItem - execute が Instrumentation を呼び出す#

ここでの ClientTransactionItem は抽象クラスで、渡されるオブジェクトによって異なる実装の詳細があります。

  // ActivityResultItem.java
  
  public class ActivityResultItem extends ActivityTransactionItem {
      @Override
      public void execute(ClientTransactionHandler client, ActivityClientRecord r,
              PendingTransactionActions pendingActions) {
  
          // @ handleSendResult メソッドを分析
          client.handleSendResult(r, mResultInfoList, "ACTIVITY_RESULT");
      }
  }
  
  // ---------------------------------------------------------------
  // ActivityThread.java
  
  @Override
  public void handleSendResult(ActivityClientRecord r, List<ResultInfo> results, String reason) {
      final boolean resumed = !r.paused;
  
      if (!r.activity.mFinished && r.activity.mDecor != null
              && r.hideForNow && resumed) {
          updateVisibility(r, true);
      }
  
      if (resumed) {
          try {
              // これでアイドル状態です。
              r.activity.mCalled = false;
              mInstrumentation.callActivityOnPause(r.activity);
              if (!r.activity.mCalled) {
                  throw new SuperNotCalledException(
                      "Activity " + r.intent.getComponent().toShortString()
                      + " did not call through to super.onPause()");
              }
          } /*省略 catch*/
      }
  
      checkAndBlockForNetworkAccess();
      deliverResults(r, results, reason);
      if (resumed) {
          // 目標 ++ onResume ++ を実行します
          r.activity.performResume(false, reason);
      }
  }
  
  // ---------------------------------------------------------------
  // Activity.java
  
  final void performResume(boolean followedByPause, String reason) {
      
      ... 省略部分
          
      // mResumed はインストゥルメンテーションによって設定されます
      mInstrumentation.callActivityOnResume(this);
          
      ... 省略部分
  }

Instrumentation が onResume を呼び出す#

最終的に Activity#onResume 関数は Instrumentation を介して呼び出されます。

  // /app/Instrumentation.java
  
      public void callActivityOnResume(Activity activity) {
          activity.mResumed = true;
          
          // Activity#onResume 関数を呼び出します
          activity.onResume();
  
          if (mActivityMonitors != null) {
              synchronized (mSync) {
                  final int N = mActivityMonitors.size();
                  for (int i=0; i<N; i++) {
                      final ActivityMonitor am = mActivityMonitors.get(i);
                      am.match(activity, activity, activity.getIntent());
                  }
              }
          }
      }
  

新しいアクティビティを起動#

Task#resumeTopActivityInnerLocked 関数は目標 ActivityRecord がすでに起動しているかどうかを判断し、すでに起動している場合は ActivityTaskSupervisor#startSpecificActivity を介してアクティビティを起動します。

ActivityTaskSupervisor - startSpecificActivity#

ここでの鍵は realStartActivityLocked 関数を呼び出すことです。ここでは ClientTransaction オブジェクトを取得し、ActivityTaskManagerService を介して ClientTransaction オブジェクトを目標(起動する)アクティビティに渡します。その後、そのアクティビティはそのオブジェクトを使用します。

  // ActivityTaskSupervisor.java
  
      final ActivityTaskManagerService mService
      
      void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
          // このアクティビティのアプリケーションがすでに実行中ですか?
          final WindowProcessController wpc =
                  mService.getProcessController(r.processName, r.info.applicationInfo.uid);
          boolean knownToBeDead = false;
          if (wpc != null && wpc.hasThread()) {
              try {
                  realStartActivityLocked(r, wpc, andResume, checkConfig);
                  return;
              } /* 省略 catch */
  
              // デッドオブジェクト例外がスローされた場合 -- アプリケーションを再起動します。
              knownToBeDead = true;
          }
  
          ...省略部分
      }
  
      boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
          boolean andResume, boolean checkConfig) throws RemoteException {
  
          ... 省略部分
          
          try {
              ... 省略部分
              
              try {
                      // アクティビティ起動トランザクションを作成します。
                  final ClientTransaction clientTransaction = ClientTransaction.obtain(
                          proc.getThread(), r.appToken);
                  
                  final boolean isTransitionForward = r.isTransitionForward();
                 
  				// 1. コールバックを追加することが重要です!!
  				// その後起動されるアクティビティは LaunchActivityItem クラスを使用します
                  clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                          System.identityHashCode(r), r.info,
                          // TODO: これがマージされた構成を取るようにする必要があります。
                          mergedConfiguration.getGlobalConfiguration(),
                          mergedConfiguration.getOverrideConfiguration(), r.compat,
                          r.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor,
                          proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(),
                          results, newIntents, r.takeOptions(), isTransitionForward,
                          proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
                          r.createFixedRotationAdjustmentsIfNeeded(), r.shareableActivityToken,
                          r.getLaunchedFromBubble()));
                  
                  // 最終的な状態を設定します。
                  final ActivityLifecycleItem lifecycleItem;
                  if (andResume) {
                      lifecycleItem = ResumeActivityItem.obtain(isTransitionForward);
                  } else {
                      lifecycleItem = PauseActivityItem.obtain();
                  }
                  
                  clientTransaction.setLifecycleStateRequest(lifecycleItem);
                  
                  // 2. トランザクションをスケジュールします。(続けて分析)
                  mService.getLifecycleManager().scheduleTransaction(clientTransaction);
                  
                  ...省略部分
                      
              } /*省略 catch*/
  
              ...省略部分
  
          } /*省略 catch*/
      
      }

LaunchActivityItem - execute が Instrumentation を呼び出す#

  // LaunchActivityItem.java
  
  public class LaunchActivityItem extends ClientTransactionItem {
  
      @Override
      public void execute(ClientTransactionHandler client, IBinder token,
              PendingTransactionActions pendingActions) {
  
          ActivityClientRecord r = client.getLaunchingActivity(token);
  
          // handleLaunchActivity は抽象メソッドです
          // ActivityThread はその実装クラスです
          client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
      }
  
  }
  
  
  // -------------------------------------------------------------
  // ActivityThread.java
  public final class ActivityThread extends ClientTransactionHandler
          implements ActivityThreadInternal {
  
      @Override
      public Activity handleLaunchActivity(ActivityClientRecord r,
              PendingTransactionActions pendingActions, Intent customIntent) {
          ... 省略部分
  
          final Activity a = performLaunchActivity(r, customIntent);
  
          ... 省略部分
      }
  }
  

ActivityThread#performLaunchActivity:ContextImpl を作成し、Instrumentation クラスを介してアクティビティ、アプリケーションなどのオブジェクトを作成します。

 // ActivityThread.java
 public final class ActivityThread extends ClientTransactionHandler
         implements ActivityThreadInternal {
 
     private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
         ...省略部分
 
         // コンテキストを作成
         ContextImpl appContext = createBaseContextForActivity(r);
 
         Activity activity = null;
         try {
             // 反射を使用してアクティビティ、アプリケーションを作成します
             java.lang.ClassLoader cl = appContext.getClassLoader();
             activity = mInstrumentation.newActivity(
                     cl, component.getClassName(), r.intent);
             StrictMode.incrementExpectedActivityCount(activity.getClass());
             r.intent.setExtrasClassLoader(cl);
             r.intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo),
                     appContext.getAttributionSource());
             if (r.state != null) {
                 r.state.setClassLoader(cl);
             }
         } /* 省略 catch */
 
 
         try {
             Application app = r.packageInfo.makeApplication(false, mInstrumentation);
 
             ... 省略部分
 
             if (activity != null) {
             
                 ... 省略部分
                 
                 // アクティビティオブジェクトにアプリケーションとコンテキストをバインドします!
                 if (r.isPersistable()) {
                     mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                 } else {
                     mInstrumentation.callActivityOnCreate(activity, r.state);
                 }
                 
                 if (!activity.mCalled) {
                     throw new SuperNotCalledException(
                         "Activity " + r.intent.getComponent().toShortString() +
                         " did not call through to super.onCreate()");
                 }
                 r.activity = activity;
                 
                 ...
                 
             }
             
         } /* 省略 catch */
 
         return activity;
     }
 
 }

Instrumentation - アクティビティ、アプリケーションを作成#

Instrumentation#newActivity: 反射を使用してアクティビティオブジェクトを作成します。

  // Instrumentation.java
  
      public Activity newActivity(Class<?> clazz, Context context, 
              IBinder token, Application application, Intent intent, ActivityInfo info, 
              CharSequence title, Activity parent, String id,
              Object lastNonConfigurationInstance) throws InstantiationException,
              IllegalAccessException {
          Activity activity = (Activity)clazz.newInstance();
          ActivityThread aThread = null;
          // Activity.attach は非 null のアプリケーションオブジェクトを期待します。
          if (application == null) {
              // アプリケーションオブジェクトを作成
              application = new Application();
          }
          activity.attach(context, aThread, this, token, 0 /* ident */, application, intent,
                  info, title, parent, id,
                  (Activity.NonConfigurationInstances)lastNonConfigurationInstance,
                  new Configuration(), null /* referrer */, null /* voiceInteractor */,
                  null /* window */, null /* activityConfigCallback */, null /*assistToken*/,
                  null /*shareableActivityToken*/);
          return activity;
      }

Instrumentation - onCreate を呼び出す#

ActivityThread#performLaunchActivity 関数は Instrumentation を使用し、Instrumentation を介して Activity#onCreate 関数を呼び出します。

  // Instrumentation.java
  
      public void callActivityOnCreate(Activity activity, Bundle icicle) {
          prePerformCreate(activity);
  
          // onCreate を呼び出します
          activity.performCreate(icicle);
          postPerformCreate(activity);
      }
  
  // -------------------------------------------------------------
  // Activity.java
      final void performCreate(Bundle icicle) {
          performCreate(icicle, null);
      }
  
      final void performCreate(Bundle icicle, PersistableBundle persistentState) {
          if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
              Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "performCreate:"
                      + mComponent.getClassName());
          }
          ... 省略部分
  
          // onCreate 関数を呼び出します
          if (persistentState != null) {
              onCreate(icicle, persistentState);
          } else {
              onCreate(icicle);
          }
  
          ... 省略部分
      }
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。