Moved startHomeActivity methods from AMS to ATMS (19/n)
Bug: 80414790
Test: Existing tests pass.
Change-Id: Ie3354304ea800777bd9ca7a83885b379776704e2
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index c1eab82..8e3eeae 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -39,6 +39,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.content.pm.ApplicationInfo.FLAG_FACTORY_TEST;
import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
import static android.content.pm.PackageManager.FEATURE_PC;
@@ -46,6 +47,9 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.res.Configuration.UI_MODE_TYPE_TELEVISION;
import static android.os.Build.VERSION_CODES.N;
+import static android.os.FactoryTest.FACTORY_TEST_HIGH_LEVEL;
+import static android.os.FactoryTest.FACTORY_TEST_LOW_LEVEL;
+import static android.os.FactoryTest.FACTORY_TEST_OFF;
import static android.os.Process.SYSTEM_UID;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
@@ -86,7 +90,6 @@
import static com.android.server.am.ActivityManagerService.SEND_LOCALE_TO_MOUNT_DAEMON_MSG;
import static com.android.server.am.ActivityManagerService.STOCK_PM_FLAGS;
import static com.android.server.am.ActivityManagerService.UPDATE_CONFIGURATION_MSG;
-import static com.android.server.am.ActivityManagerService.checkComponentPermission;
import static com.android.server.am.ActivityManagerService.dumpStackTraces;
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
@@ -167,6 +170,7 @@
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
+import android.os.FactoryTest;
import android.os.FileUtils;
import android.os.Handler;
import android.os.IBinder;
@@ -293,6 +297,7 @@
WindowProcessController mHomeProcess;
/** The currently running heavy-weight process, if any. */
WindowProcessController mHeavyWeightProcess = null;
+ boolean mHasHeavyWeightFeature;
/**
* This is the process holding the activity the user last visited that is in a different process
* from the one they are currently in.
@@ -388,6 +393,13 @@
IActivityController mController = null;
boolean mControllerIsAMonkey = false;
+ final int mFactoryTest;
+
+ /** Used to control how we initialize the service. */
+ ComponentName mTopComponent;
+ String mTopAction = Intent.ACTION_MAIN;
+ String mTopData;
+
/**
* Used to retain an update lock when the foreground activity is in
* immersive mode.
@@ -524,11 +536,14 @@
ActivityTaskManagerService(Context context) {
mContext = context;
+ mFactoryTest = FactoryTest.getMode();
mUiContext = ActivityThread.currentActivityThread().getSystemUiContext();
mLifecycleManager = new ClientLifecycleManager();
}
void onSystemReady() {
+ mHasHeavyWeightFeature = mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_CANT_SAVE_STATE);
mAssistUtils = new AssistUtils(mContext);
mVrController.onSystemReady();
mRecentTasks.onSystemReadyLocked();
@@ -2970,7 +2985,7 @@
}
/** This can be called with or without the global lock held. */
- void enforceCallerIsRecentsOrHasPermission(String permission, String func) {
+ private void enforceCallerIsRecentsOrHasPermission(String permission, String func) {
if (!getRecentTasks().isCallerRecents(Binder.getCallingUid())) {
mAmInternal.enforceCallingPermission(permission, func);
}
@@ -2988,6 +3003,12 @@
return checkComponentPermission(permission, pid, uid, -1, true);
}
+ public static int checkComponentPermission(String permission, int pid, int uid,
+ int owningUid, boolean exported) {
+ return ActivityManagerService.checkComponentPermission(
+ permission, pid, uid, owningUid, exported);
+ }
+
boolean isGetTasksAllowed(String caller, int callingPid, int callingUid) {
if (getRecentTasks().isCallerRecents(callingUid)) {
// Always allow the recents component to get tasks
@@ -5155,6 +5176,103 @@
return mAppWarnings;
}
+ Intent getHomeIntent() {
+ Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
+ intent.setComponent(mTopComponent);
+ intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
+ if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
+ intent.addCategory(Intent.CATEGORY_HOME);
+ }
+ return intent;
+ }
+
+ /**
+ * This starts home activity on displays that can have system decorations and only if the
+ * home activity can have multiple instances.
+ */
+ boolean startHomeActivityLocked(int userId, String reason, int displayId) {
+ if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL && mTopAction == null) {
+ // We are running in factory test mode, but unable to find the factory test app, so just
+ // sit around displaying the error message and don't try to start anything.
+ return false;
+ }
+
+ final Intent intent = getHomeIntent();
+ ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
+ if (aInfo != null) {
+ intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
+ // Don't do this if the home app is currently being instrumented.
+ aInfo = new ActivityInfo(aInfo);
+ aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
+ WindowProcessController app =
+ getProcessController(aInfo.processName, aInfo.applicationInfo.uid);
+ if (app == null || !app.isInstrumenting()) {
+ intent.setFlags(intent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
+ final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
+ // For ANR debugging to verify if the user activity is the one that actually
+ // launched.
+ final String myReason = reason + ":" + userId + ":" + resolvedUserId;
+ getActivityStartController().startHomeActivity(intent, aInfo, myReason, displayId);
+ }
+ } else {
+ Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
+ }
+
+ return true;
+ }
+
+ private ActivityInfo resolveActivityInfo(Intent intent, int flags, int userId) {
+ ActivityInfo ai = null;
+ final ComponentName comp = intent.getComponent();
+ try {
+ if (comp != null) {
+ // Factory test.
+ ai = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId);
+ } else {
+ ResolveInfo info = AppGlobals.getPackageManager().resolveIntent(
+ intent,
+ intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+ flags, userId);
+
+ if (info != null) {
+ ai = info.activityInfo;
+ }
+ }
+ } catch (RemoteException e) {
+ // ignore
+ }
+
+ return ai;
+ }
+
+ ApplicationInfo getAppInfoForUser(ApplicationInfo info, int userId) {
+ if (info == null) return null;
+ ApplicationInfo newInfo = new ApplicationInfo(info);
+ newInfo.initForUser(userId);
+ return newInfo;
+ }
+
+ private WindowProcessController getProcessController(String processName, int uid) {
+ if (uid == SYSTEM_UID) {
+ // The system gets to run in any process. If there are multiple processes with the same
+ // uid, just pick the first (this should never happen).
+ final SparseArray<WindowProcessController> procs =
+ mProcessNames.getMap().get(processName);
+ if (procs == null) return null;
+ final int procCount = procs.size();
+ for (int i = 0; i < procCount; i++) {
+ final int procUid = procs.keyAt(i);
+ if (UserHandle.isApp(procUid) || !UserHandle.isSameUser(procUid, uid)) {
+ // Don't use an app process or different user process for system component.
+ continue;
+ }
+ return procs.valueAt(i);
+ }
+ }
+
+ return mProcessNames.get(processName, uid);
+ }
+
void logAppTooSlow(WindowProcessController app, long startTime, String msg) {
if (true || Build.IS_USER) {
return;
@@ -5795,5 +5913,74 @@
return r.mServiceConnectionsHolder;
}
}
+
+ @Override
+ public Intent getHomeIntent() {
+ synchronized (mGlobalLock) {
+ return ActivityTaskManagerService.this.getHomeIntent();
+ }
+ }
+
+ @Override
+ public boolean startHomeActivity(int userId, String reason) {
+ synchronized (mGlobalLock) {
+ return startHomeActivityLocked(userId, reason, DEFAULT_DISPLAY);
+ }
+ }
+
+ @Override
+ public boolean isFactoryTestProcess(WindowProcessController wpc) {
+ synchronized (mGlobalLock) {
+ if (mFactoryTest == FACTORY_TEST_OFF) {
+ return false;
+ }
+ if (mFactoryTest == FACTORY_TEST_LOW_LEVEL && mTopComponent != null
+ && wpc.mName.equals(mTopComponent.getPackageName())) {
+ return true;
+ }
+ return mFactoryTest == FACTORY_TEST_HIGH_LEVEL
+ && (wpc.mInfo.flags & FLAG_FACTORY_TEST) != 0;
+ }
+ }
+
+ @Override
+ public void updateTopComponentForFactoryTest() {
+ synchronized (mGlobalLock) {
+ if (mFactoryTest != FACTORY_TEST_LOW_LEVEL) {
+ return;
+ }
+ final ResolveInfo ri = mContext.getPackageManager()
+ .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST), STOCK_PM_FLAGS);
+ final CharSequence errorMsg;
+ if (ri != null) {
+ final ActivityInfo ai = ri.activityInfo;
+ final ApplicationInfo app = ai.applicationInfo;
+ if ((app.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ mTopAction = Intent.ACTION_FACTORY_TEST;
+ mTopData = null;
+ mTopComponent = new ComponentName(app.packageName, ai.name);
+ errorMsg = null;
+ } else {
+ errorMsg = mContext.getResources().getText(
+ com.android.internal.R.string.factorytest_not_system);
+ }
+ } else {
+ errorMsg = mContext.getResources().getText(
+ com.android.internal.R.string.factorytest_no_action);
+ }
+ if (errorMsg == null) {
+ return;
+ }
+
+ mTopAction = null;
+ mTopData = null;
+ mTopComponent = null;
+ mUiHandler.post(() -> {
+ Dialog d = new FactoryErrorDialog(mUiContext, errorMsg);
+ d.show();
+ mAm.ensureBootCompleted();
+ });
+ }
+ }
}
}