【Android12】Android Framework系列--AMS启动Activity分析

AMS启动Activity分析

通过ActivityManagerService(AMS)提供的方法,可以启动指定的Activity。比如Launcher中点击应用图标后,调用AMS的startActivity 函数启动应用。

AMS提供的服务通过IActivityManager.aidl文件定义。

java 复制代码
// frameworks/base/core/java/android/app/IActivityManager.aidl
package android.app;
// 省略
/**
 * System private API for talking with the activity manager service.  This
 * provides calls from the application back to the activity manager.
 *
 * {@hide}
 */
interface IActivityManager {
	// 省略
    /** @deprecated Use {@link #startActivityWithFeature} instead */
    @UnsupportedAppUsage(maxTargetSdk=29, publicAlternatives="Use {@link android.content.Context#startActivity(android.content.Intent)} instead")
    int startActivity(in IApplicationThread caller, in String callingPackage, in Intent intent,
            in String resolvedType, in IBinder resultTo, in String resultWho, int requestCode,
            int flags, in ProfilerInfo profilerInfo, in Bundle options);
    int startActivityWithFeature(in IApplicationThread caller, in String callingPackage,
            in String callingFeatureId, in Intent intent, in String resolvedType,
            in IBinder resultTo, in String resultWho, int requestCode, int flags,
            in ProfilerInfo profilerInfo, in Bundle options);
	// 省略
}

代码版本是Android12。分析一下从应用侧(比如Launcher)调用startActivity启动另一个应用的流程。

startActivity源码分析

应用侧可以通过context的startActivity函数调用AMS。比如下述例子。

java 复制代码
Intent intent = new Intent();
// 启动com.linduo.test这个Package中的  MainActivity
intent.setComponent(new ComponentName("com.linduo.test", "com.linduo.test.MainActivity"));
context.startActivity(intent);

context是abstract的类,其实现在ContextImpl中。

java 复制代码
// frameworks/base/core/java/android/content/ContextWrapper.java
public class ContextWrapper extends Context {
}

// frameworks/base/core/java/android/app/ContextImpl.java
class ContextImpl extends Context {
@Override
public void startActivity(Intent intent) {
	warnIfCallingFromSystemProcess();
	startActivity(intent, null);
}

@Override
public void startActivity(Intent intent, Bundle options) {
	warnIfCallingFromSystemProcess();

	// Calling start activity from outside an activity without FLAG_ACTIVITY_NEW_TASK is
	// generally not allowed, except if the caller specifies the task id the activity should
	// be launched in. A bug was existed between N and O-MR1 which allowed this to work. We
	// maintain this for backwards compatibility.
	final int targetSdkVersion = getApplicationInfo().targetSdkVersion;

	if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) == 0
			&& (targetSdkVersion < Build.VERSION_CODES.N
					|| targetSdkVersion >= Build.VERSION_CODES.P)
			&& (options == null
					|| ActivityOptions.fromBundle(options).getLaunchTaskId() == -1)) {
		throw new AndroidRuntimeException(
				"Calling startActivity() from outside of an Activity "
						+ " context requires the FLAG_ACTIVITY_NEW_TASK flag."
						+ " Is this really what you want?");
	}
	mMainThread.getInstrumentation().execStartActivity(
			getOuterContext(), mMainThread.getApplicationThread(), null,
			(Activity) null, intent, -1, options);
}
}

ContextImpl通过mMainThread(ActivityThread类型)得到了Instrumentation 对象,调用Instrumentation的execStartActivity 函数。execStartActivity函数中,如果开启了Activity监听模式,会通知监听者onStartActivity,然后调用ActivityTaskManagerService的startActivity函数启动Activity。最后检查启动的结果,如果启动失败抛出对应的异常。

onStartActivity的监听,可以使用Instrumentation.addMonitor方式,具体内容可以查看Instrumentation.java

