Provide alternative find-task method without ActivityRecord
Restructure the task looks-up methods to allow finding tasks without passing in an ActivityRecord. This opens the opportunity of looking reusable tasks before building an ActivityRecord, which is the first step of stand-in activity replacement. Bug: 175354896 Test: presubmit Change-Id: Ic769790f0e5cbc921e144e1bb3d696519fc13555
This commit is contained in:
@@ -49,12 +49,6 @@
|
||||
"group": "WM_ERROR",
|
||||
"at": "com\/android\/server\/wm\/WindowManagerService.java"
|
||||
},
|
||||
"-2062338592": {
|
||||
"message": "Looking for task of %s",
|
||||
"level": "DEBUG",
|
||||
"group": "WM_DEBUG_TASKS",
|
||||
"at": "com\/android\/server\/wm\/RootWindowContainer.java"
|
||||
},
|
||||
"-2054442123": {
|
||||
"message": "Setting Intent of %s to %s",
|
||||
"level": "VERBOSE",
|
||||
@@ -475,6 +469,12 @@
|
||||
"group": "WM_DEBUG_WINDOW_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/Transition.java"
|
||||
},
|
||||
"-1559645910": {
|
||||
"message": "Looking for task of type=%s, taskAffinity=%s, intent=%s, info=%s, preferredTDA=%s",
|
||||
"level": "DEBUG",
|
||||
"group": "WM_DEBUG_TASKS",
|
||||
"at": "com\/android\/server\/wm\/RootWindowContainer.java"
|
||||
},
|
||||
"-1558137010": {
|
||||
"message": "Config is relaunching invisible activity %s called by %s",
|
||||
"level": "VERBOSE",
|
||||
@@ -1531,6 +1531,12 @@
|
||||
"group": "WM_DEBUG_APP_TRANSITIONS",
|
||||
"at": "com\/android\/server\/wm\/ActivityRecord.java"
|
||||
},
|
||||
"-373110070": {
|
||||
"message": "Skipping task: (mismatch activity\/task) %s",
|
||||
"level": "DEBUG",
|
||||
"group": "WM_DEBUG_TASKS",
|
||||
"at": "com\/android\/server\/wm\/RootWindowContainer.java"
|
||||
},
|
||||
"-354571697": {
|
||||
"message": "Existence Changed in transition %d: %s",
|
||||
"level": "VERBOSE",
|
||||
|
||||
@@ -547,19 +547,16 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
|
||||
return activityType == ACTIVITY_TYPE_STANDARD || activityType == ACTIVITY_TYPE_UNDEFINED;
|
||||
}
|
||||
|
||||
public boolean hasCompatibleActivityType(ConfigurationContainer other) {
|
||||
/*@WindowConfiguration.ActivityType*/ int thisType = getActivityType();
|
||||
/*@WindowConfiguration.ActivityType*/ int otherType = other.getActivityType();
|
||||
|
||||
if (thisType == otherType) {
|
||||
public static boolean isCompatibleActivityType(int currentType, int otherType) {
|
||||
if (currentType == otherType) {
|
||||
return true;
|
||||
}
|
||||
if (thisType == ACTIVITY_TYPE_ASSISTANT) {
|
||||
if (currentType == ACTIVITY_TYPE_ASSISTANT) {
|
||||
// Assistant activities are only compatible with themselves...
|
||||
return false;
|
||||
}
|
||||
// Otherwise we are compatible if us or other is not currently defined.
|
||||
return thisType == ACTIVITY_TYPE_UNDEFINED || otherType == ACTIVITY_TYPE_UNDEFINED;
|
||||
return currentType == ACTIVITY_TYPE_UNDEFINED || otherType == ACTIVITY_TYPE_UNDEFINED;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -306,52 +306,54 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
|
||||
private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
|
||||
|
||||
static class FindTaskResult implements Function<Task, Boolean> {
|
||||
ActivityRecord mRecord;
|
||||
boolean mIdealMatch;
|
||||
ActivityRecord mIdealRecord;
|
||||
ActivityRecord mCandidateRecord;
|
||||
|
||||
private ActivityRecord mTarget;
|
||||
private Intent intent;
|
||||
private ActivityInfo info;
|
||||
private int mActivityType;
|
||||
private String mTaskAffinity;
|
||||
private Intent mIntent;
|
||||
private ActivityInfo mInfo;
|
||||
private ComponentName cls;
|
||||
private int userId;
|
||||
private boolean isDocument;
|
||||
private Uri documentData;
|
||||
|
||||
void init(int activityType, String taskAffinity, Intent intent, ActivityInfo info) {
|
||||
mActivityType = activityType;
|
||||
mTaskAffinity = taskAffinity;
|
||||
mIntent = intent;
|
||||
mInfo = info;
|
||||
mIdealRecord = null;
|
||||
mCandidateRecord = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the top activity in any existing task matching the given Intent in the input
|
||||
* result. Returns null if no such task is found.
|
||||
*/
|
||||
void process(ActivityRecord target, Task parent) {
|
||||
mTarget = target;
|
||||
|
||||
intent = target.intent;
|
||||
info = target.info;
|
||||
cls = intent.getComponent();
|
||||
if (info.targetActivity != null) {
|
||||
cls = new ComponentName(info.packageName, info.targetActivity);
|
||||
void process(WindowContainer parent) {
|
||||
cls = mIntent.getComponent();
|
||||
if (mInfo.targetActivity != null) {
|
||||
cls = new ComponentName(mInfo.packageName, mInfo.targetActivity);
|
||||
}
|
||||
userId = UserHandle.getUserId(info.applicationInfo.uid);
|
||||
isDocument = intent != null & intent.isDocument();
|
||||
userId = UserHandle.getUserId(mInfo.applicationInfo.uid);
|
||||
isDocument = mIntent != null & mIntent.isDocument();
|
||||
// If documentData is non-null then it must match the existing task data.
|
||||
documentData = isDocument ? intent.getData() : null;
|
||||
documentData = isDocument ? mIntent.getData() : null;
|
||||
|
||||
ProtoLog.d(WM_DEBUG_TASKS, "Looking for task of %s in %s", target,
|
||||
ProtoLog.d(WM_DEBUG_TASKS, "Looking for task of %s in %s", mInfo,
|
||||
parent);
|
||||
parent.forAllLeafTasks(this);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
mRecord = null;
|
||||
mIdealMatch = false;
|
||||
}
|
||||
|
||||
void setTo(FindTaskResult result) {
|
||||
mRecord = result.mRecord;
|
||||
mIdealMatch = result.mIdealMatch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean apply(Task task) {
|
||||
if (!ConfigurationContainer.isCompatibleActivityType(mActivityType,
|
||||
task.getActivityType())) {
|
||||
ProtoLog.d(WM_DEBUG_TASKS, "Skipping task: (mismatch activity/task) %s", task);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (task.voiceSession != null) {
|
||||
// We never match voice sessions; those always run independently.
|
||||
ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: voice session", task);
|
||||
@@ -370,7 +372,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
|
||||
ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: mismatch root %s", task, r);
|
||||
return false;
|
||||
}
|
||||
if (!r.hasCompatibleActivityType(mTarget)) {
|
||||
if (!ConfigurationContainer.isCompatibleActivityType(r.getActivityType(),
|
||||
mActivityType)) {
|
||||
ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: mismatch activity type", task);
|
||||
return false;
|
||||
}
|
||||
@@ -391,35 +394,33 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
|
||||
}
|
||||
|
||||
ProtoLog.d(WM_DEBUG_TASKS, "Comparing existing cls=%s /aff=%s to new cls=%s /aff=%s",
|
||||
r.getTask().rootAffinity, intent.getComponent().flattenToShortString(),
|
||||
info.taskAffinity, (task.realActivity != null
|
||||
r.getTask().rootAffinity, mIntent.getComponent().flattenToShortString(),
|
||||
mInfo.taskAffinity, (task.realActivity != null
|
||||
? task.realActivity.flattenToShortString() : ""));
|
||||
// TODO Refactor to remove duplications. Check if logic can be simplified.
|
||||
if (task.realActivity != null && task.realActivity.compareTo(cls) == 0
|
||||
&& Objects.equals(documentData, taskDocumentData)) {
|
||||
ProtoLog.d(WM_DEBUG_TASKS, "Found matching class!");
|
||||
//dump();
|
||||
ProtoLog.d(WM_DEBUG_TASKS, "For Intent %s bringing to top: %s", intent, r.intent);
|
||||
mRecord = r;
|
||||
mIdealMatch = true;
|
||||
ProtoLog.d(WM_DEBUG_TASKS, "For Intent %s bringing to top: %s", mIntent, r.intent);
|
||||
mIdealRecord = r;
|
||||
return true;
|
||||
} else if (affinityIntent != null && affinityIntent.getComponent() != null
|
||||
&& affinityIntent.getComponent().compareTo(cls) == 0 &&
|
||||
Objects.equals(documentData, taskDocumentData)) {
|
||||
ProtoLog.d(WM_DEBUG_TASKS, "Found matching class!");
|
||||
ProtoLog.d(WM_DEBUG_TASKS, "For Intent %s bringing to top: %s", intent, r.intent);
|
||||
mRecord = r;
|
||||
mIdealMatch = true;
|
||||
ProtoLog.d(WM_DEBUG_TASKS, "For Intent %s bringing to top: %s", mIntent, r.intent);
|
||||
mIdealRecord = r;
|
||||
return true;
|
||||
} else if (!isDocument && !taskIsDocument
|
||||
&& mRecord == null && task.rootAffinity != null) {
|
||||
if (task.rootAffinity.equals(mTarget.taskAffinity)) {
|
||||
&& mIdealRecord == null && mCandidateRecord == null
|
||||
&& task.rootAffinity != null) {
|
||||
if (task.rootAffinity.equals(mTaskAffinity)) {
|
||||
ProtoLog.d(WM_DEBUG_TASKS, "Found matching affinity candidate!");
|
||||
// It is possible for multiple tasks to have the same root affinity especially
|
||||
// if they are in separate stacks. We save off this candidate, but keep looking
|
||||
// to see if there is a better candidate.
|
||||
mRecord = r;
|
||||
mIdealMatch = false;
|
||||
mCandidateRecord = r;
|
||||
}
|
||||
} else {
|
||||
ProtoLog.d(WM_DEBUG_TASKS, "Not a match: %s", task);
|
||||
@@ -2234,38 +2235,48 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
|
||||
|
||||
@Nullable
|
||||
ActivityRecord findTask(ActivityRecord r, TaskDisplayArea preferredTaskDisplayArea) {
|
||||
ProtoLog.d(WM_DEBUG_TASKS, "Looking for task of %s", r);
|
||||
mTmpFindTaskResult.clear();
|
||||
return findTask(r.getActivityType(), r.taskAffinity, r.intent, r.info,
|
||||
preferredTaskDisplayArea);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
ActivityRecord findTask(int activityType, String taskAffinity, Intent intent, ActivityInfo info,
|
||||
TaskDisplayArea preferredTaskDisplayArea) {
|
||||
ProtoLog.d(WM_DEBUG_TASKS, "Looking for task of type=%s, taskAffinity=%s, intent=%s"
|
||||
+ ", info=%s, preferredTDA=%s", activityType, taskAffinity, intent, info,
|
||||
preferredTaskDisplayArea);
|
||||
mTmpFindTaskResult.init(activityType, taskAffinity, intent, info);
|
||||
|
||||
// Looking up task on preferred display area first
|
||||
ActivityRecord candidateActivity = null;
|
||||
if (preferredTaskDisplayArea != null) {
|
||||
preferredTaskDisplayArea.findTaskLocked(r, true /* isPreferredDisplay */,
|
||||
mTmpFindTaskResult);
|
||||
if (mTmpFindTaskResult.mIdealMatch) {
|
||||
return mTmpFindTaskResult.mRecord;
|
||||
mTmpFindTaskResult.process(preferredTaskDisplayArea);
|
||||
if (mTmpFindTaskResult.mIdealRecord != null) {
|
||||
return mTmpFindTaskResult.mIdealRecord;
|
||||
} else if (mTmpFindTaskResult.mCandidateRecord != null) {
|
||||
candidateActivity = mTmpFindTaskResult.mCandidateRecord;
|
||||
}
|
||||
}
|
||||
|
||||
final ActivityRecord task = getItemFromTaskDisplayAreas(taskDisplayArea -> {
|
||||
final ActivityRecord idealMatchActivity = getItemFromTaskDisplayAreas(taskDisplayArea -> {
|
||||
if (taskDisplayArea == preferredTaskDisplayArea) {
|
||||
return null;
|
||||
}
|
||||
|
||||
taskDisplayArea.findTaskLocked(r, false /* isPreferredDisplay */,
|
||||
mTmpFindTaskResult);
|
||||
if (mTmpFindTaskResult.mIdealMatch) {
|
||||
return mTmpFindTaskResult.mRecord;
|
||||
mTmpFindTaskResult.process(taskDisplayArea);
|
||||
if (mTmpFindTaskResult.mIdealRecord != null) {
|
||||
return mTmpFindTaskResult.mIdealRecord;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
if (task != null) {
|
||||
return task;
|
||||
if (idealMatchActivity != null) {
|
||||
return idealMatchActivity;
|
||||
}
|
||||
|
||||
if (WM_DEBUG_TASKS.isEnabled() && mTmpFindTaskResult.mRecord == null) {
|
||||
if (WM_DEBUG_TASKS.isEnabled() && candidateActivity == null) {
|
||||
ProtoLog.d(WM_DEBUG_TASKS, "No task found");
|
||||
}
|
||||
return mTmpFindTaskResult.mRecord;
|
||||
return candidateActivity;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,7 +35,6 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
|
||||
|
||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
|
||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
|
||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
|
||||
import static com.android.server.wm.ActivityTaskManagerService.TAG_ROOT_TASK;
|
||||
import static com.android.server.wm.DisplayContent.alwaysCreateRootTask;
|
||||
import static com.android.server.wm.Task.ActivityState.RESUMED;
|
||||
@@ -131,9 +130,6 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> {
|
||||
*/
|
||||
Task mPreferredTopFocusableRootTask;
|
||||
|
||||
private final RootWindowContainer.FindTaskResult
|
||||
mTmpFindTaskResult = new RootWindowContainer.FindTaskResult();
|
||||
|
||||
/**
|
||||
* If this is the same as {@link #getFocusedRootTask} then the activity on the top of the
|
||||
* focused root task has been resumed. If root tasks are changing position this will hold the
|
||||
@@ -1391,43 +1387,6 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> {
|
||||
return someActivityPaused[0] > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find task for putting the Activity in.
|
||||
*/
|
||||
void findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplayArea,
|
||||
RootWindowContainer.FindTaskResult result) {
|
||||
mTmpFindTaskResult.clear();
|
||||
for (int i = mChildren.size() - 1; i >= 0; --i) {
|
||||
final Task rootTask = mChildren.get(i).asTask();
|
||||
if (rootTask == null) {
|
||||
continue;
|
||||
}
|
||||
if (!r.hasCompatibleActivityType(rootTask) && rootTask.isLeafTask()) {
|
||||
ProtoLog.d(WM_DEBUG_TASKS, "Skipping rootTask: (mismatch activity/rootTask) "
|
||||
+ "%s", rootTask);
|
||||
continue;
|
||||
}
|
||||
|
||||
mTmpFindTaskResult.process(r, rootTask);
|
||||
// It is possible to have tasks in multiple root tasks with the same root affinity, so
|
||||
// we should keep looking after finding an affinity match to see if there is a
|
||||
// better match in another root task. Also, task affinity isn't a good enough reason
|
||||
// to target a display which isn't the source of the intent, so skip any affinity
|
||||
// matches not on the specified display.
|
||||
if (mTmpFindTaskResult.mRecord != null) {
|
||||
if (mTmpFindTaskResult.mIdealMatch) {
|
||||
result.setTo(mTmpFindTaskResult);
|
||||
return;
|
||||
} else if (isPreferredDisplayArea) {
|
||||
// Note: since the traversing through the root tasks is top down, the floating
|
||||
// tasks should always have lower priority than any affinity-matching tasks
|
||||
// in the fullscreen root tasks
|
||||
result.setTo(mTmpFindTaskResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onSplitScreenModeDismissed() {
|
||||
// The focused task could be a non-resizeable fullscreen root task that is on top of the
|
||||
// other split-screen tasks, therefore had to dismiss split-screen, make sure the current
|
||||
|
||||
@@ -314,11 +314,12 @@ public class ActivityStackTests extends WindowTestsBase {
|
||||
|
||||
final RootWindowContainer.FindTaskResult result =
|
||||
new RootWindowContainer.FindTaskResult();
|
||||
result.process(r, task);
|
||||
result.init(r.getActivityType(), r.taskAffinity, r.intent, r.info);
|
||||
result.process(task);
|
||||
|
||||
assertEquals(r, task.getTopNonFinishingActivity(false /* includeOverlays */));
|
||||
assertEquals(taskOverlay, task.getTopNonFinishingActivity(true /* includeOverlays */));
|
||||
assertNotNull(result.mRecord);
|
||||
assertNotNull(result.mIdealRecord);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -340,15 +341,17 @@ public class ActivityStackTests extends WindowTestsBase {
|
||||
final ActivityRecord r1 = new ActivityBuilder(mAtm).setComponent(
|
||||
target).setTargetActivity(targetActivity).build();
|
||||
RootWindowContainer.FindTaskResult result = new RootWindowContainer.FindTaskResult();
|
||||
result.process(r1, parentTask);
|
||||
assertThat(result.mRecord).isNotNull();
|
||||
result.init(r1.getActivityType(), r1.taskAffinity, r1.intent, r1.info);
|
||||
result.process(parentTask);
|
||||
assertThat(result.mIdealRecord).isNotNull();
|
||||
|
||||
// Using alias activity to find task.
|
||||
final ActivityRecord r2 = new ActivityBuilder(mAtm).setComponent(
|
||||
alias).setTargetActivity(targetActivity).build();
|
||||
result = new RootWindowContainer.FindTaskResult();
|
||||
result.process(r2, parentTask);
|
||||
assertThat(result.mRecord).isNotNull();
|
||||
result.init(r2.getActivityType(), r2.taskAffinity, r2.intent, r2.info);
|
||||
result.process(parentTask);
|
||||
assertThat(result.mIdealRecord).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user