Merge "Some fixes for docking from navigation bar use case"

This commit is contained in:
Chong Zhang
2016-01-06 21:36:29 +00:00
committed by Android (Google) Code Review
4 changed files with 78 additions and 15 deletions

View File

@@ -1958,10 +1958,10 @@ public final class ActivityStackSupervisor implements DisplayListener {
|| tempOtherTaskInsetBounds != null);
}
void resizeTaskLocked(TaskRecord task, Rect bounds, int resizeMode, boolean preserveWindow) {
boolean resizeTaskLocked(TaskRecord task, Rect bounds, int resizeMode, boolean preserveWindow) {
if (!task.mResizeable) {
Slog.w(TAG, "resizeTask: task " + task + " not resizeable.");
return;
return true;
}
adjustForMinimalTaskDimensions(task, bounds);
@@ -1971,7 +1971,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
if (task.mBounds != null && task.mBounds.equals(bounds) && !forced) {
// Nothing to do here...
return;
return true;
}
if (!mWindowManager.isValidTaskId(task.taskId)) {
@@ -1983,7 +1983,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
// re-restore the task so it can have the proper stack association.
restoreRecentTaskLocked(task, FREEFORM_WORKSPACE_STACK_ID);
}
return;
return true;
}
// Do not move the task to another stack here.
@@ -2012,6 +2012,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
mWindowManager.resizeTask(task.taskId, bounds, task.mOverrideConfig, kept, forced);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
return kept;
}
private void adjustForMinimalTaskDimensions(TaskRecord task, Rect bounds) {
@@ -2169,13 +2170,17 @@ public final class ActivityStackSupervisor implements DisplayListener {
}
final ActivityRecord topActivity = task.getTopActivity();
if (StackId.preserveWindowOnTaskMove(stackId) && topActivity != null) {
final boolean mightReplaceWindow =
StackId.preserveWindowOnTaskMove(stackId) && topActivity != null;
if (mightReplaceWindow) {
// We are about to relaunch the activity because its configuration changed due to
// being maximized, i.e. size change. The activity will first remove the old window
// and then add a new one. This call will tell window manager about this, so it can
// preserve the old window until the new one is drawn. This prevents having a gap
// between the removal and addition, in which no window is visible. We also want the
// entrance of the new window to be properly animated.
// Note here we always set the replacing window first, as the flags might be needed
// during the relaunch. If we end up not doing any relaunch, we clear the flags later.
mWindowManager.setReplacingWindow(topActivity.appToken, animate);
}
final ActivityStack stack = moveTaskToStackUncheckedLocked(
@@ -2185,15 +2190,23 @@ public final class ActivityStackSupervisor implements DisplayListener {
stack.mNoAnimActivities.add(topActivity);
}
boolean kept = true;
// Make sure the task has the appropriate bounds/size for the stack it is in.
if (stackId == FULLSCREEN_WORKSPACE_STACK_ID && task.mBounds != null) {
resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM, !PRESERVE_WINDOWS);
kept = resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM, !PRESERVE_WINDOWS);
} else if (stackId == FREEFORM_WORKSPACE_STACK_ID
&& task.mBounds == null && task.mLastNonFullscreenBounds != null) {
resizeTaskLocked(task, task.mLastNonFullscreenBounds,
kept = resizeTaskLocked(task, task.mLastNonFullscreenBounds,
RESIZE_MODE_SYSTEM, !PRESERVE_WINDOWS);
} else if (stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID) {
resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM, !PRESERVE_WINDOWS);
kept = resizeTaskLocked(task, stack.mBounds, RESIZE_MODE_SYSTEM, !PRESERVE_WINDOWS);
}
if (mightReplaceWindow) {
// If we didn't actual do a relaunch (indicated by kept==true meaning we kept the old
// window), we need to clear the replace window settings. Otherwise, we schedule a
// timeout to remove the old window if the replacing window is not coming in time.
mWindowManager.scheduleClearReplacingWindowIfNeeded(topActivity.appToken, !kept);
}
// The task might have already been running and its visibility needs to be synchronized with

View File

@@ -25,6 +25,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.WINDOW_REPLACEMENT_TIMEOUT_DURATION;
import com.android.server.input.InputApplicationHandle;
import com.android.server.wm.WindowManagerService.H;
@@ -403,12 +404,28 @@ class AppWindowToken extends WindowToken {
}
}
void resetReplacingWindows() {
if (DEBUG_ADD_REMOVE) Slog.d(TAG_WM, "Resetting app token " + appWindowToken
+ " of replacing window marks.");
for (int i = allAppWindows.size() - 1; i >= 0; i--) {
final WindowState w = allAppWindows.get(i);
w.resetReplacing();
}
}
void addWindow(WindowState w) {
for (int i = allAppWindows.size() - 1; i >= 0; i--) {
WindowState candidate = allAppWindows.get(i);
if (candidate.mWillReplaceWindow && candidate.mReplacingWindow == null &&
candidate.getWindowTag().equals(w.getWindowTag().toString())) {
candidate.mReplacingWindow = w;
// if we got a replacement window, reset the timeout to give drawing more time
service.mH.removeMessages(H.WINDOW_REPLACEMENT_TIMEOUT);
service.mH.sendMessageDelayed(
service.mH.obtainMessage(H.WINDOW_REPLACEMENT_TIMEOUT, this),
WINDOW_REPLACEMENT_TIMEOUT_DURATION);
}
}
allAppWindows.add(w);
@@ -424,7 +441,7 @@ class AppWindowToken extends WindowToken {
return false;
}
void clearTimedoutReplaceesLocked() {
void clearTimedoutReplacesLocked() {
for (int i = allAppWindows.size() - 1; i >= 0;
// removeWindowLocked at bottom of loop may remove multiple entries from
// allAppWindows if the window to be removed has child windows. It also may
@@ -437,7 +454,11 @@ class AppWindowToken extends WindowToken {
continue;
}
candidate.mWillReplaceWindow = false;
service.removeWindowLocked(candidate);
// Since the window already timed out, remove it immediately now.
// Use removeWindowInnerLocked() instead of removeWindowLocked(), as the latter
// delays removal on certain conditions, which will leave the stale window in the
// stack and marked mWillReplaceWindow=false, so the window will never be removed.
service.removeWindowInnerLocked(candidate);
}
}

View File

@@ -8106,7 +8106,7 @@ public class WindowManagerService extends IWindowManager.Stub
case WINDOW_REPLACEMENT_TIMEOUT: {
final AppWindowToken token = (AppWindowToken) msg.obj;
synchronized (mWindowMap) {
token.clearTimedoutReplaceesLocked();
token.clearTimedoutReplacesLocked();
}
}
break;
@@ -10192,11 +10192,34 @@ public class WindowManagerService extends IWindowManager.Stub
}
appWindowToken.setReplacingWindows(animate);
}
}
if (appWindowToken != null) {
mH.removeMessages(H.WINDOW_REPLACEMENT_TIMEOUT);
mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_REPLACEMENT_TIMEOUT, appWindowToken),
WINDOW_REPLACEMENT_TIMEOUT_DURATION);
/**
* If we're replacing the window, schedule a timer to clear the replaced window
* after a timeout, in case the replacing window is not coming.
*
* If we're not replacing the window, clear the replace window settings of the app.
*
* @param token Application token for the activity whose window might be replaced.
* @param replacing Whether the window is being replaced or not.
*/
public void scheduleClearReplacingWindowIfNeeded(IBinder token, boolean replacing) {
AppWindowToken appWindowToken = null;
synchronized (mWindowMap) {
appWindowToken = findAppWindowToken(token);
if (appWindowToken == null) {
Slog.w(TAG_WM, "Attempted to reset replacing window on non-existing app token "
+ token);
return;
}
if (replacing) {
mH.removeMessages(H.WINDOW_REPLACEMENT_TIMEOUT);
mH.sendMessageDelayed(
mH.obtainMessage(H.WINDOW_REPLACEMENT_TIMEOUT, appWindowToken),
WINDOW_REPLACEMENT_TIMEOUT_DURATION);
} else {
appWindowToken.resetReplacingWindows();
}
}
}

View File

@@ -2363,4 +2363,10 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mReplacingWindow = null;
mAnimateReplacingWindow = animate;
}
void resetReplacing() {
mWillReplaceWindow = false;
mReplacingWindow = null;
mAnimateReplacingWindow = false;
}
}