java 复制代码
// frameworks/base/core/java/android/app/Instrumentation.java
@UnsupportedAppUsage
public ActivityResult execStartActivity(
		Context who, IBinder contextThread, IBinder token, Activity target,
		Intent intent, int requestCode, Bundle options) {
	IApplicationThread whoThread = (IApplicationThread) contextThread;
	Uri referrer = target != null ? target.onProvideReferrer() : null;
	if (referrer != null) {
		intent.putExtra(Intent.EXTRA_REFERRER, referrer);
	}
	if (mActivityMonitors != null) {
		// 如果开启了监听,会给监听者通过 onStartActivity
		synchronized (mSync) {
			final int N = mActivityMonitors.size();
			for (int i=0; i<N; i++) {
				final ActivityMonitor am = mActivityMonitors.get(i);
				ActivityResult result = null;
				if (am.ignoreMatchingSpecificIntents()) {
					result = am.onStartActivity(intent);
				}
				if (result != null) {
					am.mHits++;
					return result;
				} else if (am.match(who, null, intent)) {
					am.mHits++;
					if (am.isBlocking()) {
						return requestCode >= 0 ? am.getResult() : null;
					}
					break;
				}
			}
		}
	}
	try {
		intent.migrateExtraStreamToClipData(who);
		intent.prepareToLeaveProcess(who);
		// 调用ActivityTaskManagerService( AMS中提供的服务)
		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);
		// 检查启动的结果,如果失败会throw异常。
		checkStartActivityResult(result, intent);
	} catch (RemoteException e) {
		throw new RuntimeException("Failure from system", e);
	}
	return null;
}

ActivityTaskManagerService继承了IActivityTaskManager.Stub ,属于AMS提供的服务。在其startActivity函数中,会调用startActivityAsUser,判断package与UID是否相符、是否为Isolated模式的应用、并检查用户权限(源码中可以看出系统用户权限非常大,所以为了安全要慎用系统用户权限),最终调用ActivityStarterexecute启动Activity。

java 复制代码
// 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) {
	// 调用startActivityAsUser
	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) {
	// 调用startActivityAsUser,validateIncomingUser为true
	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) {
	// 判断调用的package和UID相符
	assertPackageMatchesCallingUid(callingPackage);
	// 禁止来自Isolated模式应用的调用
	enforceNotIsolatedCaller("startActivityAsUser");

	// 检测用户权限。这个函数中,可以看出系统用户权限非常大(感兴趣的可以看一下)
	userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
			Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

	// 通过ActivityStartController,取得ActivityStarter,设置好系列参数后调用execute
	// 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();

}

ActivityStarter的execute函数中,再次进行了一些检查,比如是否存在文件句柄泄露(Intent)、config是否要变更,并调用了executeRequest函数。

java 复制代码
// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
int execute() {
	try {
		// Refuse possible leaked file descriptors
		if (mRequest.intent != null && mRequest.intent.hasFileDescriptors()) {
			throw new IllegalArgumentException("File descriptors passed in Intent");
		}

		final LaunchingState launchingState;
		synchronized (mService.mGlobalLock) {
			final ActivityRecord caller = ActivityRecord.forTokenLocked(mRequest.resultTo);
			final int callingUid = mRequest.realCallingUid == Request.DEFAULT_REAL_CALLING_UID
					?  Binder.getCallingUid() : mRequest.realCallingUid;
			launchingState = mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(
					mRequest.intent, caller, callingUid);
		}

		// If the caller hasn't already resolved the activity, we're willing
		// to do so here. If the caller is already holding the WM lock here,
		// and we need to check dynamic Uri permissions, then we're forced
		// to assume those permissions are denied to avoid deadlocking.
		if (mRequest.activityInfo == null) {
			mRequest.resolveActivity(mSupervisor);
		}

		// Add checkpoint for this shutdown or reboot attempt, so we can record the original
		// intent action and package name.
		if (mRequest.intent != null) {
			String intentAction = mRequest.intent.getAction();
			String callingPackage = mRequest.callingPackage;
			if (intentAction != null && callingPackage != null
					&& (Intent.ACTION_REQUEST_SHUTDOWN.equals(intentAction)
							|| Intent.ACTION_SHUTDOWN.equals(intentAction)
							|| Intent.ACTION_REBOOT.equals(intentAction))) {
				ShutdownCheckPoints.recordCheckPoint(intentAction, callingPackage, null);
			}
		}

		int res;
		synchronized (mService.mGlobalLock) {
			final boolean globalConfigWillChange = mRequest.globalConfig != null
					&& mService.getGlobalConfiguration().diff(mRequest.globalConfig) != 0;
			// 获取当前处于Top且Focus的RootTask
			final Task rootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();
			if (rootTask != null) {
				// RookTask非空,更新一下ConfigChange的Flag。
				rootTask.mConfigWillChange = globalConfigWillChange;
			}
			ProtoLog.v(WM_DEBUG_CONFIGURATION, "Starting activity when config "
					+ "will change = %b", globalConfigWillChange);

			final long origId = Binder.clearCallingIdentity();

			res = resolveToHeavyWeightSwitcherIfNeeded();
			if (res != START_SUCCESS) {
				return res;
			}
			// 这个函数中,会创建ActivityRecord,并启动Activity
			res = executeRequest(mRequest);
			// 后面的函数,主要是Config的变更。如果有变化会给config变化的通知。
			// 以及结果的检查。
			Binder.restoreCallingIdentity(origId);

			if (globalConfigWillChange) {
				// If the caller also wants to switch to a new configuration, do so now.
				// This allows a clean switch, as we are waiting for the current activity
				// to pause (so we will not destroy it), and have not yet started the
				// next activity.
				mService.mAmInternal.enforceCallingPermission(
						android.Manifest.permission.CHANGE_CONFIGURATION,
						"updateConfiguration()");
				if (rootTask != null) {
					rootTask.mConfigWillChange = false;
				}
				ProtoLog.v(WM_DEBUG_CONFIGURATION,
							"Updating to new configuration after starting activity.");

				mService.updateConfigurationLocked(mRequest.globalConfig, null, false);
			}

			// The original options may have additional info about metrics. The mOptions is not
			// used here because it may be cleared in setTargetRootTaskIfNeeded.
			final ActivityOptions originalOptions = mRequest.activityOptions != null
					? mRequest.activityOptions.getOriginalOptions() : null;
			// If the new record is the one that started, a new activity has created.
			final boolean newActivityCreated = mStartActivity == mLastStartActivityRecord;
			// Notify ActivityMetricsLogger that the activity has launched.
			// ActivityMetricsLogger will then wait for the windows to be drawn and populate
			// WaitResult.
			mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, res,
					newActivityCreated, mLastStartActivityRecord, originalOptions);
			if (mRequest.waitResult != null) {
				mRequest.waitResult.result = res;
				res = waitResultIfNeeded(mRequest.waitResult, mLastStartActivityRecord,
						launchingState);
			}
			return getExternalResult(res);
		}
	} finally {
		onExecutionComplete();
	}
}

