Loading services/core/java/com/android/server/am/ActivityStack.java +36 −23 Original line number Diff line number Diff line Loading @@ -1456,6 +1456,12 @@ final class ActivityStack { } if (r.app == null || r.app.thread == null) { // We need to make sure the app is running if it's the top, or it is // just made visible from invisible. // If the app is already visible, it must have died while it was visible. // In this case, we'll show the dead window but will not restart the app. // Otherwise we could end up thrashing. if (r == top || !r.visible) { // This activity needs to be visible, but isn't even running... // get it started and resume if no other stack in this stack is resumed. if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, Loading @@ -1478,7 +1484,7 @@ final class ActivityStack { noStackActivityResumed = false; } } } } else if (r.visible) { // If this activity is already visible, then there is nothing // else to do here. Loading Loading @@ -3731,10 +3737,13 @@ final class ActivityStack { // Don't currently have state for the activity, or // it is finishing -- always remove it. remove = true; } else if (r.launchCount > 2 && } else if (!r.visible && r.launchCount > 2 && r.lastLaunchTime > (SystemClock.uptimeMillis() - 60000)) { // We have launched this activity too many times since it was // able to run, so give up and remove it. // (Note if the activity is visible, we don't remove the record. // We leave the dead window on the screen but the process will // not be restarted unless user explicitly tap on it.) remove = true; } else { // The process may be gone, but the activity lives on! Loading Loading @@ -3764,7 +3773,11 @@ final class ActivityStack { if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during removeHistory for activity " + r); r.app = null; r.nowVisible = false; // Set nowVisible to previous visible state. If the app was visible while // it died, we leave the dead window on screen so it's basically visible. // This is needed when user later tap on the dead window, we need to stop // other apps when user transfers focus to the restarted activity. r.nowVisible = r.visible; if (!r.haveState) { if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, "App died, clearing saved state of " + r); Loading services/core/java/com/android/server/am/ActivityStackSupervisor.java +9 −9 Original line number Diff line number Diff line Loading @@ -2886,24 +2886,24 @@ public final class ActivityStackSupervisor implements DisplayListener { return; } int stackId = task.stack.mStackId; if (task.mResizeable && options != null) { ActivityOptions opts = new ActivityOptions(options); if (opts.hasBounds()) { Rect bounds = opts.getBounds(); task.updateOverrideConfiguration(bounds); mWindowManager.resizeTask(task.taskId, bounds, task.mOverrideConfig, false /*relayout*/, false /*forced*/); stackId = task.getLaunchStackId(); } } final int stackId = task.getLaunchStackId(); if (stackId != task.stack.mStackId) { moveTaskToStackUncheckedLocked(task, stackId, ON_TOP, !FORCE_FOCUS, reason); // moveTaskToStackUncheckedLocked() should already placed the task on top, // still need moveTaskToFrontLocked() below for any transition settings. } // WM resizeTask must be done after the task is moved to the correct stack, // because Task's setBounds() also updates dim layer's bounds, but that has // dependency on the stack. mWindowManager.resizeTask(task.taskId, bounds, task.mOverrideConfig, false /*relayout*/, false /*forced*/); } } final ActivityRecord r = task.getTopActivity(); task.stack.moveTaskToFrontLocked(task, false /* noAnimation */, options, Loading services/core/java/com/android/server/wm/AppWindowToken.java +21 −0 Original line number Diff line number Diff line Loading @@ -102,6 +102,7 @@ class AppWindowToken extends WindowToken { // Set to true when the token has been removed from the window mgr. boolean removed; boolean appDied; // Information about an application starting window if displayed. StartingData startingData; WindowState startingWindow; Loading Loading @@ -365,6 +366,26 @@ class AppWindowToken extends WindowToken { windows.clear(); } void removeAllDeadWindows() { for (int winNdx = allAppWindows.size() - 1; winNdx >= 0; // removeWindowLocked at bottom of loop may remove multiple entries from // allAppWindows if the window to be removed has child windows. It also may // not remove any windows from allAppWindows at all if win is exiting and // currently animating away. This ensures that winNdx is monotonically decreasing // and never beyond allAppWindows bounds. winNdx = Math.min(winNdx - 1, allAppWindows.size() - 1)) { WindowState win = allAppWindows.get(winNdx); if (win.mAppDied) { if (WindowManagerService.DEBUG_WINDOW_MOVEMENT) { Slog.w(WindowManagerService.TAG, "removeAllDeadWindows: " + win); } // Set mDestroying, we don't want any animation or delayed removal here. win.mDestroying = true; service.removeWindowLocked(win); } } } @Override void dump(PrintWriter pw, String prefix) { super.dump(pw, prefix); Loading services/core/java/com/android/server/wm/DimBehindController.java→services/core/java/com/android/server/wm/DimLayerController.java +59 −31 Original line number Diff line number Diff line package com.android.server.wm; import static com.android.server.wm.WindowManagerService.DEBUG_DIM_LAYER; import static com.android.server.wm.WindowManagerService.LAYER_OFFSET_DIM; import android.graphics.Rect; import android.util.ArrayMap; Loading @@ -11,32 +12,38 @@ import java.io.PrintWriter; /** * Centralizes the control of dim layers used for * {@link android.view.WindowManager.LayoutParams#FLAG_DIM_BEHIND}. * {@link android.view.WindowManager.LayoutParams#FLAG_DIM_BEHIND} * as well as other use cases (such as dimming above a dead window). */ class DimBehindController { private static final String TAG = "DimBehindController"; class DimLayerController { private static final String TAG = "DimLayerController"; /** Amount of time in milliseconds to animate the dim surface from one value to another, * when no window animation is driving it. */ private static final int DEFAULT_DIM_DURATION = 200; // Shared dim layer for fullscreen users. {@link DimBehindState#dimLayer} will point to this /** * The default amount of dim applied over a dead window */ private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f; // Shared dim layer for fullscreen users. {@link DimLayerState#dimLayer} will point to this // instead of creating a new object per fullscreen task on a display. private DimLayer mSharedFullScreenDimLayer; private ArrayMap<DimLayer.DimLayerUser, DimBehindState> mState = new ArrayMap<>(); private ArrayMap<DimLayer.DimLayerUser, DimLayerState> mState = new ArrayMap<>(); private DisplayContent mDisplayContent; private Rect mTmpBounds = new Rect(); DimBehindController(DisplayContent displayContent) { DimLayerController(DisplayContent displayContent) { mDisplayContent = displayContent; } /** Updates the dim layer bounds, recreating it if needed. */ void updateDimLayer(DimLayer.DimLayerUser dimLayerUser) { DimBehindState state = getOrCreateDimBehindState(dimLayerUser); DimLayerState state = getOrCreateDimLayerState(dimLayerUser, false); final boolean previousFullscreen = state.dimLayer != null && state.dimLayer == mSharedFullScreenDimLayer; DimLayer newDimLayer; Loading Loading @@ -72,19 +79,21 @@ class DimBehindController { state.dimLayer = newDimLayer; } private DimBehindState getOrCreateDimBehindState(DimLayer.DimLayerUser dimLayerUser) { if (DEBUG_DIM_LAYER) Slog.v(TAG, "getDimBehindState, dimLayerUser=" private DimLayerState getOrCreateDimLayerState( DimLayer.DimLayerUser dimLayerUser, boolean aboveApp) { if (DEBUG_DIM_LAYER) Slog.v(TAG, "getOrCreateDimLayerState, dimLayerUser=" + dimLayerUser.toShortString()); DimBehindState state = mState.get(dimLayerUser); DimLayerState state = mState.get(dimLayerUser); if (state == null) { state = new DimBehindState(); state = new DimLayerState(); mState.put(dimLayerUser, state); } state.dimAbove = aboveApp; return state; } private void setContinueDimming(DimLayer.DimLayerUser dimLayerUser) { DimBehindState state = mState.get(dimLayerUser); DimLayerState state = mState.get(dimLayerUser); if (state == null) { if (DEBUG_DIM_LAYER) Slog.w(TAG, "setContinueDimming, no state for: " + dimLayerUser.toShortString()); Loading @@ -95,7 +104,7 @@ class DimBehindController { boolean isDimming() { for (int i = mState.size() - 1; i >= 0; i--) { DimBehindState state = mState.valueAt(i); DimLayerState state = mState.valueAt(i); if (state.dimLayer != null && state.dimLayer.isDimming()) { return true; } Loading @@ -110,15 +119,15 @@ class DimBehindController { } private boolean getContinueDimming(DimLayer.DimLayerUser dimLayerUser) { DimBehindState state = mState.get(dimLayerUser); DimLayerState state = mState.get(dimLayerUser); return state != null && state.continueDimming; } void startDimmingIfNeeded(DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator newWinAnimator) { WindowStateAnimator newWinAnimator, boolean aboveApp) { // Only set dim params on the highest dimmed layer. // Don't turn on for an unshown surface, or for any layer but the highest dimmed layer. DimBehindState state = getOrCreateDimBehindState(dimLayerUser); DimLayerState state = getOrCreateDimLayerState(dimLayerUser, aboveApp); if (DEBUG_DIM_LAYER) Slog.v(TAG, "startDimmingIfNeeded," + " dimLayerUser=" + dimLayerUser.toShortString() + " newWinAnimator=" + newWinAnimator Loading @@ -145,7 +154,7 @@ class DimBehindController { private void stopDimmingIfNeeded(DimLayer.DimLayerUser dimLayerUser) { // No need to check if state is null, we know the key has a value. DimBehindState state = mState.get(dimLayerUser); DimLayerState state = mState.get(dimLayerUser); if (DEBUG_DIM_LAYER) Slog.v(TAG, "stopDimmingIfNeeded," + " dimLayerUser=" + dimLayerUser.toShortString() + " state.continueDimming=" + state.continueDimming Loading Loading @@ -188,7 +197,7 @@ class DimBehindController { } private boolean animateDimLayers(DimLayer.DimLayerUser dimLayerUser) { DimBehindState state = mState.get(dimLayerUser); DimLayerState state = mState.get(dimLayerUser); if (DEBUG_DIM_LAYER) Slog.v(TAG, "animateDimLayers," + " dimLayerUser=" + dimLayerUser.toShortString() + " state.animator=" + state.animator Loading @@ -199,9 +208,14 @@ class DimBehindController { dimLayer = state.dimLayer.getLayer(); dimAmount = 0; } else { dimLayer = state.animator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM; if (state.dimAbove) { dimLayer = state.animator.mAnimLayer + LAYER_OFFSET_DIM; dimAmount = DEFAULT_DIM_AMOUNT_DEAD_WINDOW; } else { dimLayer = state.animator.mAnimLayer - LAYER_OFFSET_DIM; dimAmount = state.animator.mWin.mAttrs.dimAmount; } } final float targetAlpha = state.dimLayer.getTargetAlpha(); if (targetAlpha != dimAmount) { if (state.animator == null) { Loading @@ -211,7 +225,7 @@ class DimBehindController { ? state.animator.mAnimation.computeDurationHint() : DEFAULT_DIM_DURATION; if (targetAlpha > dimAmount) { duration = getDimBehindFadeDuration(duration); duration = getDimLayerFadeDuration(duration); } state.dimLayer.show(dimLayer, dimAmount, duration); } Loading @@ -230,11 +244,11 @@ class DimBehindController { } boolean isDimming(DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator winAnimator) { DimBehindState state = mState.get(dimLayerUser); DimLayerState state = mState.get(dimLayerUser); return state != null && state.animator == winAnimator && state.dimLayer.isDimming(); } private long getDimBehindFadeDuration(long duration) { private long getDimLayerFadeDuration(long duration) { TypedValue tv = new TypedValue(); mDisplayContent.mService.mContext.getResources().getValue( com.android.internal.R.fraction.config_dimBehindFadeDuration, tv, true); Loading @@ -248,7 +262,7 @@ class DimBehindController { void close() { for (int i = mState.size() - 1; i >= 0; i--) { DimBehindState state = mState.valueAt(i); DimLayerState state = mState.valueAt(i); state.dimLayer.destroySurface(); } mState.clear(); Loading @@ -256,10 +270,23 @@ class DimBehindController { } void removeDimLayerUser(DimLayer.DimLayerUser dimLayerUser) { DimLayerState state = mState.get(dimLayerUser); if (state != null) { state.dimLayer.destroySurface(); mState.remove(dimLayerUser); } } void applyDimBehind(DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator animator) { applyDim(dimLayerUser, animator, false /* aboveApp */); } void applyDimAbove(DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator animator) { applyDim(dimLayerUser, animator, true /* aboveApp */); } private void applyDim( DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator animator, boolean aboveApp) { if (dimLayerUser == null) { Slog.e(TAG, "Trying to apply dim layer for: " + this + ", but no dim layer user found."); Loading @@ -269,26 +296,27 @@ class DimBehindController { setContinueDimming(dimLayerUser); if (!isDimming(dimLayerUser, animator)) { if (DEBUG_DIM_LAYER) Slog.v(TAG, "Win " + this + " start dimming."); startDimmingIfNeeded(dimLayerUser, animator); startDimmingIfNeeded(dimLayerUser, animator, aboveApp); } } } private static class DimBehindState { // The particular window with FLAG_DIM_BEHIND set. If null, hide dimLayer. private static class DimLayerState { // The particular window requesting a dim layer. If null, hide dimLayer. WindowStateAnimator animator; // Set to false at the start of performLayoutAndPlaceSurfaces. If it is still false by the // end then stop any dimming. boolean continueDimming; DimLayer dimLayer; boolean dimAbove; } void dump(String prefix, PrintWriter pw) { pw.println(prefix + "DimBehindController"); pw.println(prefix + "DimLayerController"); for (int i = 0, n = mState.size(); i < n; i++) { pw.println(prefix + " " + mState.keyAt(i).toShortString()); pw.print(prefix + " "); DimBehindState state = mState.valueAt(i); DimLayerState state = mState.valueAt(i); pw.print("dimLayer=" + (state.dimLayer == mSharedFullScreenDimLayer ? "shared" : state.dimLayer)); pw.print(", animator=" + state.animator); Loading services/core/java/com/android/server/wm/DisplayContent.java +9 −9 Original line number Diff line number Diff line Loading @@ -116,7 +116,7 @@ class DisplayContent { final DockedStackDividerController mDividerControllerLocked; final DimBehindController mDimBehindController; final DimLayerController mDimLayerController; /** * @param display May not be null. Loading @@ -131,7 +131,7 @@ class DisplayContent { mService = service; initializeDisplayBaseInfo(); mDividerControllerLocked = new DockedStackDividerController(service.mContext, this); mDimBehindController = new DimBehindController(this); mDimLayerController = new DimLayerController(this); } int getDisplayId() { Loading Loading @@ -271,7 +271,7 @@ class DisplayContent { } void detachStack(TaskStack stack) { mDimBehindController.removeDimLayerUser(stack); mDimLayerController.removeDimLayerUser(stack); mStacks.remove(stack); } Loading Loading @@ -415,23 +415,23 @@ class DisplayContent { } boolean animateDimLayers() { return mDimBehindController.animateDimLayers(); return mDimLayerController.animateDimLayers(); } void resetDimming() { mDimBehindController.resetDimming(); mDimLayerController.resetDimming(); } boolean isDimming() { return mDimBehindController.isDimming(); return mDimLayerController.isDimming(); } void stopDimmingIfNeeded() { mDimBehindController.stopDimmingIfNeeded(); mDimLayerController.stopDimmingIfNeeded(); } void close() { mDimBehindController.close(); mDimLayerController.close(); for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { mStacks.get(stackNdx).close(); } Loading Loading @@ -578,7 +578,7 @@ class DisplayContent { } } pw.println(); mDimBehindController.dump(prefix + " ", pw); mDimLayerController.dump(prefix + " ", pw); } @Override Loading Loading
services/core/java/com/android/server/am/ActivityStack.java +36 −23 Original line number Diff line number Diff line Loading @@ -1456,6 +1456,12 @@ final class ActivityStack { } if (r.app == null || r.app.thread == null) { // We need to make sure the app is running if it's the top, or it is // just made visible from invisible. // If the app is already visible, it must have died while it was visible. // In this case, we'll show the dead window but will not restart the app. // Otherwise we could end up thrashing. if (r == top || !r.visible) { // This activity needs to be visible, but isn't even running... // get it started and resume if no other stack in this stack is resumed. if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, Loading @@ -1478,7 +1484,7 @@ final class ActivityStack { noStackActivityResumed = false; } } } } else if (r.visible) { // If this activity is already visible, then there is nothing // else to do here. Loading Loading @@ -3731,10 +3737,13 @@ final class ActivityStack { // Don't currently have state for the activity, or // it is finishing -- always remove it. remove = true; } else if (r.launchCount > 2 && } else if (!r.visible && r.launchCount > 2 && r.lastLaunchTime > (SystemClock.uptimeMillis() - 60000)) { // We have launched this activity too many times since it was // able to run, so give up and remove it. // (Note if the activity is visible, we don't remove the record. // We leave the dead window on the screen but the process will // not be restarted unless user explicitly tap on it.) remove = true; } else { // The process may be gone, but the activity lives on! Loading Loading @@ -3764,7 +3773,11 @@ final class ActivityStack { if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during removeHistory for activity " + r); r.app = null; r.nowVisible = false; // Set nowVisible to previous visible state. If the app was visible while // it died, we leave the dead window on screen so it's basically visible. // This is needed when user later tap on the dead window, we need to stop // other apps when user transfers focus to the restarted activity. r.nowVisible = r.visible; if (!r.haveState) { if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, "App died, clearing saved state of " + r); Loading
services/core/java/com/android/server/am/ActivityStackSupervisor.java +9 −9 Original line number Diff line number Diff line Loading @@ -2886,24 +2886,24 @@ public final class ActivityStackSupervisor implements DisplayListener { return; } int stackId = task.stack.mStackId; if (task.mResizeable && options != null) { ActivityOptions opts = new ActivityOptions(options); if (opts.hasBounds()) { Rect bounds = opts.getBounds(); task.updateOverrideConfiguration(bounds); mWindowManager.resizeTask(task.taskId, bounds, task.mOverrideConfig, false /*relayout*/, false /*forced*/); stackId = task.getLaunchStackId(); } } final int stackId = task.getLaunchStackId(); if (stackId != task.stack.mStackId) { moveTaskToStackUncheckedLocked(task, stackId, ON_TOP, !FORCE_FOCUS, reason); // moveTaskToStackUncheckedLocked() should already placed the task on top, // still need moveTaskToFrontLocked() below for any transition settings. } // WM resizeTask must be done after the task is moved to the correct stack, // because Task's setBounds() also updates dim layer's bounds, but that has // dependency on the stack. mWindowManager.resizeTask(task.taskId, bounds, task.mOverrideConfig, false /*relayout*/, false /*forced*/); } } final ActivityRecord r = task.getTopActivity(); task.stack.moveTaskToFrontLocked(task, false /* noAnimation */, options, Loading
services/core/java/com/android/server/wm/AppWindowToken.java +21 −0 Original line number Diff line number Diff line Loading @@ -102,6 +102,7 @@ class AppWindowToken extends WindowToken { // Set to true when the token has been removed from the window mgr. boolean removed; boolean appDied; // Information about an application starting window if displayed. StartingData startingData; WindowState startingWindow; Loading Loading @@ -365,6 +366,26 @@ class AppWindowToken extends WindowToken { windows.clear(); } void removeAllDeadWindows() { for (int winNdx = allAppWindows.size() - 1; winNdx >= 0; // removeWindowLocked at bottom of loop may remove multiple entries from // allAppWindows if the window to be removed has child windows. It also may // not remove any windows from allAppWindows at all if win is exiting and // currently animating away. This ensures that winNdx is monotonically decreasing // and never beyond allAppWindows bounds. winNdx = Math.min(winNdx - 1, allAppWindows.size() - 1)) { WindowState win = allAppWindows.get(winNdx); if (win.mAppDied) { if (WindowManagerService.DEBUG_WINDOW_MOVEMENT) { Slog.w(WindowManagerService.TAG, "removeAllDeadWindows: " + win); } // Set mDestroying, we don't want any animation or delayed removal here. win.mDestroying = true; service.removeWindowLocked(win); } } } @Override void dump(PrintWriter pw, String prefix) { super.dump(pw, prefix); Loading
services/core/java/com/android/server/wm/DimBehindController.java→services/core/java/com/android/server/wm/DimLayerController.java +59 −31 Original line number Diff line number Diff line package com.android.server.wm; import static com.android.server.wm.WindowManagerService.DEBUG_DIM_LAYER; import static com.android.server.wm.WindowManagerService.LAYER_OFFSET_DIM; import android.graphics.Rect; import android.util.ArrayMap; Loading @@ -11,32 +12,38 @@ import java.io.PrintWriter; /** * Centralizes the control of dim layers used for * {@link android.view.WindowManager.LayoutParams#FLAG_DIM_BEHIND}. * {@link android.view.WindowManager.LayoutParams#FLAG_DIM_BEHIND} * as well as other use cases (such as dimming above a dead window). */ class DimBehindController { private static final String TAG = "DimBehindController"; class DimLayerController { private static final String TAG = "DimLayerController"; /** Amount of time in milliseconds to animate the dim surface from one value to another, * when no window animation is driving it. */ private static final int DEFAULT_DIM_DURATION = 200; // Shared dim layer for fullscreen users. {@link DimBehindState#dimLayer} will point to this /** * The default amount of dim applied over a dead window */ private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f; // Shared dim layer for fullscreen users. {@link DimLayerState#dimLayer} will point to this // instead of creating a new object per fullscreen task on a display. private DimLayer mSharedFullScreenDimLayer; private ArrayMap<DimLayer.DimLayerUser, DimBehindState> mState = new ArrayMap<>(); private ArrayMap<DimLayer.DimLayerUser, DimLayerState> mState = new ArrayMap<>(); private DisplayContent mDisplayContent; private Rect mTmpBounds = new Rect(); DimBehindController(DisplayContent displayContent) { DimLayerController(DisplayContent displayContent) { mDisplayContent = displayContent; } /** Updates the dim layer bounds, recreating it if needed. */ void updateDimLayer(DimLayer.DimLayerUser dimLayerUser) { DimBehindState state = getOrCreateDimBehindState(dimLayerUser); DimLayerState state = getOrCreateDimLayerState(dimLayerUser, false); final boolean previousFullscreen = state.dimLayer != null && state.dimLayer == mSharedFullScreenDimLayer; DimLayer newDimLayer; Loading Loading @@ -72,19 +79,21 @@ class DimBehindController { state.dimLayer = newDimLayer; } private DimBehindState getOrCreateDimBehindState(DimLayer.DimLayerUser dimLayerUser) { if (DEBUG_DIM_LAYER) Slog.v(TAG, "getDimBehindState, dimLayerUser=" private DimLayerState getOrCreateDimLayerState( DimLayer.DimLayerUser dimLayerUser, boolean aboveApp) { if (DEBUG_DIM_LAYER) Slog.v(TAG, "getOrCreateDimLayerState, dimLayerUser=" + dimLayerUser.toShortString()); DimBehindState state = mState.get(dimLayerUser); DimLayerState state = mState.get(dimLayerUser); if (state == null) { state = new DimBehindState(); state = new DimLayerState(); mState.put(dimLayerUser, state); } state.dimAbove = aboveApp; return state; } private void setContinueDimming(DimLayer.DimLayerUser dimLayerUser) { DimBehindState state = mState.get(dimLayerUser); DimLayerState state = mState.get(dimLayerUser); if (state == null) { if (DEBUG_DIM_LAYER) Slog.w(TAG, "setContinueDimming, no state for: " + dimLayerUser.toShortString()); Loading @@ -95,7 +104,7 @@ class DimBehindController { boolean isDimming() { for (int i = mState.size() - 1; i >= 0; i--) { DimBehindState state = mState.valueAt(i); DimLayerState state = mState.valueAt(i); if (state.dimLayer != null && state.dimLayer.isDimming()) { return true; } Loading @@ -110,15 +119,15 @@ class DimBehindController { } private boolean getContinueDimming(DimLayer.DimLayerUser dimLayerUser) { DimBehindState state = mState.get(dimLayerUser); DimLayerState state = mState.get(dimLayerUser); return state != null && state.continueDimming; } void startDimmingIfNeeded(DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator newWinAnimator) { WindowStateAnimator newWinAnimator, boolean aboveApp) { // Only set dim params on the highest dimmed layer. // Don't turn on for an unshown surface, or for any layer but the highest dimmed layer. DimBehindState state = getOrCreateDimBehindState(dimLayerUser); DimLayerState state = getOrCreateDimLayerState(dimLayerUser, aboveApp); if (DEBUG_DIM_LAYER) Slog.v(TAG, "startDimmingIfNeeded," + " dimLayerUser=" + dimLayerUser.toShortString() + " newWinAnimator=" + newWinAnimator Loading @@ -145,7 +154,7 @@ class DimBehindController { private void stopDimmingIfNeeded(DimLayer.DimLayerUser dimLayerUser) { // No need to check if state is null, we know the key has a value. DimBehindState state = mState.get(dimLayerUser); DimLayerState state = mState.get(dimLayerUser); if (DEBUG_DIM_LAYER) Slog.v(TAG, "stopDimmingIfNeeded," + " dimLayerUser=" + dimLayerUser.toShortString() + " state.continueDimming=" + state.continueDimming Loading Loading @@ -188,7 +197,7 @@ class DimBehindController { } private boolean animateDimLayers(DimLayer.DimLayerUser dimLayerUser) { DimBehindState state = mState.get(dimLayerUser); DimLayerState state = mState.get(dimLayerUser); if (DEBUG_DIM_LAYER) Slog.v(TAG, "animateDimLayers," + " dimLayerUser=" + dimLayerUser.toShortString() + " state.animator=" + state.animator Loading @@ -199,9 +208,14 @@ class DimBehindController { dimLayer = state.dimLayer.getLayer(); dimAmount = 0; } else { dimLayer = state.animator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM; if (state.dimAbove) { dimLayer = state.animator.mAnimLayer + LAYER_OFFSET_DIM; dimAmount = DEFAULT_DIM_AMOUNT_DEAD_WINDOW; } else { dimLayer = state.animator.mAnimLayer - LAYER_OFFSET_DIM; dimAmount = state.animator.mWin.mAttrs.dimAmount; } } final float targetAlpha = state.dimLayer.getTargetAlpha(); if (targetAlpha != dimAmount) { if (state.animator == null) { Loading @@ -211,7 +225,7 @@ class DimBehindController { ? state.animator.mAnimation.computeDurationHint() : DEFAULT_DIM_DURATION; if (targetAlpha > dimAmount) { duration = getDimBehindFadeDuration(duration); duration = getDimLayerFadeDuration(duration); } state.dimLayer.show(dimLayer, dimAmount, duration); } Loading @@ -230,11 +244,11 @@ class DimBehindController { } boolean isDimming(DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator winAnimator) { DimBehindState state = mState.get(dimLayerUser); DimLayerState state = mState.get(dimLayerUser); return state != null && state.animator == winAnimator && state.dimLayer.isDimming(); } private long getDimBehindFadeDuration(long duration) { private long getDimLayerFadeDuration(long duration) { TypedValue tv = new TypedValue(); mDisplayContent.mService.mContext.getResources().getValue( com.android.internal.R.fraction.config_dimBehindFadeDuration, tv, true); Loading @@ -248,7 +262,7 @@ class DimBehindController { void close() { for (int i = mState.size() - 1; i >= 0; i--) { DimBehindState state = mState.valueAt(i); DimLayerState state = mState.valueAt(i); state.dimLayer.destroySurface(); } mState.clear(); Loading @@ -256,10 +270,23 @@ class DimBehindController { } void removeDimLayerUser(DimLayer.DimLayerUser dimLayerUser) { DimLayerState state = mState.get(dimLayerUser); if (state != null) { state.dimLayer.destroySurface(); mState.remove(dimLayerUser); } } void applyDimBehind(DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator animator) { applyDim(dimLayerUser, animator, false /* aboveApp */); } void applyDimAbove(DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator animator) { applyDim(dimLayerUser, animator, true /* aboveApp */); } private void applyDim( DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator animator, boolean aboveApp) { if (dimLayerUser == null) { Slog.e(TAG, "Trying to apply dim layer for: " + this + ", but no dim layer user found."); Loading @@ -269,26 +296,27 @@ class DimBehindController { setContinueDimming(dimLayerUser); if (!isDimming(dimLayerUser, animator)) { if (DEBUG_DIM_LAYER) Slog.v(TAG, "Win " + this + " start dimming."); startDimmingIfNeeded(dimLayerUser, animator); startDimmingIfNeeded(dimLayerUser, animator, aboveApp); } } } private static class DimBehindState { // The particular window with FLAG_DIM_BEHIND set. If null, hide dimLayer. private static class DimLayerState { // The particular window requesting a dim layer. If null, hide dimLayer. WindowStateAnimator animator; // Set to false at the start of performLayoutAndPlaceSurfaces. If it is still false by the // end then stop any dimming. boolean continueDimming; DimLayer dimLayer; boolean dimAbove; } void dump(String prefix, PrintWriter pw) { pw.println(prefix + "DimBehindController"); pw.println(prefix + "DimLayerController"); for (int i = 0, n = mState.size(); i < n; i++) { pw.println(prefix + " " + mState.keyAt(i).toShortString()); pw.print(prefix + " "); DimBehindState state = mState.valueAt(i); DimLayerState state = mState.valueAt(i); pw.print("dimLayer=" + (state.dimLayer == mSharedFullScreenDimLayer ? "shared" : state.dimLayer)); pw.print(", animator=" + state.animator); Loading
services/core/java/com/android/server/wm/DisplayContent.java +9 −9 Original line number Diff line number Diff line Loading @@ -116,7 +116,7 @@ class DisplayContent { final DockedStackDividerController mDividerControllerLocked; final DimBehindController mDimBehindController; final DimLayerController mDimLayerController; /** * @param display May not be null. Loading @@ -131,7 +131,7 @@ class DisplayContent { mService = service; initializeDisplayBaseInfo(); mDividerControllerLocked = new DockedStackDividerController(service.mContext, this); mDimBehindController = new DimBehindController(this); mDimLayerController = new DimLayerController(this); } int getDisplayId() { Loading Loading @@ -271,7 +271,7 @@ class DisplayContent { } void detachStack(TaskStack stack) { mDimBehindController.removeDimLayerUser(stack); mDimLayerController.removeDimLayerUser(stack); mStacks.remove(stack); } Loading Loading @@ -415,23 +415,23 @@ class DisplayContent { } boolean animateDimLayers() { return mDimBehindController.animateDimLayers(); return mDimLayerController.animateDimLayers(); } void resetDimming() { mDimBehindController.resetDimming(); mDimLayerController.resetDimming(); } boolean isDimming() { return mDimBehindController.isDimming(); return mDimLayerController.isDimming(); } void stopDimmingIfNeeded() { mDimBehindController.stopDimmingIfNeeded(); mDimLayerController.stopDimmingIfNeeded(); } void close() { mDimBehindController.close(); mDimLayerController.close(); for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { mStacks.get(stackNdx).close(); } Loading Loading @@ -578,7 +578,7 @@ class DisplayContent { } } pw.println(); mDimBehindController.dump(prefix + " ", pw); mDimLayerController.dump(prefix + " ", pw); } @Override Loading