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

AMS启动Activity分析

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

// 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。比如下述例子。

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中。

// 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

// 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。

// 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函数。

// 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启动应用。

// 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。


// 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实现)

// 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输出的,大概流程一样),感兴趣的可以依照堆栈看源码.

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/235242.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

智能优化算法应用:基于郊狼算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于郊狼算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于郊狼算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.郊狼算法4.实验参数设定5.算法结果6.参考文献7.MA…

关于IDEA中maven的作用以及如何配置MAVEN

关于IDEA中maven的作用以及如何配置MAVEN 1、Maven是什么2、Idea中对于Maven的配置3、下载依赖时&#xff0c;Idea下方的显示3.1、Maven中央仓库的下载显示界面3.2、阿里云仓库的下载显示界面 4、Maven在Idea中的使用4.1、clean4.2、validate4.3、compile4.4、test&#xff08;…

pyqt5使用Designer实现按钮上传图片

pyqt5使用Designer实现按钮上传图片 1、ui界面 2、ui转py代码 其中uploadimg.py代码如下&#xff1a; # -*- coding: utf-8 -*-# Form implementation generated from reading ui file uploadimg.ui # # Created by: PyQt5 UI code generator 5.15.4 # # WARNING: Any manua…

git 使用记录

远程仓库为空初始化 初始化本地仓库 git init 在本地仓库书写代码&#xff08;这里可以编辑一个文本文件做测试&#xff0c;如hello.txt&#xff09; 5&#xff09;执行&#xff1a;git add 要让git管理的文件&#xff08;git add hello.txt&#xff09;>执行完此操作将我…

有趣的数学 用示例来阐述什么是初值问题一

一、初值问题简述 在多变量微积分中&#xff0c;初值问题是一个常微分方程以及一个初始条件&#xff0c;该初始条件指定域中给定点处未知函数的值。在物理学或其他科学中对系统进行建模通常相当于解决初始值问题。 通常给定的微分方程有无数个解&#xff0c;因此我们很自然地会…

Linux 基础IO

文章目录 前言基础IO定义系统IO接口文件描述符重定向原理缓冲区刷新 前言 要知道每个函数/接口的全部参数和返回值建议去官网或者直接在Linux的man手册中查&#xff0c;这不是复制粘贴函数用法的文章。 C语言文件读写介绍链接 基础IO定义 IO是Input/Output的缩写&#xff0c…

【大数据】Hudi 核心知识点详解(一)

&#x1f60a; 如果您觉得这篇文章有用 ✔️ 的话&#xff0c;请给博主一个一键三连 &#x1f680;&#x1f680;&#x1f680; 吧 &#xff08;点赞 &#x1f9e1;、关注 &#x1f49b;、收藏 &#x1f49a;&#xff09;&#xff01;&#xff01;&#xff01;您的支持 &#x…

【操作宝典】VSCode解锁指南:释放潜能的详细教程!

目录 &#x1f4d6;前言 &#x1f680; 1 配置node.js &#x1f680;2. 使用脚本测试vue项目 &#x1f680;3. VSCode运行vue &#x1f680;4. VSCode引入elementUI &#x1f31f;4.1 显示OPENSSL错误 &#x1f4d6;前言 Visual Studio Code&#xff08;简称VSCode&#x…

MySQL数据库,创建和管理表

创建数据库&#xff1a; 方式一&#xff1a;创建数据库 CREATE DATABASE 数据库名&#xff1b;&#xff08;使用的是默认的字符集&#xff09; 方式二&#xff1a;创建数据库并指定字符集 CREATE DATABASE 数据库名 CHARACTER SET 字符集&#xff1b; 方式三&#xff1a;判断数…

基于若依的ruoyi-nbcio的flowable流程管理系统增加服务任务和我的抄送功能

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 1、增加一个状态字段 wf_copy增加下面两个字段 就用未读已读来区分 2、前端 api接口增加如下&#xff…

城市基础设施智慧路灯改造的特点

