Android 12のソースリンク: http://aospxref.com/android-12.0.0_r3/を検索
デスクトップアイコンをクリックすると、ランチャーアプリケーションのクリックメソッドに入ります。
private static void onClick(View v) {
// Make sure that rogue clicks don't get through while allapps is launching, or after the
// view has detached (it's possible for this to happen if the view is removed mid touch).
if (v.getWindowToken() == null) return;
Launcher launcher = Launcher.getLauncher(v.getContext());
if (!launcher.getWorkspace().isFinishedSwitchingState()) return;
Object tag = v.getTag();
if (tag instanceof WorkspaceItemInfo) {
onClickAppShortcut(v, (WorkspaceItemInfo) tag, launcher);
} else if (tag instanceof FolderInfo) {
if (v instanceof FolderIcon) {
onClickFolderIcon(v);
}
} else if (tag instanceof AppInfo) {
startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher
);
} else if (tag instanceof LauncherAppWidgetInfo) {
if (v instanceof PendingAppWidgetHostView) {
onClickPendingWidget((PendingAppWidgetHostView) v, launcher);
}
} else if (tag instanceof SearchActionItemInfo) {
onClickSearchAction(launcher, (SearchActionItemInfo) tag);
}
}
降りる
packages/apps/Launcher3/src/com/android/launcher3/touch/ItemClickHandler.java
public static void onClickAppShortcut(View v, WorkspaceItemInfo shortcut, Launcher launcher) {
if (shortcut.isDisabled() && handleDisabledItemClicked(shortcut, launcher)) {
return;
}
// Check for abandoned promise
if ((v instanceof BubbleTextView) && shortcut.hasPromiseIconUi()) {
String packageName = shortcut.getIntent().getComponent() != null
? shortcut.getIntent().getComponent().getPackageName()
: shortcut.getIntent().getPackage();
if (!TextUtils.isEmpty(packageName)) {
onClickPendingAppItem(
v,
launcher,
packageName,
(shortcut.runtimeStatusFlags
& ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0);
return;
}
}
// Start activities
启动activity
startAppShortcutOrInfoActivity(v, shortcut, launcher);
}
それから下に行きます
packages/apps/Launcher3/src/com/android/launcher3/touch/ItemClickHandler.java
private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher) {
TestLogging.recordEvent(
TestProtocol.SEQUENCE_MAIN, "start: startAppShortcutOrInfoActivity");
Intent intent;
if (item instanceof ItemInfoWithIcon
&& (((ItemInfoWithIcon) item).runtimeStatusFlags
& ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) {//APP未在安装中
ItemInfoWithIcon appInfo = (ItemInfoWithIcon) item;
根据点击的item解析出package name
intent = new PackageManagerHelper(launcher)
.getMarketIntent(appInfo.getTargetComponent().getPackageName());
} else {
根据点击的item得到intent
intent = item.getIntent();
}
if (intent == null) {
throw new IllegalArgumentException("Input must have a valid intent");
}
if (item instanceof WorkspaceItemInfo) {
WorkspaceItemInfo si = (WorkspaceItemInfo) item;
if (si.hasStatusFlag(WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI)
&& Intent.ACTION_VIEW.equals(intent.getAction())) {
// make a copy of the intent that has the package set to null
// we do this because the platform sometimes disables instant
// apps temporarily (triggered by the user) and fallbacks to the
// web ui. This only works though if the package isn't set
intent = new Intent(intent);
intent.setPackage(null);
}
}
if (v != null && launcher.supportsAdaptiveIconAnimation(v)) {
// Preload the icon to reduce latency b/w swapping the floating view with the original.
FloatingIconView.fetchIcon(launcher, v, item, true /* isOpening */);
}
将解析出的intent传入
launcher.startActivitySafely(v, intent, item);
}
次に、スーパーのstartActivitySafelyに入ります
packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
@Override
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
//判断是否已经resumed
if (!hasBeenResumed()) {
// Workaround an issue where the WM launch animation is clobbered when finishing the
// recents animation into launcher. Defer launching the activity until Launcher is
// next resumed.
解决当完成从最近任务动画进入launcher时WM启动动画被破坏的问题
addOnResumeCallback(() -> startActivitySafely(v, intent, item));
if (mOnDeferredActivityLaunchCallback != null) {
mOnDeferredActivityLaunchCallback.run();
mOnDeferredActivityLaunchCallback = null;
}
return true;
}
进入super的startActivitySafely
boolean success = super.startActivitySafely(v, intent, item);
if (success && v instanceof BubbleTextView) {
// This is set to the view that launched the activity that navigated the user away
// from launcher. Since there is no callback for when the activity has finished
// launching, enable the press state and keep this reference to reset the press
// state when we return to launcher.
BubbleTextView btv = (BubbleTextView) v;
btv.setStayPressed(true);
addOnResumeCallback(() -> btv.setStayPressed(false));
}
return success;
}
継承関係は次のとおりです。 public クラス Launcher は StatefulActivityを拡張します。 <LauncherState>は、LauncherExterns、 Callbacks、InvariantDeviceProfileを実装します。OnIDPChangeListener、PluginListener < OverlayPlugin >パブリック抽象クラス StatefulActivity < STATE_TYPE は BaseState < STATE_TYPE >> を拡張します BaseDraggingActivity
パブリック 抽象 クラス BaseDraggingActivity は BaseActivityを拡張し、 OnColorsChangedListener、DisplayInfoChangeListenerを実装します。
最後に、BaseDraggingActivity の startActivitySafely に入ります。
public boolean startActivitySafely(View v, Intent intent, @Nullable ItemInfo item) {
if (mIsSafeModeEnabled && !PackageManagerHelper.isSystemApp(this, intent)) {
Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
return false;
}
解析得到bundle
Bundle optsBundle = (v != null) ? getActivityLaunchOptions(v, item).toBundle() : null;
UserHandle user = item == null ? null : item.user;
// Prepare intent
添加FLAG_ACTIVITY_NEW_TASK
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (v != null) {
intent.setSourceBounds(getViewBounds(v));
}
try {
boolean isShortcut = (item instanceof WorkspaceItemInfo)
&& (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
|| item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
&& !((WorkspaceItemInfo) item).isPromise();
if (isShortcut) {
// Shortcuts need some special checks due to legacy reasons.
startShortcutIntentSafely(intent, optsBundle, item);
} else if (user == null || user.equals(Process.myUserHandle())) {
// Could be launching some bookkeeping activity
启动activity
startActivity(intent, optsBundle);
} else {
getSystemService(LauncherApps.class).startMainActivity(
intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
}
if (item != null) {
InstanceId instanceId = new InstanceIdSequence().newInstanceId();
logAppLaunch(item, instanceId);
}
return true;
} catch (NullPointerException | ActivityNotFoundException | SecurityException e) {
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
Log.e(TAG, "Unable to launch. tag=" + item + " intent=" + intent, e);
}
return false;
}
そして基本クラスを呼び出します
Frameworks/base/core/java/android/app/Activity.java 中のもの
startActivityForResult方法
frameworks/base/core/java/android/app/Activity.java
@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)) {
if (TextUtils.equals(getPackageName(),
intent.resolveActivity(getPackageManager()).getPackageName())) {
// Apply Autofill restore mechanism on the started activity by startActivity()
final IBinder token =
mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN);
// Remove restore ability from current activity
mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN);
mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY);
// Put restore token
intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token);
intent.putExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY, true);
}
}
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
次に、現在のクラスに進み、startActivityForResult を呼び出します。
frameworks/base/core/java/android/app/Activity.java
@Override
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public void startActivityForResult(
String who, Intent intent, int requestCode, @Nullable Bundle options) {
Uri referrer = onProvideReferrer();
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
options = transferSpringboardActivityOptions(options);
通过Instrumentation跨进程启动activity
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, who,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, who, requestCode,
ar.getResultCode(), ar.getResultData());
}
cancelInputsAndStartExitTransition(options);
}
次にインストルメンテーションについて説明します。インストルメンテーションとは、JVM 上で実行されているアプリケーションを監視および支援するために、アプリケーションから独立したエージェント (エージェント) プログラムを使用することを指します。この監視と支援には、JVM ランタイム状態の取得、クラス定義の置換と変更などが含まれますが、これらに限定されません。
フレームワーク/ベース/コア/java/android/app/Instrumentation.java
frameworks/base/core/java/android/app/Instrumentation.java
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
...
try {
intent.migrateExtraStreamToClipData(who);
intent.prepareToLeaveProcess(who);
获取ATMS的binder对象,通过对象调用startActivity方法
int result = ActivityTaskManager.getService().startActivity(whoThread,
who.getOpPackageName(), who.getAttributionTag(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()), token,
target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
次に、ActivityTaskManager に移動し、AIDL を通じて ActivityTaskManagerService のインスタンスを取得します。
フレームワーク/base/core/java/android/app/ActivityTaskManager.java
frameworks/base/core/java/android/app/ActivityTaskManager.java
public static IActivityTaskManager getService() {
return IActivityTaskManagerSingleton.get();
}
@UnsupportedAppUsage(trackingBug = 129726065)
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
new Singleton<IActivityTaskManager>() {
@Override
protected IActivityTaskManager create() {
获取ACTIVITY_TASK_SERVICE服务
final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
返回Binder实例
return IActivityTaskManager.Stub.asInterface(b);
}
};
-------------------------------------------------- -------------------------------------------------- --------------
ここから、システム プロセス SystemServer の ActivityTaskManagerService サービスに移動します。
Frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@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) {
return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
@Override
public int startActivityAsUser(IApplicationThread caller, String callingPackage,
String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
Bundle bOptions, int userId) {
return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
true /*validateIncomingUser*/);
}
private int startActivityAsUser(IApplicationThread caller, String callingPackage,
@Nullable String callingFeatureId, Intent intent, String resolvedType,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
assertPackageMatchesCallingUid(callingPackage);
enforceNotIsolatedCaller("startActivityAsUser");
userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
将相关设置参数等都设置进去
call:发起者context
callPackage:发起者包名
// TODO: Switch to user app stacks here.
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
.execute();
}
Frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
private ActivityStartController mActivityStartController;
ActivityStartController getActivityStartController() {
return mActivityStartController;
}
ActivityStarter obtainStarter(Intent intent, String reason) {
return mFactory.obtain().setIntent(intent).setReason(reason);
フレームワーク/base/services/core/java/com/android/server/wm/ActivityStarter.java
/** * 前に指定したリクエスト パラメータに従って必要な情報を解決し、 * アクティビティを開始するプロセスを開始するリクエストを実行します。 * @return スターターの結果。 */ intexecute() { ... res =solveToHeavyWeightSwitcherIfNeeded(); if (res != START_SUCCESS) { res を返します。 res = 実行リクエスト(mRequest); ... }
フレームワーク/base/services/core/java/com/android/server/wm/ActivityStarter.java
/** * アクティビティ開始リクエストを実行し、アクティビティを開始するプロセスを開始します。ここで * は、いくつかの事前チェックを実行することから始まります。通常、アクティビティの起動フローは * {@link #startActivityUnchecked} を経由して {@link #startActivityInner} まで進みます。 */ private intexecuteRequest(Request request) { ... //初期值 int err = ActivityManager.START_SUCCESS; ... //各パラメータに基づいて当否を判断する if (err == ActivityManager.START_SUCCESS &&tent.getComponent() == null) { // 指定された Intent を処理できるクラスが見つかりませんでした。 err = ActivityManager.START_INTENT_NOT_RESOLVED; } // これで終わりです! if (err == ActivityManager.START_SUCCESS && aInfo == null) { // インテントで指定された特定のクラスが見つかりませんでした。 // 行末でもあります。 err = ActivityManager.START_CLASS_NOT_FOUND; } ... / /ActivityRecord のさまざまな情報を設定します。ActivityRecord はアクティビティを表します。アクティビティのさまざまな情報は、ActivityRecord を通じて取得できます。final ActivityRecord r = new ActivityRecord.Builder(mService) .setCaller(callerApp) .setLaunchedFromPid(callingPid) .setLaunchedFromUid(callingUid) .setIntent(intent) .setLaunchedFromPackage(callingPackage) .setLaunchedFromFeature(callingFeatureId) .setResolvedType(resolvedType) .setActivityInfo(aInfo) .setConfiguration(mService.getGlobalConfiguration()) .setResultTo(resultRecord) .setResultWho(resultWho) .setRequestCode(requestCode) .setComponentSpecified(request.componentSpecified) .setRootVoiceInteraction(音声セッション!= null) .setActivityOptions(checkedOptions) .setSourceRecord(sourceRecord) .build(); ... //启活動活動 mLastStartActivityResult = startActivityUnchecked(r,sourceRecord,voiceSession, request.voiceInteractor、startFlags、true /* doResume */、checkedOptions、inTask、 restrictedBgActivity、tentGrants); ...
フレームワーク/base/services/core/java/com/android/server/wm/ActivityStarter.java
/** * ほとんどの事前チェックが完了し、呼び出し元が * 必要な権限を保持していることが確認された状態で、アクティビティを開始します。 * ここでは、開始が成功しなかった場合に、開始アクティビティが確実に削除されるようにします。 */ private int startActivityUnchecked (final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, Task inTask, boolean requestedBgActivity, NeededUriGrantstentGrants) { ... try { //延迟绘制 mService.deferWindowLayout(); Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner"); //アクティビティの開始 result = startActivityInner(r,sourceRecord,voiceSession,voiceInteractor,startFlags,doResume,options,inTask,restrictedBgActivity,tentGrants); 最後に { Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); startingActivityRootTask = handleStartResult(r, result); //継続绘制 mService. continueWindowLayout(); ...
フレームワーク/base/services/core/java/com/android/server/wm/ActivityStarter.java
/** * アクティビティを開始し、アクティビティを既存のタスクの先頭に追加する必要があるか 、 * 既存のアクティビティに新しいインテントを配信するかを決定します。また、アクティビティ タスク * を、要求されたまたは有効なルート タスク/ディスプレイ上で操作します。 * * 注: このメソッドは、{@link #startActivityUnchecked} からのみ呼び出す必要があります。 */ // TODO(b/152429287): startActivityInner @VisibleForTesting int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession、IVoiceInteractor voiceInteractor、int startFlags、boolean doResume、ActivityOptions options、Task inTask、boolean requestedBgActivity、NeededUriGrantstentGrants) { setInitialState(r, options, inTask、doResume、startFlags、sourceRecord、voiceSession、 voiceInteractor、restrictedBgActivity); computeLaunchingTaskFlags(); computeSourceRootTask(); mIntent.setFlags(mLaunchFlags); 最終タスク再利用タスク = getReusableTask(); ... computeLaunchParams(r,sourceRecord,targetTask); ... mTargetRootTask.startActivityLocked(mStartActivity, topRootTask != null ? topRootTask.getTopNonFinishingActivity() : null, newTask,mKeepCurTransition, mOptions, sourceRecord); if (mDoResume) { 最終アクティビティレコード topTaskActivity = mStartActivity.getTask().topRunningActivityLocked(); if (!mTargetRootTask.isTopActivityFocusable() || (topTaskActivity != null && topTaskActivity.isTaskOverlay() && mStartActivity != topTaskActivity)) { // mTargetRootTask.ensureActivitiesVisible(null /* 開始 */, 0 /* configChanges */, !PRESERVE_WINDOWS); // mTargetRootTask.mDisplayContent.executeAppTransition(); } その他 { // if (mTargetRootTask.isTopActivityFocusable() && !mRootWindowContainer.isTopDisplayFocusedRootTask(mTargetRootTask)) { mTargetRootTask.moveToFront("startActivityInner"); } mRootWindowContainer.resumeFocusedTasksTopActivities( mTargetRootTask, mStartActivity, mOptions, mTransientLaunch); } } mRootWindowContainer.updateUserRootTask(mStartActivity.mUserId, mTargetRootTask); // 最近のタスクを更新しますアクティビティが開始されるとすぐに mSupervisor.mRecentTasks をリストします。 add(mStartActivity.getTask()); mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetRootTask); return START_SUCCESS; }
フレームワーク/base/services/core/java/com/android/server/wm/RootWindowContainer.java
ブール型resumeFocusedTasksTopActivities() { returnresumeFocusedTasksTopActivities(null, null, null); -------------------------------------------------- _ --------------------------------- booleanresumeFocusedTasksTopActivities( Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions) { returnresumeFocusedTasksTopActivities(targetRootTask) , target, targetOptions, false /* deferPause */); -------------------------------------------------- _ --------------------------------- boolean raiseFocusedTasksTopActivities( タスク targetRootTask, ActivityRecord target, ActivityOptions targetOptions, boolean deferPause) { if (!mTaskSupervisor.readyToResume()) { return false; ブール 値の結果 = 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); 最終ブール値 curResult = 結果; boolean[] restartOnDisplay = 新しい boolean[1]; display.forAllRootTasks(rootTask -> { final ActivityRecord topRunningActivity = rootTask.topRunningActivity(); if (!rootTask.isFocusableAndVisible() || topRunningActivity == null) { return; } if (rootTask == targetRootTask) { // restartOnDisplay[0] ] |= curResult; return; } if (rootTask.getDisplayArea().isTopRootTask(rootTask) && topRunningActivity.isState(RESUMED)) { // rootTask.executeAppTransition(targetOptions); } else { returnsOnDisplay[0] |= topRunningActivity.makeActiveIfNeeded(target); } }); 結果 |= 再開オンディスプレイ[0]; if (!resumedOnDisplay[0]) { // 最終タスク focusRoot = display.getFocusedRootTask(); if (focusedRoot != null) { result |= focusedRoot.resumeTopActivityUncheckedLocked(target, targetOptions); } else if (targetRootTask == null) { result |=resumeHomeActivity(null /* prev */, "no-focusable-task", display.getDefaultTaskDisplayArea()); 結果を 返し ます 。 }
フレームワーク/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean continueTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) { returnumeTopActivityUncheckedLocked(prev, options, false /* SkipPause */); -------------------------------------------------- _ ------------------------- boolean raiseTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options, boolean deferPause) { if (mInResumeTopActivity) { // 禁止再帰を開始することさえあります。 false を返します。 ブール 値 someActivityResumed = false; try { // 再帰から保護します。 mInResumeTopActivity = true; if (isLeafTask()) { if (isFocusableAndVisible()) { // someActivityResumed =resumeTopActivityInnerLocked(prev, options, deferPause); } } else { int idx = mChildren.size() - 1; while (idx >= 0) { 最終タスクの子 = (タスク) getChildAt(idx--); if (!child.isTopActivityFocusable()) { 続行; if (child.getVisibility(null /* starting */) != TASK_VISIBILITY_VISIBLE) { ブレーク ; } someActivityResumed |= child.resumeTopActivityUncheckedLocked(prev, options, deferPause); // if (idx >= mChildren.size()) { idx = mChildren.size() - 1; } } } // 最終的な ActivityRecord next = topRunningActivity(true /* focusableOnly */); if (next == null || !next.canTurnScreenOn()) { checkReadyForSleep(); 最後に { mInResumeTopActivity = false; someActivityResumed を返し ます。 }
フレームワーク/base/services/core/java/com/android/server/wm/RootWindowContainer.java
@GuardedBy("mService") private booleanresumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options, boolean deferPause) { ... ActivityRecord next = topRunningActivity(true /* focusableOnly */); 最終ブール値 hasRunningActivity = next != null; // TODO: おそらくこの状態全体を削除できるでしょうか? if (hasRunningActivity && !isAttached()) { return false; mRootWindowContainer.cancelInitializingActivities( ) ; if (!hasRunningActivity) { // ルート タスクにはアクティビティが残っていないので、別の場所を見てみましょう。 returnresumeNextFocusableActivityWhenRootTaskIsEmpty(prev, options); next.layedResume = false; 最終的な TaskDisplayArea taskDisplayArea = getDisplayArea(); // 最上位のアクティビティが再開されたアクティビティの場合は、何も行いません。 if (mResumedActivity == next && next.isState(RESUMED) && taskDisplayArea.allResumedActivitiesComplete()) { // この時点では何もすることが残っていないはずな ので、保留中のトランジションが実行されていることを確認してください。 executeAppTransition(オプション); // フルスクリーン モードではないデバイス (フリーフォーム ウィンドウなど) の場合は可能です // 他のウィンドウの可視性が変更されたかどうかを確認したいと考えています (たとえば、 // 別のフリーフォーム アクティビティをカバーするために全画面ウィンドウを前に持ってきます。) if (taskDisplayArea.inMultiWindowMode()) { taskDisplayArea.ensureActivitiesVisible(null /* starting */ , 0 /* configChanges */, false /* prepareWindows */, true /* NoticeClients */); ProtoLog.d (WM_DEBUG_STATES, "resumeTopActivityLocked: トップアクティビティ " + "%s を再開しました", next); false を返します。 if (!next.canResumeByCompat()) { return false; } // 現在アクティビティを一時停止している場合は、それが完了するまで何もしないでください。 最終ブール値 allPausedComplete = mRootWindowContainer.allPausedActivitiesComplete(); if (!allPausedComplete) { ProtoLog.v(WM_DEBUG_STATES, "resumeTopActivityLocked: 再開をスキップ: 一部のアクティビティが一時停止しています。"); false を返します。 } // スリープ中であり、再開されるアクティビティがなく、最上位のアクティビティが一時停止されている場合、 // それが私たちが望む状態です。 if (mLastPausedActivity == next && shouldSleepOrShutDownActivities()) { // 保留中のトランジションがあれば必ず実行してください。 // この時点では何もする必要はありません。 executeAppTransition(オプション); ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: スリープ状態になり、" + " すべて一時停止されました"); false を返します。 } // このアクティビティを所有するユーザーが開始されていることを確認してください。そうでない場合は、 // 誰かが 別のユーザーのアクティビティをスタックの一番上に 持ってくるはずなので、 // そのままにしておきます。 if (!mAtmService.mAmInternal.hasStartedUserState(next.mUserId)) { Slog.w(TAG, "先頭アクティビティの再開をスキップします " + next + ": user " + next. false を返します。 } // アクティビティは停止を待っている可能性がありますが、それは // もはや 適切ではありません。 mTaskSupervisor.mStoppingActivities.remove(next); if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "再開 " + next); mTaskSupervisor.setLaunchSource(next.info.applicationInfo.uid); ActivityRecord lastResumed = null; 最終タスク lastFocusedRootTask = taskDisplayArea.getLastFocusedRootTask(); if (lastFocusedRootTask != null && lastFocusedRootTask != getRootTask()) { // では、なぜここで prev を使用しないのでしょうか?メソッドの param コメントを参照してください。前へ // は最後に再開されたアクティビティを表しません。ただし、最後のフォーカス スタックは、 // null でない場合に実行されます。 lastResumed = lastFocusedRootTask.getResumedActivity(); boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next) ; if (mResumedActivity != null) { ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: %s を一時停止しています", mResumedActivity); 一時停止中 |= startPausingLocked(false /* uiSleeping */, next, "resumeTopActivityInnerLocked"); } if (一時停止) { ProtoLog.v(WM_DEBUG_STATES, "resumeTopActivityLocked: 再開をスキップ: する必要があります" + "一時停止を開始"); // この時点で、今後のアクティビティのプロセスを // LRU リストの先頭に置きたいと思います 。これは、それがすぐに必要になることがわかっているためです。 // 終了した場合に強制終了させるのは無駄です //たまたま端の方に座っていました。 if (next.attachedToProcess()) { next.app.updateProcessInfo(false /* updateServiceConnectionActivities */, true /* activityChange */, false /* updateOomAdj */, false /* addPendingTopUid */); else if (!next.isProcessRunning()) { // 開始プロセスは非同期であるため、次のアクティビティの プロセスが実行されていないことがわかっている場合は、 // 現在のアクティビティが一時停止されるまで待つ時間を節約するために、 // より早くプロセスを開始できます。 最終ブール値 isTop = this == taskDisplayArea.getFocusedRootTask(); mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop, isTop ? "pre-top-activity" : "pre-activity"); if (lastResumed != null) { lastResumed.setWillCloseOrEnterPip (true); true を返し ます。 } else if (mResumedActivity == next && next.isState(RESUMED) && taskDisplayArea.allResumedActivitiesComplete()) { // 次のアクティビティに // がない 場合、上記のバックスタックを一時停止したときにアクティビティが再開される可能性があります。一時停止が完了するまで待ちます。 // したがって、次のこと以外は何もする必要はありません。 // この時点では何もすることが残っていないはずな ので、保留中のトランジションが実行されていることを確認してください。 executeAppTransition(オプション); ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: 上位アクティビティが再開されました " + "(dontWaitForPause) %s", 次); true を返します。 } // 最新のアクティビティが noHistory であったが、 デバイスがスリープ状態になったため // 停止+終了ではなく停止されただけの場合、 新しいアクティビティを最上位に作成しているため、 // 必ず終了する必要があります。 if ( shouldSleepActivities()) { mTaskSupervisor.finishNoHistoryActivitiesIfNeeded(next); } if (prev != null && prev != next && next.nowVisible) { // 次のアクティビティはすでに表示されているので、 すぐに新しいアクティビティを表示できるように、 // 前のアクティビティのウィンドウを今すぐ非表示にします。 // 前のものが終了している場合にのみこれを行います。つまり、 // 再開中のものの上にあるので、すぐに非表示にするのが // 良いです。 それ以外の場合は、 // 新しいアクティビティが 全画面表示であるかどうかに応じて 、 // 前のアクティビティを実際に非表示にするかどうかを決定できるように、 // 再開されたアクティビティの表示を許可する通常のルートを実行したいと考えています。 if (prev.finishing) { prev.setVisibility(false); if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "表示が非表示になるのを待機していません: " + prev + ", nowVisible=" + next.nowVisible); } else { if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, 「前はすでに表示されていますが、まだ非表示を待っています: " + prev + ", nowVisible=" + next.nowVisible); } } // このアプリのアクティビティを起動すると、 // アプリが 停止したとみなされなくなることを確認します。 { mTaskSupervisor.getActivityMetricsLogger() .notifyBeforePackageUnstopped(next.packageName);を試してください。 mAtmService.getPackageManager().setPackageStoppedState( next.packageName, false, next.mUserId); /* TODO: ユーザー ID が正しいかどうかを確認します */ } catch (RemoteException e1) { } catch (IllegalArgumentException e) { Slog.w(TAG, "パッケージ " + next.packageName + " の 停止を解除できませんでした: " + e); } // 次のアクティビティを開始しているので、 // 前のアクティビティが間もなく非表示になることをウィンドウ マネージャーに伝えます。このようにして、 // 必要な画面の向きを計算するときにそれを無視することを知ることができます。 ブール値のアニメーション = true; 最終 DisplayContent dc = taskDisplayArea.mDisplayContent; if (prev != null) { if (prev.finishing) { if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "クローズトランジションの準備: prev=" + prev); if (mTaskSupervisor.mNoAnimActivities.contains(prev)) { anim = false; dc.prepareAppTransition(TRANSIT_NONE); } else { dc.prepareAppTransition(TRANSIT_CLOSE); prev.setVisibility (false); } else { if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "オープントランジションの準備: prev=" + prev); if (mTaskSupervisor.mNoAnimActivities.contains(next)) { anim = false; dc.prepareAppTransition(TRANSIT_NONE); } それ以外 { dc.prepareAppTransition(TRANSIT_OPEN, next.mLaunchTaskBehind ? TRANSIT_FLAG_OPEN_BEHIND : 0); } } } else { if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "オープン トランジションの準備: 前のものはありません"); if (mTaskSupervisor.mNoAnimActivities.contains(next)) { anim = false; dc.prepareAppTransition(TRANSIT_NONE); } else { dc.prepareAppTransition(TRANSIT_OPEN); if ( anim) { next.applyOptionsAnimation(); } それ以外 { next.abortAndClearOptionsAnimation(); mTaskSupervisor.mNoAnimActivities.clear( ) ; if (next.attachedToProcess()) { if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "実行を再開: " + next + " stoped=" + next.stopped + "visibleRequested=" + next.mVisibleRequested); // 前のアクティビティが半透明の場合、次のアクティビティの表示更新を強制します 。これにより、次のアクティビティが WM の開始アプリ リストに追加され、 // 遷移アニメーションが適切に設定されます。 // たとえば、半透明のアクティビティにフォーカスがある状態でホーム ボタンを押すとします。 // この場合、ランチャーはすでに表示されています。// アプリを開くときにこれを追加しないと 、UpdateTransitToWallpaper() は // これを TRANSIT_WALLPAPER_OPEN アニメーションとして識別できず 、面白いアニメーションを実行するでしょう。 Final boolean lastActivityTranslucent = lastFocusedRootTask != null && (lastFocusedRootTask.inMultiWindowMode() || (lastFocusedRootTask.mLastPausedActivity != null && !lastFocusedRootTask.mLastPausedActivity.occludesParent())); // このアクティビティは可視化されています。 if (!next.mVisibleRequested || next.stopped || lastActivityTranslucent) { next.setVisibility(true); } // 遅いアプリに関する情報を収集するために起動ティックをスケジュールします。 next.startLaunchTickingLocked(); ActivityRecord lastResumedActivity = lastFocusedRootTask == null ? null : lastFocusedRootTask.getResumedActivity(); 最終的なアクティビティ状態 lastState = next.getState(); mAtmService.updateCpuStats(); ProtoLog.v(WM_DEBUG_STATES, "再開済み: %s (既存) に移動", 次); next.setState(RESUMED, "resumeTopActivityInnerLocked"); // ウィンドウ マネージャーに方向を再評価させます。 // 新しいアクティビティの順序に基づいた画面。 ブール値 notUpdated = true; // mLaunchTaskBehind を true に設定すると、アクティビティも表示されるはずです ( // ActivityRecord#ShouldBeVisibleIgnoringKeyguard() を参照)。 if ( shouldBeVisible(next)) { // 特定の方向を要求するアクティブなアクティビティがある場合、 またはキーガードがロックされている場合、 // 特別な回転動作が行われます。 // 正しい回転動作を実現するために、すべてのアクティビティの可視性が // 必要に応じてトランジションが更新されていることを確認してください。それ以外の場合は、更新のための次の呼び出し // 向きによっては、 非表示のウィンドウのサイズ変更の結果として、 // クライアントに誤った構成が配信される可能性があります。 // TODO: 可視性が正しく設定されたら、 // アクティビティの開始時にすぐにこれを削除します。 notUpdated = !mRootWindowContainer.ensureVisibilityAndConfig(next, getDisplayId(), true /* markFrozenIfConfigChanged */, false /* deferResume */); } if (notUpdated) { // 設定の更新により 、 // アクティビティの 既存のインスタンスを維持できず、代わりに新しいインスタンスが開始されました。 // すべて完了する必要がありますが、アクティビティが // まだ先頭にあることを確認し、 // 何か奇妙なことが起こった場合は別の実行をスケジュールしましょう。 ActivityRecord nextNext = topRunningActivity(); ProtoLog.i(WM_DEBUG_STATES, "再開中にアクティビティ構成が変更されました: " + "%s、新しい次: %s", next, nextNext); if (nextNext != next) { // やり直します! mTaskSupervisor.scheduleResumeTopActivities(); if (!next.mVisibleRequested || next.stopped) { next.setVisibility(true) ; } next.completeResumeLocked(); true を返します。 { 最終的な ClientTransaction トランザクション = 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) { if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "結果を " + next + " に配信中: " + a); transaction.addCallback(ActivityResultItem.obtain(a)); if (next.newIntents != null) { transaction.addCallback( NewIntentItem.obtain(next.newIntents, true /* 再開 * /)); } // さて、アプリはもう停止されません。 // 必要に応じて、ウィンドウ マネージャーでアプリ トークンの停止状態をクリアします。 next.notifyAppResumed(next.stopped); EventLogTags.writeWmResumeActivity(next.mUserId, System.identityHashCode(next), next.getTask().mTaskId, next.shortComponentName); mAtmService.getAppWarningsLocked().onResumeActivity(next); next.app.setPendingUiCleanAndForceProcessStateUpTo(mAtmService.mTopProcessState); next.abortAndClearOptionsAnimation(); transaction.setLifecycleStateRequest( ResumeActivityItem.obtain(next.app.getReportedProcState(), dc.isNextTransitionForward())); mAtmService.getLifecycleManager().scheduleTransaction(トランザクション); ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: %s を再開しました", next); } catch (Exception e) { // おっと、このアクティビティを再起動する必要があります。 ProtoLog.v(WM_DEBUG_STATES, "再開に失敗しました; 状態を %s にリセットします: " + "%s", lastState, next); next.setState(lastState, "resumeTopActivityInnerLocked"); // lastResumedActivity が null でない場合は、lastStack が存在することを意味します。 if (lastResumedActivity != null) { lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked"); Slog.i(TAG, "プロセスが 停止したため再起動します: " + next); if (!next.hasBeenLaunched) { 次。hasBeenLaunched = true; } else if (SHOW_APP_STARTING_PREVIEW && lastFocusedRootTask != null && lastFocusedRootTask.isTopRootTaskInDisplayArea()) { next.showStartingWindow(false /* taskSwitch */); mTaskSupervisor.startSpecificActivity (next, true, false); true を返します。 } // この時点から、何か問題が発生した場合、 // アクティビティを回復する方法はありません。 { next.completeResumeLocked();を試してください。 } catch (Exception e) { // 例外がスローされた場合は、この // アクティビティを破棄して、次のアクティビティを試します。 Slog.w(TAG, "「 + next, e) の再開中に例外がスローされました。」; next.finishIfPossible("再開例外", true /* oomAdj */); true を返します。 } } else { // おっと、このアクティビティを再起動する必要があります。 if (!next.hasBeenLaunched) { next.hasBeenLaunched = true; } else { if (SHOW_APP_STARTING_PREVIEW) { next.showStartingWindow(false /* taskSwich */); if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "再起動中: " + next ); } ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: %s を再起動しています", next); mTaskSupervisor.startSpecificActivity(next, true, true); true を返し ます。 }