ActivityStarter的executeRequest比较长,下面省略一部分内容。根据其注释内容"Executing activity start request and starts the journey of starting an activity"也可以看出,在这里处理了activity启动的请求。函数中,进行了权限检查,包括判断了是否为Home应用,创建了ActivityRecord记录这次启动为最后一次启动的Activity,然后调用startActivityUnchecked启动应用。

java 复制代码
// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
/**
 * Executing activity start request and starts the journey of starting an activity. Here
 * begins with performing several preliminary checks. The normally activity launch flow will
 * go through {@link #startActivityUnchecked} to {@link #startActivityInner}.
 */
private int executeRequest(Request request) {

	// 检查启动 权限
	boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
			requestCode, callingPid, callingUid, callingPackage, callingFeatureId,
			request.ignoreTargetSecurity, inTask != null, callerApp, resultRecord,
			resultRootTask);
	abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
			callingPid, resolvedType, aInfo.applicationInfo);
	abort |= !mService.getPermissionPolicyInternal().checkStartActivity(intent, callingUid,
			callingPackage);

	boolean restrictedBgActivity = false;
	if (!abort) {
		try {
			Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER,
					"shouldAbortBackgroundActivityStart");
			// 判断是否可以启动Activity.
			// 这里也会判断是否为Home应用,如果是Home应用的可以启动。如果不是,还要进行其他判断。
			restrictedBgActivity = shouldAbortBackgroundActivityStart(callingUid,
					callingPid, callingPackage, realCallingUid, realCallingPid, callerApp,
					request.originatingPendingIntent, request.allowBackgroundActivityStart,
					intent);
		} finally {
			Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
		}
	}
	
	// 创建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();
	// 记录为最后一次启动的Activity
	mLastStartActivityRecord = r;
	// 调用startActivityUnchecked,启动Activity
	mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
			request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,
			restrictedBgActivity, intentGrants);

	if (request.outActivity != null) {
		request.outActivity[0] = mLastStartActivityRecord;
	}

	return mLastStartActivityResult;
}

ActivityStarter的startActivityUnchecked函数会调用startActivityInner函数,在这个函数中获取加载Activity的RootTask加载Activity,并调用RootWindowContainer的resumeFocusedTasksTopActivities函数fork出一个进程来运行Activity。

java 复制代码
// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

/**
 * Start an activity while most of preliminary checks has been done and caller has been
 * confirmed that holds necessary permissions to do so.
 * Here also ensures that the starting activity is removed if the start wasn't successful.
 */
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
			IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
			int startFlags, boolean doResume, ActivityOptions options, Task inTask,
			boolean restrictedBgActivity, NeededUriGrants intentGrants) {
	// 省略
	try {
		mService.deferWindowLayout();
		Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
		// 调用startActivityInner
		result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
				startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);
	} finally {
		// 省略
	}

	postStartActivityProcessing(r, result, startedActivityRootTask);

	return result;
}


