Loading services/core/java/com/android/server/am/ActivityRecord.java +7 −3 Original line number Diff line number Diff line Loading @@ -1568,17 +1568,21 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } void setVisibility(boolean visible) { mWindowContainerController.setVisibility(visible); mWindowContainerController.setVisibility(visible, false /* deferHidingClient */); } // TODO: Look into merging with #setVisibility() void setVisible(boolean newVisible) { setVisible(newVisible, false /* deferHidingClient */); } // TODO: Look into merging with #setVisibility() 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); Loading services/core/java/com/android/server/am/ActivityStack.java +20 −25 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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: Loading @@ -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 */); } Loading Loading @@ -2343,20 +2336,22 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid); final boolean prevCanPip = prev != null && prev.checkEnterPictureInPictureState( 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, Loading services/core/java/com/android/server/wm/AppWindowContainerController.java +8 −10 Original line number Diff line number Diff line Loading @@ -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: " Loading @@ -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. Loading @@ -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(); Loading services/core/java/com/android/server/wm/AppWindowToken.java +22 −13 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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); Loading Loading @@ -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); } Loading services/core/java/com/android/server/wm/DisplayContent.java +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading
services/core/java/com/android/server/am/ActivityRecord.java +7 −3 Original line number Diff line number Diff line Loading @@ -1568,17 +1568,21 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } void setVisibility(boolean visible) { mWindowContainerController.setVisibility(visible); mWindowContainerController.setVisibility(visible, false /* deferHidingClient */); } // TODO: Look into merging with #setVisibility() void setVisible(boolean newVisible) { setVisible(newVisible, false /* deferHidingClient */); } // TODO: Look into merging with #setVisibility() 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); Loading
services/core/java/com/android/server/am/ActivityStack.java +20 −25 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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: Loading @@ -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 */); } Loading Loading @@ -2343,20 +2336,22 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid); final boolean prevCanPip = prev != null && prev.checkEnterPictureInPictureState( 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, Loading
services/core/java/com/android/server/wm/AppWindowContainerController.java +8 −10 Original line number Diff line number Diff line Loading @@ -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: " Loading @@ -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. Loading @@ -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(); Loading
services/core/java/com/android/server/wm/AppWindowToken.java +22 −13 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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); Loading Loading @@ -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); } Loading
services/core/java/com/android/server/wm/DisplayContent.java +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading