Merge "Fixed transition animation from pipable activities" into oc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
3fc176913a
@@ -1568,17 +1568,21 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
|
||||
}
|
||||
|
||||
void setVisibility(boolean visible) {
|
||||
mWindowContainerController.setVisibility(visible);
|
||||
mWindowContainerController.setVisibility(visible, false /* deferHidingClient */);
|
||||
}
|
||||
|
||||
void setVisible(boolean newVisible) {
|
||||
setVisible(newVisible, false /* deferHidingClient */);
|
||||
}
|
||||
|
||||
// TODO: Look into merging with #setVisibility()
|
||||
void setVisible(boolean newVisible) {
|
||||
void setVisible(boolean newVisible, boolean deferHidingClient) {
|
||||
visible = newVisible;
|
||||
if (!visible && mUpdateTaskThumbnailWhenHidden) {
|
||||
updateThumbnailLocked(screenshotActivityLocked(), null /* description */);
|
||||
mUpdateTaskThumbnailWhenHidden = false;
|
||||
}
|
||||
mWindowContainerController.setVisibility(visible);
|
||||
mWindowContainerController.setVisibility(visible, deferHidingClient);
|
||||
final ArrayList<ActivityContainer> containers = mChildContainers;
|
||||
for (int containerNdx = containers.size() - 1; containerNdx >= 0; --containerNdx) {
|
||||
final ActivityContainer container = containers.get(containerNdx);
|
||||
|
||||
@@ -1407,7 +1407,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
|
||||
} else if ((!prev.visible && !hasVisibleBehindActivity())
|
||||
|| mService.isSleepingOrShuttingDownLocked()) {
|
||||
// If we were visible then resumeTopActivities will release resources before
|
||||
// stopping.
|
||||
// stopping. Also, set visibility to false to flush any client hide that might have
|
||||
// been deferred.
|
||||
prev.setVisibility(false);
|
||||
addToStopping(prev, true /* scheduleIdle */, false /* idleDelayed */);
|
||||
}
|
||||
} else {
|
||||
@@ -2024,11 +2026,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
|
||||
try {
|
||||
final boolean canEnterPictureInPicture = r.checkEnterPictureInPictureState(
|
||||
"makeInvisible", true /* noThrow */, true /* beforeStopping */);
|
||||
// We don't want to call setVisible(false) to avoid notifying the client of this
|
||||
// intermittent invisible state if it can enter Pip and isn't stopped or stopping.
|
||||
if (!canEnterPictureInPicture || r.state == STOPPING || r.state == STOPPED) {
|
||||
r.setVisible(false);
|
||||
}
|
||||
// Defer telling the client it is hidden if it can enter Pip and isn't current stopped
|
||||
// or stopping. This gives it a chance to enter Pip in onPause().
|
||||
final boolean deferHidingClient = canEnterPictureInPicture
|
||||
&& r.state != STOPPING && r.state != STOPPED;
|
||||
r.setVisible(false, deferHidingClient);
|
||||
|
||||
switch (r.state) {
|
||||
case STOPPING:
|
||||
@@ -2053,15 +2055,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
|
||||
if (visibleBehind == r) {
|
||||
releaseBackgroundResources(r);
|
||||
} else {
|
||||
// If this activity is in a state where it can currently enter
|
||||
// picture-in-picture, then don't immediately schedule the idle now in case
|
||||
// the activity tries to enterPictureInPictureMode() later. Otherwise,
|
||||
// we will try and stop the activity next time idle is processed.
|
||||
|
||||
if (canEnterPictureInPicture) {
|
||||
// We set r.visible=false so that Stop will later call setVisible for us
|
||||
r.visible = false;
|
||||
}
|
||||
addToStopping(r, true /* scheduleIdle */,
|
||||
canEnterPictureInPicture /* idleDelayed */);
|
||||
}
|
||||
@@ -2343,20 +2336,22 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
|
||||
|
||||
mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
|
||||
|
||||
final boolean prevCanPip = prev != null && prev.checkEnterPictureInPictureState(
|
||||
"resumeTopActivity", true /* noThrow */, userLeaving /* beforeStopping */);
|
||||
boolean lastResumedCanPip = false;
|
||||
final ActivityStack lastFocusedStack = mStackSupervisor.getLastStack();
|
||||
if (lastFocusedStack != null && lastFocusedStack != this) {
|
||||
// So, why aren't we using prev here??? See the param comment on the method. prev doesn't
|
||||
// represent the last resumed activity. However, the last focus stack does if it isn't null.
|
||||
final ActivityRecord lastResumed = lastFocusedStack.mResumedActivity;
|
||||
lastResumedCanPip = lastResumed != null && lastResumed.checkEnterPictureInPictureState(
|
||||
"resumeTopActivity", true /* noThrow */, userLeaving /* beforeStopping */);
|
||||
}
|
||||
// If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity
|
||||
// to be paused, while at the same time resuming the new resume activity only if the
|
||||
// previous activity can't go into Pip since we want to give Pip activities a chance to
|
||||
// enter Pip before resuming the next activity.
|
||||
final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;
|
||||
// TODO: This would be go to have however, the various call points that pass in
|
||||
// prev need to be corrected first. In some cases the prev is equal to the next e.g. launch
|
||||
// an app from home. And, is come other cases it is null e.g. press home button after
|
||||
// launching an app. The doc on the method says prev. is null expect for the case we are
|
||||
// coming from pause. We need to see if that is a valid thing and also if all the code in
|
||||
// this method using prev. are setup to function like that.
|
||||
//&& !prevCanPip;
|
||||
final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0
|
||||
&& !lastResumedCanPip;
|
||||
|
||||
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
|
||||
if (mResumedActivity != null) {
|
||||
if (DEBUG_STATES) Slog.d(TAG_STATES,
|
||||
|
||||
@@ -323,7 +323,7 @@ public class AppWindowContainerController
|
||||
}
|
||||
}
|
||||
|
||||
public void setVisibility(boolean visible) {
|
||||
public void setVisibility(boolean visible, boolean deferHidingClient) {
|
||||
synchronized(mWindowMap) {
|
||||
if (mContainer == null) {
|
||||
Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: "
|
||||
@@ -342,6 +342,7 @@ public class AppWindowContainerController
|
||||
mService.mClosingApps.remove(wtoken);
|
||||
wtoken.waitingToShow = false;
|
||||
wtoken.hiddenRequested = !visible;
|
||||
wtoken.mDeferHidingClient = deferHidingClient;
|
||||
|
||||
if (!visible) {
|
||||
// If the app is dead while it was visible, we kept its dead window on screen.
|
||||
@@ -368,15 +369,12 @@ public class AppWindowContainerController
|
||||
wtoken.waitingToShow = true;
|
||||
}
|
||||
|
||||
if (wtoken.clientHidden) {
|
||||
// In the case where we are making an app visible
|
||||
// but holding off for a transition, we still need
|
||||
// to tell the client to make its windows visible so
|
||||
// they get drawn. Otherwise, we will wait on
|
||||
// performing the transition until all windows have
|
||||
// been drawn, they never will be, and we are sad.
|
||||
wtoken.clientHidden = false;
|
||||
wtoken.sendAppVisibilityToClients();
|
||||
if (wtoken.isClientHidden()) {
|
||||
// In the case where we are making an app visible but holding off for a
|
||||
// transition, we still need to tell the client to make its windows visible
|
||||
// so they get drawn. Otherwise, we will wait on performing the transition
|
||||
// until all windows have been drawn, they never will be, and we are sad.
|
||||
wtoken.setClientHidden(false);
|
||||
}
|
||||
}
|
||||
wtoken.requestUpdateWallpaperIfNeeded();
|
||||
|
||||
@@ -129,7 +129,11 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
boolean hiddenRequested;
|
||||
|
||||
// Have we told the window clients to hide themselves?
|
||||
boolean clientHidden;
|
||||
private boolean mClientHidden;
|
||||
|
||||
// If true we will defer setting mClientHidden to true and reporting to the client that it is
|
||||
// hidden.
|
||||
boolean mDeferHidingClient;
|
||||
|
||||
// Last visibility state we reported to the app token.
|
||||
boolean reportedVisible;
|
||||
@@ -312,16 +316,25 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
}
|
||||
}
|
||||
|
||||
boolean isClientHidden() {
|
||||
return mClientHidden;
|
||||
}
|
||||
|
||||
void setClientHidden(boolean hideClient) {
|
||||
if (mClientHidden == hideClient || (hideClient && mDeferHidingClient)) {
|
||||
return;
|
||||
}
|
||||
mClientHidden = hideClient;
|
||||
sendAppVisibilityToClients();
|
||||
}
|
||||
|
||||
boolean setVisibility(WindowManager.LayoutParams lp,
|
||||
boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
|
||||
|
||||
boolean delayed = false;
|
||||
inPendingTransaction = false;
|
||||
|
||||
if (clientHidden == visible) {
|
||||
clientHidden = !visible;
|
||||
sendAppVisibilityToClients();
|
||||
}
|
||||
setClientHidden(!visible);
|
||||
|
||||
// Allow for state changes and animation to be applied if:
|
||||
// * token is transitioning visibility state
|
||||
@@ -1165,10 +1178,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
hidden = false;
|
||||
hiddenRequested = false;
|
||||
}
|
||||
if (clientHidden != fromToken.clientHidden) {
|
||||
clientHidden = fromToken.clientHidden;
|
||||
sendAppVisibilityToClients();
|
||||
}
|
||||
setClientHidden(fromToken.mClientHidden);
|
||||
fromToken.mAppAnimator.transferCurrentAnimation(
|
||||
mAppAnimator, tStartingWindow.mWinAnimator);
|
||||
|
||||
@@ -1533,10 +1543,9 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
|
||||
pw.print(prefix); pw.print("task="); pw.println(getTask());
|
||||
pw.print(prefix); pw.print(" mFillsParent="); pw.print(mFillsParent);
|
||||
pw.print(" mOrientation="); pw.println(mOrientation);
|
||||
pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
|
||||
pw.print(" clientHidden="); pw.print(clientHidden);
|
||||
pw.print(" reportedDrawn="); pw.print(reportedDrawn);
|
||||
pw.print(" reportedVisible="); pw.println(reportedVisible);
|
||||
pw.println(prefix + "hiddenRequested=" + hiddenRequested + " mClientHidden=" + mClientHidden
|
||||
+ ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
|
||||
+ " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
|
||||
if (paused) {
|
||||
pw.print(prefix); pw.print("paused="); pw.println(paused);
|
||||
}
|
||||
|
||||
@@ -2245,7 +2245,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
wsa.destroySurface();
|
||||
mService.mForceRemoves.add(w);
|
||||
mTmpWindow = w;
|
||||
} else if (w.mAppToken != null && w.mAppToken.clientHidden) {
|
||||
} else if (w.mAppToken != null && w.mAppToken.isClientHidden()) {
|
||||
Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
|
||||
+ w + " surface=" + wsa.mSurfaceController
|
||||
+ " token=" + w.mAppToken
|
||||
|
||||
@@ -439,7 +439,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
|
||||
for (int i = mChildren.size() - 1; i >= 0; i--) {
|
||||
final AppWindowToken token = mChildren.get(i);
|
||||
// skip hidden (or about to hide) apps
|
||||
if (token.mIsExiting || token.clientHidden || token.hiddenRequested) {
|
||||
if (token.mIsExiting || token.isClientHidden() || token.hiddenRequested) {
|
||||
continue;
|
||||
}
|
||||
final WindowState win = token.findMainWindow();
|
||||
@@ -607,7 +607,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
|
||||
for (int i = mChildren.size() - 1; i >= 0; i--) {
|
||||
final AppWindowToken token = mChildren.get(i);
|
||||
// skip hidden (or about to hide) apps
|
||||
if (!token.mIsExiting && !token.clientHidden && !token.hiddenRequested) {
|
||||
if (!token.mIsExiting && !token.isClientHidden() && !token.hiddenRequested) {
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1470,7 +1470,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
if (mInTouchMode) {
|
||||
res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE;
|
||||
}
|
||||
if (win.mAppToken == null || !win.mAppToken.clientHidden) {
|
||||
if (win.mAppToken == null || !win.mAppToken.isClientHidden()) {
|
||||
res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
|
||||
}
|
||||
|
||||
@@ -1950,7 +1950,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
if (viewVisibility == View.VISIBLE &&
|
||||
(win.mAppToken == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
|
||||
|| !win.mAppToken.clientHidden)) {
|
||||
|| !win.mAppToken.isClientHidden())) {
|
||||
result = win.relayoutVisibleWindow(mergedConfiguration, result, attrChanges,
|
||||
oldVisibility);
|
||||
try {
|
||||
|
||||
@@ -1399,7 +1399,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
* @return true if the window should be considered while evaluating allDrawn flags.
|
||||
*/
|
||||
boolean mightAffectAllDrawn(boolean visibleOnly) {
|
||||
final boolean isViewVisible = (mAppToken == null || !mAppToken.clientHidden)
|
||||
final boolean isViewVisible = (mAppToken == null || !mAppToken.isClientHidden())
|
||||
&& (mViewVisibility == View.VISIBLE) && !mWindowRemovalAllowed;
|
||||
return (isOnScreen() && (!visibleOnly || isViewVisible)
|
||||
|| mWinAnimator.mAttrType == TYPE_BASE_APPLICATION
|
||||
@@ -2312,7 +2312,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
* interacts with it.
|
||||
*/
|
||||
boolean shouldKeepVisibleDeadAppWindow() {
|
||||
if (!isWinVisibleLw() || mAppToken == null || mAppToken.clientHidden) {
|
||||
if (!isWinVisibleLw() || mAppToken == null || mAppToken.isClientHidden()) {
|
||||
// Not a visible app window or the app isn't dead.
|
||||
return false;
|
||||
}
|
||||
@@ -2570,12 +2570,24 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
void sendAppVisibilityToClients() {
|
||||
super.sendAppVisibilityToClients();
|
||||
|
||||
final boolean clientHidden = mAppToken.clientHidden;
|
||||
final boolean clientHidden = mAppToken.isClientHidden();
|
||||
if (mAttrs.type == TYPE_APPLICATION_STARTING && clientHidden) {
|
||||
// Don't hide the starting window.
|
||||
return;
|
||||
}
|
||||
|
||||
if (clientHidden) {
|
||||
// Once we are notifying the client that it's visibility has changed, we need to prevent
|
||||
// it from destroying child surfaces until the animation has finished. We do this by
|
||||
// detaching any surface control the client added from the client.
|
||||
for (int i = mChildren.size() - 1; i >= 0; --i) {
|
||||
final WindowState c = mChildren.get(i);
|
||||
c.mWinAnimator.detachChildren();
|
||||
}
|
||||
|
||||
mWinAnimator.detachChildren();
|
||||
}
|
||||
|
||||
try {
|
||||
if (DEBUG_VISIBILITY) Slog.v(TAG,
|
||||
"Setting visibility of " + this + ": " + (!clientHidden));
|
||||
|
||||
Reference in New Issue
Block a user