/**
 * Start an activity and determine if the activity should be adding to the top of an existing
 * task or delivered new intent to an existing activity. Also manipulating the activity task
 * onto requested or valid root-task/display.
 *
 * Note: This method should only be called from {@link #startActivityUnchecked}.
 */

// TODO(b/152429287): Make it easier to exercise code paths through startActivityInner
@VisibleForTesting
int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
		IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
		int startFlags, boolean doResume, ActivityOptions options, Task inTask,
		boolean restrictedBgActivity, NeededUriGrants intentGrants) {
	// 省略
	if (mTargetRootTask == null) {
		// 获取目标RootTask
		mTargetRootTask = getLaunchRootTask(mStartActivity, mLaunchFlags, targetTask, mOptions);
	}
	// 调用RootTask,startActivity(细节可以顺着这个函数看)
	mTargetRootTask.startActivityLocked(mStartActivity,
			topRootTask != null ? topRootTask.getTopNonFinishingActivity() : null, newTask,
			mKeepCurTransition, mOptions, sourceRecord);
			
	// mDoResume为Ture
	if (mDoResume) {
		if (!mTargetRootTask.isTopActivityFocusable()
				|| (topTaskActivity != null && topTaskActivity.isTaskOverlay()
				&& mStartActivity != topTaskActivity)) {
			// 省略
		} else {
			// If the target root-task was not previously focusable (previous top running
			// activity on that root-task was not visible) then any prior calls to move the
			// root-task to the will not update the focused root-task.  If starting the new
			// activity now allows the task root-task to be focusable, then ensure that we
			// now update the focused root-task accordingly.
			if (mTargetRootTask.isTopActivityFocusable()
					&& !mRootWindowContainer.isTopDisplayFocusedRootTask(mTargetRootTask)) {
				mTargetRootTask.moveToFront("startActivityInner");
			}
			mRootWindowContainer.resumeFocusedTasksTopActivities(
					mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
		}
	}
	mRootWindowContainer.updateUserRootTask(mStartActivity.mUserId, mTargetRootTask);

	// Update the recent tasks list immediately when the activity starts
	mSupervisor.mRecentTasks.add(mStartActivity.getTask());
	mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(),
			mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetRootTask);

	return START_SUCCESS;
}

启动的Activity如果是另一个应用,Android会fork出一个进程来加载Activity。那么是在哪里进行的fork?

在ActivityStarter的handleStartResult中,会进行fork进程操作(调用Process.start实现)

java 复制代码
// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
/**
 * Start an activity while most of preliminary checks has been done and caller has been
 * confirmed that holds necessary permissions to do so.
 * Here also ensures that the starting activity is removed if the start wasn't successful.
 */
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
		IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
		int startFlags, boolean doResume, ActivityOptions options, Task inTask,
		TaskFragment inTaskFragment, boolean restrictedBgActivity,
		NeededUriGrants intentGrants) {
	int result = START_CANCELED;
	final Task startedActivityRootTask;

	// Create a transition now to record the original intent of actions taken within
	// startActivityInner. Otherwise, logic in startActivityInner could start a different
	// transition based on a sub-action.
	// Only do the create here (and defer requestStart) since startActivityInner might abort.
	final TransitionController transitionController = r.mTransitionController;
	Transition newTransition = (!transitionController.isCollecting()
			&& transitionController.getTransitionPlayer() != null)
			? transitionController.createTransition(TRANSIT_OPEN) : null;
	RemoteTransition remoteTransition = r.takeRemoteTransition();
	if (newTransition != null && remoteTransition != null) {
		newTransition.setRemoteTransition(remoteTransition);
	}
	transitionController.collect(r);
	try {
		mService.deferWindowLayout();
		Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
		result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
				startFlags, doResume, options, inTask, inTaskFragment, restrictedBgActivity,
				intentGrants);
	} finally {
		Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
		// 这里会fork出一个进程(调用RootWindowContainer.ensureVisibilityAndConfig),最终调用Process.start
		startedActivityRootTask = handleStartResult(r, options, result, newTransition,
				remoteTransition);
		mService.continueWindowLayout();
	}
	postStartActivityProcessing(r, result, startedActivityRootTask);

	return result;
}

下面是调用的堆栈(Android13输出的,大概流程一样),感兴趣的可以依照堆栈看源码.