智慧城市建设稳步有序推进。作为智慧城市的基础设施&#xff0c;智能照明是智慧城市的重要组成部分&#xff0c;而叁仟智慧路灯是智慧城市理念下的新产品。随着物联网和智能控制技术的飞速发展&#xff0c;路灯被赋予了新的任务和角色。除了使道路照明智能化和节能化外&#xf…

Oracle(2-12)User-Managed Complete Recovery

文章目录 一、基础知识1、Media Recovery 介质恢复2、Recovery Steps 恢复步骤3、恢复4、Recovery in ARCHIVELOG 在ARCHIVELOG中恢复5、Complete Recovery完全恢复6、CR in ARCHIVELOG Mode 归档日志模式下的完全恢复7、Determine Files Need Recovery确定需要恢复的文件8、Ab…

HTTP与HTTPS的区别:安全性、协议地址和默认端口等比较

目录 ​编辑 作者其他博客链接&#xff1a; 一、概述 二、HTTP与HTTPS的区别 安全性 协议地址 默认端口 性能影响 三、比较与评估 浏览器支持 部署和维护成本 隐私保护 四、最佳实践建议 作者其他博客链接&#xff1a; 深入理解HashMap&#xff1a;Java中的键值对…

侯捷C++ (二--STL标准库)2

适配器 adapter 也可以叫做改造器&#xff0c;改造已经存在的东西 有&#xff1a;仿函数适配器、迭代器适配器、容器适配器 实现适配&#xff0c;可以使用继承、复合的两种方式实现。 共性&#xff1a;STL使用复合来实现适配 容器适配器 包括stack、queue&#xff0c;内含一…

win11 powershell conda 激活环境后不显示环境名称

win11 powershell conda 激活环境后不显示环境名称 问题现象解决方法 问题现象 安装 Anaconda 后在 powershell 中激活环境后&#xff0c;命令行前面不显示环境名称 解决方法 在 powershell 中执行 conda init 重新打开 poweshell 出现以下问题&#xff0c;请参考 win11 p…

fl studio 21破解版注册机下载 水果音乐编曲软件 FL Studio v21.

FL studio21中文别名水果编曲软件&#xff0c;是一款全能的音乐制作软件&#xff0c;包括编曲、录音、剪辑和混音等诸多功能&#xff0c;让你的电脑编程一个全能的录音室&#xff0c;它为您提供了一个集成的开发环境&#xff0c;使用起来非常简单有效&#xff0c;您的工作会变得…

zabbix、netdata和glances,做最简单的系统资源监控

软件需要显示服务器的资源信息&#xff08;CPU、内存、网络、硬盘等&#xff09;&#xff0c;但是软件是在Docker容器中运行。 目前方案 通过ssh在主机上远程运行ps、free等指令&#xff0c;获取相应的信息。这种方案需要代码配置主机的IP&#xff0c;以及用户名和密码&#…

指针(笔记1)

一、内存和地址 内存及其管理方法: 1.计算机主存储器由一个一个存储单元组成&#xff0c;微型计算机以字节作为存储单元 2.内存区的每一个字节有一个唯一的编号&#xff0c;这就是“地址”&#xff0c;它相当于教学楼中的教室号 3.内存地址&#xff0c;是一个无符号整数(un…

04.仿简道云公式函数实战-QLExpress基础语法

1. 前言 小伙伴大家好&#xff0c;在上一篇文章我们简单初探了QLExpress表达式引擎&#xff0c;我们简单写了一个HelloWorld的程序&#xff0c;并成功的运行期望的结果。在本篇文章中我们来熟悉一下QLExpress的语法&#xff0c;因为我们在后面简道云公式实战的时候&#xff0c…

java之SpringBoot开发实用篇

MENU SpringBoot开发实用篇KF-1.热部署KF-1-1.手动启动热部署KF-1-2.自动启动热部署KF-1-3.参与热部署监控的文件范围配置KF-1-4.关闭热部署 KF-2.配置高级KF-2-1.ConfigurationPropertiesKF-2-2.宽松绑定/松散绑定KF-2-3.常用计量单位绑定KF-2-4.校验KF-2-5.数据类型转换 KF-3…