Merge "Simplify check-behind-fullscreen-activity"
This commit is contained in:
@@ -4605,8 +4605,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
return false;
|
||||
}
|
||||
|
||||
final boolean behindFullscreenActivity = stack.checkBehindFullscreenActivity(
|
||||
this, null /* handleBehindFullscreenActivity */);
|
||||
final boolean behindFullscreenActivity = !stack.shouldBeVisible(null /* starting */)
|
||||
|| stack.getOccludingActivityAbove(this) != null;
|
||||
return shouldBeVisible(behindFullscreenActivity, false /* ignoringKeyguard */);
|
||||
}
|
||||
|
||||
|
||||
@@ -328,81 +328,6 @@ class ActivityStack extends Task {
|
||||
}
|
||||
}
|
||||
|
||||
private final CheckBehindFullscreenActivityHelper mCheckBehindFullscreenActivityHelper =
|
||||
new CheckBehindFullscreenActivityHelper();
|
||||
private class CheckBehindFullscreenActivityHelper {
|
||||
private boolean mAboveTop;
|
||||
private boolean mBehindFullscreenActivity;
|
||||
private ActivityRecord mToCheck;
|
||||
private Consumer<ActivityRecord> mHandleBehindFullscreenActivity;
|
||||
private boolean mHandlingOccluded;
|
||||
|
||||
private void reset(ActivityRecord toCheck,
|
||||
Consumer<ActivityRecord> handleBehindFullscreenActivity) {
|
||||
mToCheck = toCheck;
|
||||
mHandleBehindFullscreenActivity = handleBehindFullscreenActivity;
|
||||
mAboveTop = true;
|
||||
mBehindFullscreenActivity = false;
|
||||
|
||||
if (!shouldBeVisible(null)) {
|
||||
// The stack is not visible, so no activity in it should be displaying a starting
|
||||
// window. Mark all activities below top and behind fullscreen.
|
||||
mAboveTop = false;
|
||||
mBehindFullscreenActivity = true;
|
||||
}
|
||||
|
||||
mHandlingOccluded = mToCheck == null && mHandleBehindFullscreenActivity != null;
|
||||
}
|
||||
|
||||
boolean process(ActivityRecord toCheck,
|
||||
Consumer<ActivityRecord> handleBehindFullscreenActivity) {
|
||||
reset(toCheck, handleBehindFullscreenActivity);
|
||||
|
||||
if (!mHandlingOccluded && mBehindFullscreenActivity) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final ActivityRecord topActivity = topRunningActivity();
|
||||
final PooledFunction f = PooledLambda.obtainFunction(
|
||||
CheckBehindFullscreenActivityHelper::processActivity, this,
|
||||
PooledLambda.__(ActivityRecord.class), topActivity);
|
||||
forAllActivities(f);
|
||||
f.recycle();
|
||||
|
||||
return mBehindFullscreenActivity;
|
||||
}
|
||||
|
||||
/** Returns {@code true} to stop the outer loop and indicate the result is computed. */
|
||||
private boolean processActivity(ActivityRecord r, ActivityRecord topActivity) {
|
||||
if (mAboveTop) {
|
||||
if (r == topActivity) {
|
||||
if (r == mToCheck) {
|
||||
// It is the top activity in a visible stack.
|
||||
mBehindFullscreenActivity = false;
|
||||
return true;
|
||||
}
|
||||
mAboveTop = false;
|
||||
}
|
||||
mBehindFullscreenActivity |= r.occludesParent();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mHandlingOccluded) {
|
||||
// Iterating through all occluded activities.
|
||||
if (mBehindFullscreenActivity) {
|
||||
mHandleBehindFullscreenActivity.accept(r);
|
||||
}
|
||||
} else if (r == mToCheck) {
|
||||
return true;
|
||||
} else if (mBehindFullscreenActivity) {
|
||||
// It is occluded before {@param toCheck} is found.
|
||||
return true;
|
||||
}
|
||||
mBehindFullscreenActivity |= r.occludesParent();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Can we just loop through WindowProcessController#mActivities instead of doing this?
|
||||
private final RemoveHistoryRecordsForApp mRemoveHistoryRecordsForApp =
|
||||
new RemoveHistoryRecordsForApp();
|
||||
@@ -1434,25 +1359,6 @@ class ActivityStack extends Task {
|
||||
}
|
||||
}
|
||||
|
||||
/** @see ActivityRecord#cancelInitializing() */
|
||||
void cancelInitializingActivities() {
|
||||
// We don't want to clear starting window for activities that aren't behind fullscreen
|
||||
// activities as we need to display their starting window until they are done initializing.
|
||||
checkBehindFullscreenActivity(null /* toCheck */, ActivityRecord::cancelInitializing);
|
||||
}
|
||||
|
||||
/**
|
||||
* If an activity {@param toCheck} is given, this method returns {@code true} if the activity
|
||||
* is occluded by any fullscreen activity. If there is no {@param toCheck} and the handling
|
||||
* function {@param handleBehindFullscreenActivity} is given, this method will pass all occluded
|
||||
* activities to the function.
|
||||
*/
|
||||
boolean checkBehindFullscreenActivity(ActivityRecord toCheck,
|
||||
Consumer<ActivityRecord> handleBehindFullscreenActivity) {
|
||||
return mCheckBehindFullscreenActivityHelper.process(
|
||||
toCheck, handleBehindFullscreenActivity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the top activity in the stack is resumed.
|
||||
*
|
||||
@@ -2660,16 +2566,6 @@ class ActivityStack extends Task {
|
||||
task.setBounds(task.isResizeable() ? bounds : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the top-most activity that occludes the given one, or @{code null} if none.
|
||||
*/
|
||||
@Nullable
|
||||
private ActivityRecord getOccludingActivityAbove(ActivityRecord activity) {
|
||||
ActivityRecord top = getActivity((ar) -> ar.occludesParent(),
|
||||
true /* traverseTopToBottom */, activity);
|
||||
return top != activity ? top : null;
|
||||
}
|
||||
|
||||
boolean willActivityBeVisible(IBinder token) {
|
||||
final ActivityRecord r = ActivityRecord.forTokenLocked(token);
|
||||
if (r == null) {
|
||||
|
||||
@@ -3353,7 +3353,10 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
|
||||
void cancelInitializingActivities() {
|
||||
forAllTaskDisplayAreas(taskDisplayArea -> {
|
||||
for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
|
||||
taskDisplayArea.getStackAt(sNdx).cancelInitializingActivities();
|
||||
// We don't want to clear starting window for activities that aren't occluded
|
||||
// as we need to display their starting window until they are done initializing.
|
||||
taskDisplayArea.getStackAt(sNdx).forAllOccludedActivities(
|
||||
ActivityRecord::cancelInitializing);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3175,6 +3175,33 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Returns the top-most activity that occludes the given one, or {@code null} if none. */
|
||||
@Nullable
|
||||
ActivityRecord getOccludingActivityAbove(ActivityRecord activity) {
|
||||
final ActivityRecord top = getActivity(ActivityRecord::occludesParent,
|
||||
true /* traverseTopToBottom */, activity);
|
||||
return top != activity ? top : null;
|
||||
}
|
||||
|
||||
/** Iterates through all occluded activities. */
|
||||
void forAllOccludedActivities(Consumer<ActivityRecord> handleOccludedActivity) {
|
||||
if (!shouldBeVisible(null /* starting */)) {
|
||||
// The stack is invisible so all activities are occluded.
|
||||
forAllActivities(handleOccludedActivity);
|
||||
return;
|
||||
}
|
||||
final ActivityRecord topOccluding = getOccludingActivityAbove(null);
|
||||
if (topOccluding == null) {
|
||||
// No activities are occluded.
|
||||
return;
|
||||
}
|
||||
// Invoke the callback on the activities behind the top occluding activity.
|
||||
forAllActivities(r -> {
|
||||
handleOccludedActivity.accept(r);
|
||||
return false;
|
||||
}, topOccluding, false /* includeBoundary */, true /* traverseTopToBottom */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurfaceControl.Builder makeAnimationLeash() {
|
||||
return super.makeAnimationLeash().setMetadata(METADATA_TASK_ID, mTaskId);
|
||||
|
||||
@@ -1331,42 +1331,40 @@ public class ActivityStackTests extends ActivityTestsBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckBehindFullscreenActivity() {
|
||||
public void testIterateOccludedActivity() {
|
||||
final ArrayList<ActivityRecord> occludedActivities = new ArrayList<>();
|
||||
final Consumer<ActivityRecord> handleBehindFullscreenActivity = occludedActivities::add;
|
||||
final Consumer<ActivityRecord> handleOccludedActivity = occludedActivities::add;
|
||||
final ActivityRecord bottomActivity =
|
||||
new ActivityBuilder(mService).setStack(mStack).setTask(mTask).build();
|
||||
final ActivityRecord topActivity =
|
||||
new ActivityBuilder(mService).setStack(mStack).setTask(mTask).build();
|
||||
doReturn(true).when(mStack).shouldBeVisible(any());
|
||||
assertTrue(mStack.checkBehindFullscreenActivity(bottomActivity,
|
||||
null /* handleBehindFullscreenActivity */));
|
||||
assertFalse(mStack.checkBehindFullscreenActivity(topActivity,
|
||||
null /* handleBehindFullscreenActivity */));
|
||||
|
||||
// Top activity occludes bottom activity.
|
||||
mStack.checkBehindFullscreenActivity(null /* toCheck */, handleBehindFullscreenActivity);
|
||||
doReturn(true).when(mStack).shouldBeVisible(any());
|
||||
assertTrue(topActivity.shouldBeVisible());
|
||||
assertFalse(bottomActivity.shouldBeVisible());
|
||||
|
||||
mStack.forAllOccludedActivities(handleOccludedActivity);
|
||||
assertThat(occludedActivities).containsExactly(bottomActivity);
|
||||
|
||||
// Top activity doesn't occlude parent, so the bottom activity is not occluded.
|
||||
doReturn(false).when(topActivity).occludesParent();
|
||||
assertFalse(mStack.checkBehindFullscreenActivity(bottomActivity,
|
||||
null /* handleBehindFullscreenActivity */));
|
||||
assertFalse(mStack.checkBehindFullscreenActivity(topActivity,
|
||||
null /* handleBehindFullscreenActivity */));
|
||||
assertTrue(bottomActivity.shouldBeVisible());
|
||||
|
||||
occludedActivities.clear();
|
||||
// Top activity doesn't occlude parent, so the bottom activity is not occluded.
|
||||
mStack.checkBehindFullscreenActivity(null /* toCheck */, handleBehindFullscreenActivity);
|
||||
mStack.forAllOccludedActivities(handleOccludedActivity);
|
||||
assertThat(occludedActivities).isEmpty();
|
||||
|
||||
// A finishing activity should not occlude other activities behind.
|
||||
final ActivityRecord finishingActivity =
|
||||
new ActivityBuilder(mService).setStack(mStack).setTask(mTask).build();
|
||||
finishingActivity.finishing = true;
|
||||
doCallRealMethod().when(finishingActivity).occludesParent();
|
||||
assertFalse(mStack.checkBehindFullscreenActivity(bottomActivity,
|
||||
null /* handleBehindFullscreenActivity */));
|
||||
assertFalse(mStack.checkBehindFullscreenActivity(topActivity,
|
||||
null /* handleBehindFullscreenActivity */));
|
||||
assertTrue(topActivity.shouldBeVisible());
|
||||
assertTrue(bottomActivity.shouldBeVisible());
|
||||
|
||||
occludedActivities.clear();
|
||||
mStack.forAllOccludedActivities(handleOccludedActivity);
|
||||
assertThat(occludedActivities).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user