Merge "Prevent IME from targeting home when closing app is still animating" into pi-dev

This commit is contained in:
TreeHugger Robot
2018-05-12 00:25:43 +00:00
committed by Android (Google) Code Review
5 changed files with 131 additions and 43 deletions

View File

@@ -800,6 +800,20 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack>
}
}
/**
* See {@link DisplayWindowController#deferUpdateImeTarget()}
*/
public void deferUpdateImeTarget() {
mWindowContainerController.deferUpdateImeTarget();
}
/**
* See {@link DisplayWindowController#deferUpdateImeTarget()}
*/
public void continueUpdateImeTarget() {
mWindowContainerController.continueUpdateImeTarget();
}
public void dump(PrintWriter pw, String prefix) {
pw.println(prefix + "displayId=" + mDisplayId + " stacks=" + mStacks.size());
final String myPrefix = prefix + " ";

View File

@@ -4592,46 +4592,58 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
}
// Shift all activities with this task up to the top
// of the stack, keeping them in the same internal order.
insertTaskAtTop(tr, null);
try {
// Defer updating the IME target since the new IME target will try to get computed
// before updating all closing and opening apps, which can cause the ime target to
// get calculated incorrectly.
getDisplay().deferUpdateImeTarget();
// Don't refocus if invisible to current user
final ActivityRecord top = tr.getTopActivity();
if (top == null || !top.okToShowLocked()) {
if (top != null) {
mStackSupervisor.mRecentTasks.add(top.getTask());
// Shift all activities with this task up to the top
// of the stack, keeping them in the same internal order.
insertTaskAtTop(tr, null);
// Don't refocus if invisible to current user
final ActivityRecord top = tr.getTopActivity();
if (top == null || !top.okToShowLocked()) {
if (top != null) {
mStackSupervisor.mRecentTasks.add(top.getTask());
}
ActivityOptions.abort(options);
return;
}
ActivityOptions.abort(options);
return;
}
// Set focus to the top running activity of this stack.
final ActivityRecord r = topRunningActivityLocked();
mStackSupervisor.moveFocusableActivityStackToFrontLocked(r, reason);
// Set focus to the top running activity of this stack.
final ActivityRecord r = topRunningActivityLocked();
mStackSupervisor.moveFocusableActivityStackToFrontLocked(r, reason);
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr);
if (noAnimation) {
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
if (r != null) {
mStackSupervisor.mNoAnimActivities.add(r);
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr);
if (noAnimation) {
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
if (r != null) {
mStackSupervisor.mNoAnimActivities.add(r);
}
ActivityOptions.abort(options);
} else {
updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
}
ActivityOptions.abort(options);
} else {
updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
}
// If a new task is moved to the front, then mark the existing top activity as supporting
// picture-in-picture while paused only if the task would not be considered an oerlay on top
// of the current activity (eg. not fullscreen, or the assistant)
if (canEnterPipOnTaskSwitch(topActivity, tr, null /* toFrontActivity */,
options)) {
topActivity.supportsEnterPipOnTaskSwitch = true;
}
// If a new task is moved to the front, then mark the existing top activity as
// supporting
mStackSupervisor.resumeFocusedStackTopActivityLocked();
EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
// picture-in-picture while paused only if the task would not be considered an oerlay
// on top
// of the current activity (eg. not fullscreen, or the assistant)
if (canEnterPipOnTaskSwitch(topActivity, tr, null /* toFrontActivity */,
options)) {
topActivity.supportsEnterPipOnTaskSwitch = true;
}
mService.mTaskChangeNotificationController.notifyTaskMovedToFront(tr.taskId);
mStackSupervisor.resumeFocusedStackTopActivityLocked();
EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
mService.mTaskChangeNotificationController.notifyTaskMovedToFront(tr.taskId);
} finally {
getDisplay().continueUpdateImeTarget();
}
}
/**

View File

@@ -390,6 +390,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
*/
int mLayoutSeq = 0;
/**
* Specifies the count to determine whether to defer updating the IME target until ready.
*/
private int mDeferUpdateImeTargetCount;
/** Temporary float array to retrieve 3x3 matrix values. */
private final float[] mTmpFloats = new float[9];
@@ -2454,6 +2459,12 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
return null;
}
final WindowState curTarget = mService.mInputMethodTarget;
if (!canUpdateImeTarget()) {
if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Defer updating IME target");
return curTarget;
}
// TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
// same display. Or even when the current IME/target are not on the same screen as the next
// IME/target. For now only look for input windows on the main screen.
@@ -2477,16 +2488,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (DEBUG_INPUT_METHOD && updateImeTarget) Slog.v(TAG_WM,
"Proposed new IME target: " + target);
// Now, a special case -- if the last target's window is in the process of exiting, and is
// above the new target, keep on the last target to avoid flicker. Consider for example a
// Dialog with the IME shown: when the Dialog is dismissed, we want to keep the IME above it
// until it is completely gone so it doesn't drop behind the dialog or its full-screen
// scrim.
final WindowState curTarget = mService.mInputMethodTarget;
// Now, a special case -- if the last target's window is in the process of exiting, and the
// new target is home, keep on the last target to avoid flicker. Home is a special case
// since its above other stacks in the ordering list, but layed out below the others.
if (curTarget != null && curTarget.isDisplayedLw() && curTarget.isClosing()
&& (target == null
|| curTarget.mWinAnimator.mAnimLayer > target.mWinAnimator.mAnimLayer)) {
if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Current target higher, not changing");
&& (target == null || target.isActivityTypeHome())) {
if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "New target is home while current target is"
+ "closing, not changing");
return curTarget;
}
@@ -3958,4 +3966,33 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
void assignStackOrdering() {
mTaskStackContainers.assignStackOrdering(getPendingTransaction());
}
/**
* Increment the deferral count to determine whether to update the IME target.
*/
void deferUpdateImeTarget() {
mDeferUpdateImeTargetCount++;
}
/**
* Decrement the deferral count to determine whether to update the IME target. If the count
* reaches 0, a new ime target will get computed.
*/
void continueUpdateImeTarget() {
if (mDeferUpdateImeTargetCount == 0) {
return;
}
mDeferUpdateImeTargetCount--;
if (mDeferUpdateImeTargetCount == 0) {
computeImeTarget(true /* updateImeTarget */);
}
}
/**
* @return Whether a new IME target should be computed.
*/
private boolean canUpdateImeTarget() {
return mDeferUpdateImeTargetCount == 0;
}
}

View File

@@ -94,6 +94,31 @@ public class DisplayWindowController
}
}
/**
* Starts deferring the ability to update the IME target. This is needed when a call will
* attempt to update the IME target before all information about the Windows have been updated.
*/
public void deferUpdateImeTarget() {
synchronized (mWindowMap) {
final DisplayContent dc = mRoot.getDisplayContent(mDisplayId);
if (dc != null) {
dc.deferUpdateImeTarget();
}
}
}
/**
* Resumes updating the IME target after deferring. See {@link #deferUpdateImeTarget()}
*/
public void continueUpdateImeTarget() {
synchronized (mWindowMap) {
final DisplayContent dc = mRoot.getDisplayContent(mDisplayId);
if (dc != null) {
dc.continueUpdateImeTarget();
}
}
}
@Override
public String toString() {
return "{DisplayWindowController displayId=" + mDisplayId + "}";

View File

@@ -2726,7 +2726,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
boolean isClosing() {
return mAnimatingExit || (mService.mClosingApps.contains(mAppToken));
return mAnimatingExit || (mAppToken.isAnimating() && mAppToken.hiddenRequested);
}
void addWinAnimatorToList(ArrayList<WindowStateAnimator> animators) {