I.はじめに
AMS (ActivityManagerService) は Activity 管理のコア コンポーネントであり、Activity の起動、ライフサイクル管理、スタック管理などの機能を提供します. AMS に精通していると、Activity の動作原理を理解するのに役立ちます.
AMS にはコンテンツが多すぎて、網羅的に分析することはできません.Activity の開始、Activity メッセージの返信 (onActivityResult)、Activity スタックの管理、および AMS、WMS の共同作業から、これらの点を深く理解しましょう。 、および PMS. 、ソース コードを組み合わせるプロセスを通じて、AMS についての理解が深まりました。
この記事を読む前に、アプリケーション層でのstartActivity のライフサイクルに関する著者の記事を 必ずお読みください. 記事で言及されている 3 つの質問を目指して、フレームワーク層で答えを探します. この記事はプロセスです. Android11ソースコードによる追跡の
1. 同じプロセスで startActivity メソッドを呼び出すプロセスは何ですか?
2. 別のプロセスでアクティビティを開始する場合、startActivity の呼び出しプロセスは何ですか?
3. 新しいアクティビティを開始するには、最初に onPause メソッドを実行し、新しいインターフェイスが表示された後に onStop メソッドを実行するのはなぜですか?
2.AMS コラボレーション
最初に歴史的なバージョンの変更について学びます
Android 10 では、将来的にデザインをより明確にするために、Android は AMS に多くの変更を加えました. Android の最終的な目標は、アクティビティとウィンドウを統合することです.
ActivityTaskManagerService (ATMS) の概念は、Android 10 で導入されました。
Android 9.0 以前のバージョンでは、アクティビティ管理は AMS と WMS の連携によって完成されており、AMS と WMS の両方で同様の機能を持つエンティティが存在していました.大量のコード冗長性に加えて、両者の連携も非常に困難です. .
Android 10.0 のコード変更から判断すると、Google の最終的な目標はアクティビティとウィンドウを統合することです
AMS配下のアクティビティ管理に関するコードをWMSディレクトリに移動し、activityStack、activityRecordなどのファイルをWMSディレクトリに移動し、ウィンドウで一元管理する.AMS内のファイルの一部を分割し、元のアクティビティと一緒に処理されるファイルは分割され、アクティビティの関連部分は個別に分割され、統合
管理のために WMS に移動されます。
たとえば、ActivityManagerService.java は、ActivityManagerService.java と ActivityTaskManagerService.java の 2 つのファイルに分割されます。
アクティビティの開始はActivityTaskManagerService.javaが担当しており、
アクティビティとウィンドウの一元管理がWMSで完結するため、これまでのDispayWindowControllerやstackWindowControllerは途中で調整する必要がなくなり、ディスプレイやスタック、タスクなどを・一元的に管理できる。最終的には完全な統合が必要. スタックを例にとると, taskstack の機能は完了後に activityStack に完全に統合されます. 現在, activityStack には taskstack のみが含まれています. 作成および管理プロセスもそれに応じて変更されました。
いくつかの主要なクラスの紹介
クラス名 | 機能説明 |
---|---|
計装 | アクティビティとアプリケーションのライフサイクルの呼び出しを担当 |
ActivityTaskManagerService | アクティビティの管理とスケジューリングを担当する ATMS は、Android10 の新しいコンテンツです。 |
ActivityManagerService | ライフサイクルと状態の切り替えを含む、4 つの主要なコンポーネントとプロセスの管理を担当します。 |
ActivityTaskManagerInternal | これは ActivityTaskManagerService によって提供される抽象クラスです. 実際の 実装は ActivityTaskManagerService#LocalService にあります |
アクティビティ スレッド | アプリケーション プロセスのメイン スレッドの実行を管理します。 |
ActivityStackSupervisor | すべてのアクティビティ スタックの管理を担当 |
TransactionExecutor | 主な機能は ClientTransaction を実行することです |
ClientLifecycleManager | ライフサイクル管理呼び出し |
3. 同じプロセス内の startActivity プロセス
開始コード
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
//调用Activity.java中的startActivity方法
startActivity(intent);
詳細が多すぎるため、最も重要なコアのタイミング図のみを描きます
図 1 startActivity シーケンス図
3 番目の質問を見てみましょう。新しいアクティビティを開始します。なぜ onPause メソッドが最初に実行されるのですか?
対応するソース コード プロセスは次のとおりです。
上記のシーケンス図のステップ 12 は、frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java の resumeTopActivityInnerLocked メソッドにあります。
@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
if (!mService.isBooting() && !mService.isBooted()) {
// Not ready yet!
return false;
}
.....
// Activity栈中有需要Pause操作的Activity
boolean pausing = getDisplay().pauseBackStacks(userLeaving, next, false);
if (mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Pausing " + mResumedActivity);
// 暂停当前正在显示的Activity
pausing |= startPausingLocked(userLeaving, false, next, false);
}
.....
}
startPausingLocked メソッドの説明を続けます
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
ActivityRecord resuming, boolean pauseImmediately) {
.....
if (prev.attachedToProcess()) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
try {
EventLogTags.writeAmPauseActivity(prev.mUserId, System.identityHashCode(prev),
prev.shortComponentName, "userLeaving=" + userLeaving);
//关键代码, 这里是执行Activity onPause的方法
mService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving,
prev.configChangeFlags, pauseImmediately));
mService.notifyActivityStateChange(prev.intent, ProcessInfo.ACTIVITY_STATE_PAUSE, null);
} catch (Exception e) {
// Ignore exception, if process died other code will cleanup.
Slog.w(TAG, "Exception thrown during pause", e);
mPausingActivity = null;
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
.....
}
ここで MainActivity の onPause メソッドが実行された後、 SecondActivity の onCreate onStart onResume コールバック メソッドが開始されます。
上図の14段目にあたる
/frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
#startSpecificActivityLocked メソッド
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
boolean knownToBeDead = false;
if (wpc != null && wpc.hasThread()) {
try {
//如果是同一进程的话,就直接启动目标Activity
realStartActivityLocked(r, wpc, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
knownToBeDead = true;
}
// Suppress transition until the new activity becomes ready, otherwise the keyguard can
// appear for a short amount of time before the new process with the new activity had the
// ability to set its showWhenLocked flags.
if (getKeyguardController().isKeyguardLocked()) {
r.notifyUnknownVisibilityLaunched();
}
try {
if (Trace.isTagEnabled(TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dispatchingStartProcess:"
+ r.processName);
}
// Post message to start process to avoid possible deadlock of calling into AMS with the
// ATMS lock held.
//如果不是同进程,且进程没有启动, 则需要去fork一个新进程.
final Message msg = PooledLambda.obtainMessage(
ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,
r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent());
mService.mH.sendMessage(msg);
} finally {
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
}
同じプロセスであれば、直接 realStartActivityLocked メソッドを呼び出す
同じプロセスではなく、プロセスがまだ開始されていない場合は、ActivityManagerInternal::startProcess を呼び出して新しいプロセスをフォークします。
次に、realStartActivityLocked のメソッドの分析を続けます。
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException {
.....
//关键代码
// Create activity launch transaction.
final ClientTransaction clientTransaction = ClientTransaction.obtain(
proc.getThread(), r.appToken);
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
System.identityHashCode(r), r.info,
// TODO: Have this take the merged configuration instead of separate global
// and override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
r.icicle, r.persistentState, results, newIntents,
dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
r.assistToken));
// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
} else {
lifecycleItem = PauseActivityItem.obtain();
}
clientTransaction.setLifecycleStateRequest(lifecycleItem);
// Schedule transaction.
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
......
}
ClientTransaction オブジェクトをカプセル化し、TransactionExecutor.java の execute() メソッドに対して実行します。
clientTransaction.addCallback ( LaunchActivityItem オブジェクトをカプセル化)。これは、開始する必要がある Activity オブジェクトです。
最後に、コード mService.getLifecycleManager().scheduleTransaction(clientTransaction) によって実行が調整され、このコードは次の場所にジャンプします。
フレームワーク/ベース/サービス/コア/Java/com/Android/サーバー/wm/ClientLifecycleManager.java
scheduleTransaction メソッド
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
final IApplicationThread client = transaction.getClient();
transaction.schedule();
if (!(client instanceof Binder)) {
// If client is not an instance of Binder - it's a remote call and at this point it is
// safe to recycle the object. All objects used for local calls will be recycled after
// the transaction is executed on client in ActivityThread.
transaction.recycle();
}
}
realStartActivityLocked を呼び出した後のタイミング図は次のとおりです。
ステップ 13 で performLaunchActivity メソッドを実行すると、SecondActivity が onCreate メソッドを作成してコールバックします。
4. 異なるプロセスでの startActivity プロセス
開始コード:
startBprocessBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();
ComponentName componentName = new ComponentName("com.example.myclient",
"com.example.myclient.BprocessActivity");
intent.setComponent(componentName);
try{
startActivity(intent);
} catch (Exception e) {
Log.e("activity", "error: "+e.getMessage());
}
}
});
2 番目の要約に従って分析を続行します。同じプロセスでない場合は、startProcess のコード フローに従います。
新しいプロセスの起動については、筆者も以前に該当するプロセスを分析したので、Androidのプロセス間通信の仕組み (4) アプリのプロセス起動プロセスを参照してください。
プロセスが正常に作成されて開始されたら、BprocessActivity の onCreate メソッドに到達する方法を分析してみましょう。
アプリケーションプロセスが正常に作成された後、最初に ActivityThread.java の main メソッドが実行され、フローチャートは次のようになります。
次の写真
さて、図の最後のステップ mStackSupervisor.attachApplicationLocked(app) は、mStackSupervisor.realStartActivityLocked のメソッドに呼び出されます。
つまり、3 番目のセクションで realStartActivityLocked の後のプロセス、プロセスは同じで、終了後、BprocessActivity が正常に作成され、ライフ サイクルの onCreate メソッドがコールバックされます。