java 复制代码
ActivityTaskManager:     at com.android.server.wm.ActivityTaskManagerService.startProcessAsync(ActivityTaskManagerService.java:4683)
ActivityTaskManager:     at com.android.server.wm.ActivityTaskSupervisor.startSpecificActivity(ActivityTaskSupervisor.java:1013)
ActivityTaskManager:     at com.android.server.wm.EnsureActivitiesVisibleHelper.makeVisibleAndRestartIfNeeded(EnsureActivitiesVisibleHelper.java:265)
ActivityTaskManager:     at com.android.server.wm.EnsureActivitiesVisibleHelper.setActivityVisibilityState(EnsureActivitiesVisibleHelper.java:191)
ActivityTaskManager:     at com.android.server.wm.EnsureActivitiesVisibleHelper.process(EnsureActivitiesVisibleHelper.java:139)
ActivityTaskManager:     at com.android.server.wm.TaskFragment.updateActivityVisibilities(TaskFragment.java:985)
ActivityTaskManager:     at com.android.server.wm.Task.lambda$ensureActivitiesVisible$15(Task.java:4866)
ActivityTaskManager:     at com.android.server.wm.Task$$ExternalSyntheticLambda20.accept(Unknown Source:10)
ActivityTaskManager:     at com.android.server.wm.Task.forAllLeafTasks(Task.java:3185)
ActivityTaskManager:     at com.android.server.wm.Task.ensureActivitiesVisible(Task.java:4865)
ActivityTaskManager:     at com.android.server.wm.DisplayContent.lambda$ensureActivitiesVisible$46(DisplayContent.java:6000)
ActivityTaskManager:     at com.android.server.wm.DisplayContent$$ExternalSyntheticLambda17.accept(Unknown Source:10)
ActivityTaskManager:     at com.android.server.wm.Task.forAllRootTasks(Task.java:3197)
ActivityTaskManager:     at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:1806)
ActivityTaskManager:     at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:1806)
ActivityTaskManager:     at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:1806)
ActivityTaskManager:     at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:1806)
ActivityTaskManager:     at com.android.server.wm.WindowContainer.forAllRootTasks(WindowContainer.java:1799)
ActivityTaskManager:     at com.android.server.wm.DisplayContent.ensureActivitiesVisible(DisplayContent.java:5999)
ActivityTaskManager:     at com.android.server.wm.RootWindowContainer.ensureActivitiesVisible(RootWindowContainer.java:2075)
ActivityTaskManager:     at com.android.server.wm.RootWindowContainer.ensureVisibilityAndConfig(RootWindowContainer.java:1876)
ActivityTaskManager:     at com.android.server.wm.ActivityStarter.handleStartResult(ActivityStarter.java:1669)
ActivityTaskManager:     at com.android.server.wm.ActivityStarter.startActivityUnchecked(ActivityStarter.java:1598)
ActivityTaskManager:     at com.android.server.wm.ActivityStarter.executeRequest(ActivityStarter.java:1185)
ActivityTaskManager:     at com.android.server.wm.ActivityStarter.execute(ActivityStarter.java:672)
ActivityTaskManager:     at com.android.server.wm.ActivityTaskManagerService.startActivityAsUser(ActivityTaskManagerService.java:1243)
ActivityTaskManager:     at com.android.server.wm.ActivityTaskManagerService.startActivityAsUser(ActivityTaskManagerService.java:1215)
ActivityTaskManager:     at android.app.IActivityTaskManager$Stub.onTransact(IActivityTaskManager.java:969)
ActivityTaskManager:     at com.android.server.wm.ActivityTaskManagerService.onTransact(ActivityTaskManagerService.java:5152)
ActivityTaskManager:     at android.os.Binder.execTransactInternal(Binder.java:1179)
ActivityTaskManager:     at android.os.Binder.execTransact(Binder.java:1143)
ActivityTaskManager: java.lang.Throwable
相关推荐
拭心10 分钟前
Google 提供的 Android 端上大模型组件:MediaPipe LLM 介绍
android
带电的小王2 小时前
WhisperKit: Android 端测试 Whisper -- Android手机(Qualcomm GPU)部署音频大模型
android·智能手机·whisper·qualcomm
梦想平凡3 小时前
PHP 微信棋牌开发全解析:高级教程
android·数据库·oracle
元争栈道3 小时前
webview和H5来实现的android短视频(短剧)音视频播放依赖控件
android·音视频
阿甘知识库4 小时前
宝塔面板跨服务器数据同步教程:双机备份零停机
android·运维·服务器·备份·同步·宝塔面板·建站
元争栈道5 小时前
webview+H5来实现的android短视频(短剧)音视频播放依赖控件资源
android·音视频
MuYe5 小时前
Android Hook - 动态加载so库
android
居居飒5 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin
Henry_He8 小时前
桌面列表小部件不能点击的问题分析
android
工程师老罗9 小时前
Android笔试面试题AI答之Android基础(1)
android