Loading services/core/java/com/android/server/wm/SurfaceControlWithBackground.java +56 −47 Original line number Original line Diff line number Diff line Loading @@ -29,12 +29,16 @@ import android.view.SurfaceSession; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManagerPolicy.NAV_BAR_BOTTOM; import static android.view.WindowManagerPolicy.NAV_BAR_LEFT; import static android.view.WindowManagerPolicy.NAV_BAR_RIGHT; /** /** * SurfaceControl extension that has background sized to match its container. * SurfaceControl extension that has black background behind navigation bar area for fullscreen * letterboxed apps. */ */ class SurfaceControlWithBackground extends SurfaceControl { class SurfaceControlWithBackground extends SurfaceControl { // SurfaceControl that holds the background behind opaque letterboxed app windows. // SurfaceControl that holds the background. private SurfaceControl mBackgroundControl; private SurfaceControl mBackgroundControl; // Flag that defines whether the background should be shown. // Flag that defines whether the background should be shown. Loading @@ -51,8 +55,10 @@ class SurfaceControlWithBackground extends SurfaceControl { private float mLastDsDx = 1, mLastDsDy = 1; private float mLastDsDx = 1, mLastDsDy = 1; private float mLastX, mLastY; private float mLastX, mLastY; // Will skip alpha animation for background of starting window. // SurfaceFlinger doesn't support crop rectangles where width or height is non-positive. private boolean mIsStartingWindow; // If we just set an empty crop it will behave as if there is no crop at all. // To fix this we explicitly hide the surface and won't let it to be shown. private boolean mHiddenForCrop = false; public SurfaceControlWithBackground(SurfaceControlWithBackground other) { public SurfaceControlWithBackground(SurfaceControlWithBackground other) { super(other); super(other); Loading @@ -76,7 +82,6 @@ class SurfaceControlWithBackground extends SurfaceControl { mLastWidth = w; mLastWidth = w; mLastHeight = h; mLastHeight = h; mWindowSurfaceController.getContainerRect(mTmpContainerRect); mWindowSurfaceController.getContainerRect(mTmpContainerRect); mIsStartingWindow = windowType == TYPE_APPLICATION_STARTING; mBackgroundControl = new SurfaceControl(s, "Background for - " + name, mBackgroundControl = new SurfaceControl(s, "Background for - " + name, mTmpContainerRect.width(), mTmpContainerRect.height(), PixelFormat.OPAQUE, mTmpContainerRect.width(), mTmpContainerRect.height(), PixelFormat.OPAQUE, flags | SurfaceControl.FX_SURFACE_DIM); flags | SurfaceControl.FX_SURFACE_DIM); Loading @@ -89,10 +94,7 @@ class SurfaceControlWithBackground extends SurfaceControl { if (mBackgroundControl == null) { if (mBackgroundControl == null) { return; return; } } // We won't animate alpha for starting window because it will be visible as a flash for user mBackgroundControl.setAlpha(alpha); // when fading out to reveal real app window. final float backgroundAlpha = mIsStartingWindow && alpha < 1.f ? 0 : alpha; mBackgroundControl.setAlpha(backgroundAlpha); } } @Override @Override Loading Loading @@ -146,15 +148,10 @@ class SurfaceControlWithBackground extends SurfaceControl { if (mBackgroundControl == null) { if (mBackgroundControl == null) { return; return; } } if (crop.width() < mLastWidth || crop.height() < mLastHeight) { // We're animating and cropping window, compute the appropriate crop for background. calculateBgCrop(crop); calculateBgCrop(crop); mBackgroundControl.setWindowCrop(mTmpContainerRect); mBackgroundControl.setWindowCrop(mTmpContainerRect); } else { mHiddenForCrop = mTmpContainerRect.isEmpty(); // When not animating just set crop to container rect. updateBackgroundVisibility(); mWindowSurfaceController.getContainerRect(mTmpContainerRect); mBackgroundControl.setWindowCrop(mTmpContainerRect); } } } @Override @Override Loading @@ -164,34 +161,24 @@ class SurfaceControlWithBackground extends SurfaceControl { if (mBackgroundControl == null) { if (mBackgroundControl == null) { return; return; } } if (crop.width() < mLastWidth || crop.height() < mLastHeight) { // We're animating and cropping window, compute the appropriate crop for background. calculateBgCrop(crop); mBackgroundControl.setFinalCrop(mTmpContainerRect); } else { // When not animating just set crop to container rect. mWindowSurfaceController.getContainerRect(mTmpContainerRect); mWindowSurfaceController.getContainerRect(mTmpContainerRect); mBackgroundControl.setFinalCrop(mTmpContainerRect); mBackgroundControl.setFinalCrop(mTmpContainerRect); } } } /** Compute background crop based on current animation progress for main surface control. */ /** * Compute background crop based on current animation progress for main surface control and * update {@link #mTmpContainerRect} with new values. */ private void calculateBgCrop(Rect crop) { private void calculateBgCrop(Rect crop) { // Track overall progress of animation by computing cropped portion of status bar. // Track overall progress of animation by computing cropped portion of status bar. final Rect contentInsets = mWindowSurfaceController.mAnimator.mWin.mContentInsets; final Rect contentInsets = mWindowSurfaceController.mAnimator.mWin.mContentInsets; float d = contentInsets.top == 0 ? 0 : (float) crop.top / contentInsets.top; float d = contentInsets.top == 0 ? 0 : (float) crop.top / contentInsets.top; if (d > 1.f) { if (d > 1.f) { // We're running expand animation from launcher, won't compute custom bg crop here. // We're running expand animation from launcher, won't compute custom bg crop here. mTmpContainerRect.set(crop); mTmpContainerRect.setEmpty(); return; return; } } // Compute additional offset for the background when app window is positioned not at (0,0). // E.g. landscape with navigation bar on the left. final Rect winFrame = mWindowSurfaceController.mAnimator.mWin.mFrame; final int offsetX = (int) (winFrame.left * mLastDsDx * d + 0.5); final int offsetY = (int) (winFrame.top * mLastDsDy * d + 0.5); // Compute new scaled width and height for background that will depend on current animation // Compute new scaled width and height for background that will depend on current animation // progress. Those consist of current crop rect for the main surface + scaled areas outside // progress. Those consist of current crop rect for the main surface + scaled areas outside // of letterboxed area. // of letterboxed area. Loading @@ -201,17 +188,39 @@ class SurfaceControlWithBackground extends SurfaceControl { // computing correct frames for letterboxed windows in WindowState. // computing correct frames for letterboxed windows in WindowState. d = d < 0.025f ? 0 : d; d = d < 0.025f ? 0 : d; mWindowSurfaceController.getContainerRect(mTmpContainerRect); mWindowSurfaceController.getContainerRect(mTmpContainerRect); final int backgroundWidth = int backgroundWidth = 0, backgroundHeight = 0; (int) (crop.width() + (mTmpContainerRect.width() - mLastWidth) * (1 - d) + 0.5); // Compute additional offset for the background when app window is positioned not at (0,0). final int backgroundHeight = // E.g. landscape with navigation bar on the left. (int) (crop.height() + (mTmpContainerRect.height() - mLastHeight) * (1 - d) + 0.5); final Rect winFrame = mWindowSurfaceController.mAnimator.mWin.mFrame; int offsetX = (int)((winFrame.left - mTmpContainerRect.left) * mLastDsDx), mTmpContainerRect.set(crop); offsetY = (int) ((winFrame.top - mTmpContainerRect.top) * mLastDsDy); // Make sure that part of background to left/top is visible and scaled. mTmpContainerRect.offset(offsetX, offsetY); // Position and size background. // Set correct width/height, so that area to right/bottom is cropped properly. final int bgPosition = mWindowSurfaceController.mAnimator.mService.getNavBarPosition(); mTmpContainerRect.right = mTmpContainerRect.left + backgroundWidth; mTmpContainerRect.bottom = mTmpContainerRect.top + backgroundHeight; switch (bgPosition) { case NAV_BAR_LEFT: backgroundWidth = (int) ((mTmpContainerRect.width() - mLastWidth) * (1 - d) + 0.5); backgroundHeight = crop.height(); offsetX += crop.left - backgroundWidth; offsetY += crop.top; break; case NAV_BAR_RIGHT: backgroundWidth = (int) ((mTmpContainerRect.width() - mLastWidth) * (1 - d) + 0.5); backgroundHeight = crop.height(); offsetX += crop.right; offsetY += crop.top; break; case NAV_BAR_BOTTOM: backgroundWidth = crop.width(); backgroundHeight = (int) ((mTmpContainerRect.height() - mLastHeight) * (1 - d) + 0.5); offsetX += crop.left; offsetY += crop.bottom; break; } mTmpContainerRect.set(offsetX, offsetY, offsetX + backgroundWidth, offsetY + backgroundHeight); } } @Override @Override Loading Loading @@ -317,7 +326,7 @@ class SurfaceControlWithBackground extends SurfaceControl { return; return; } } final AppWindowToken appWindowToken = mWindowSurfaceController.mAnimator.mWin.mAppToken; final AppWindowToken appWindowToken = mWindowSurfaceController.mAnimator.mWin.mAppToken; if (appWindowToken != null && appWindowToken.fillsParent() && mVisible) { if (!mHiddenForCrop && mVisible && appWindowToken != null && appWindowToken.fillsParent()) { mBackgroundControl.show(); mBackgroundControl.show(); } else { } else { mBackgroundControl.hide(); mBackgroundControl.hide(); Loading Loading
services/core/java/com/android/server/wm/SurfaceControlWithBackground.java +56 −47 Original line number Original line Diff line number Diff line Loading @@ -29,12 +29,16 @@ import android.view.SurfaceSession; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManagerPolicy.NAV_BAR_BOTTOM; import static android.view.WindowManagerPolicy.NAV_BAR_LEFT; import static android.view.WindowManagerPolicy.NAV_BAR_RIGHT; /** /** * SurfaceControl extension that has background sized to match its container. * SurfaceControl extension that has black background behind navigation bar area for fullscreen * letterboxed apps. */ */ class SurfaceControlWithBackground extends SurfaceControl { class SurfaceControlWithBackground extends SurfaceControl { // SurfaceControl that holds the background behind opaque letterboxed app windows. // SurfaceControl that holds the background. private SurfaceControl mBackgroundControl; private SurfaceControl mBackgroundControl; // Flag that defines whether the background should be shown. // Flag that defines whether the background should be shown. Loading @@ -51,8 +55,10 @@ class SurfaceControlWithBackground extends SurfaceControl { private float mLastDsDx = 1, mLastDsDy = 1; private float mLastDsDx = 1, mLastDsDy = 1; private float mLastX, mLastY; private float mLastX, mLastY; // Will skip alpha animation for background of starting window. // SurfaceFlinger doesn't support crop rectangles where width or height is non-positive. private boolean mIsStartingWindow; // If we just set an empty crop it will behave as if there is no crop at all. // To fix this we explicitly hide the surface and won't let it to be shown. private boolean mHiddenForCrop = false; public SurfaceControlWithBackground(SurfaceControlWithBackground other) { public SurfaceControlWithBackground(SurfaceControlWithBackground other) { super(other); super(other); Loading @@ -76,7 +82,6 @@ class SurfaceControlWithBackground extends SurfaceControl { mLastWidth = w; mLastWidth = w; mLastHeight = h; mLastHeight = h; mWindowSurfaceController.getContainerRect(mTmpContainerRect); mWindowSurfaceController.getContainerRect(mTmpContainerRect); mIsStartingWindow = windowType == TYPE_APPLICATION_STARTING; mBackgroundControl = new SurfaceControl(s, "Background for - " + name, mBackgroundControl = new SurfaceControl(s, "Background for - " + name, mTmpContainerRect.width(), mTmpContainerRect.height(), PixelFormat.OPAQUE, mTmpContainerRect.width(), mTmpContainerRect.height(), PixelFormat.OPAQUE, flags | SurfaceControl.FX_SURFACE_DIM); flags | SurfaceControl.FX_SURFACE_DIM); Loading @@ -89,10 +94,7 @@ class SurfaceControlWithBackground extends SurfaceControl { if (mBackgroundControl == null) { if (mBackgroundControl == null) { return; return; } } // We won't animate alpha for starting window because it will be visible as a flash for user mBackgroundControl.setAlpha(alpha); // when fading out to reveal real app window. final float backgroundAlpha = mIsStartingWindow && alpha < 1.f ? 0 : alpha; mBackgroundControl.setAlpha(backgroundAlpha); } } @Override @Override Loading Loading @@ -146,15 +148,10 @@ class SurfaceControlWithBackground extends SurfaceControl { if (mBackgroundControl == null) { if (mBackgroundControl == null) { return; return; } } if (crop.width() < mLastWidth || crop.height() < mLastHeight) { // We're animating and cropping window, compute the appropriate crop for background. calculateBgCrop(crop); calculateBgCrop(crop); mBackgroundControl.setWindowCrop(mTmpContainerRect); mBackgroundControl.setWindowCrop(mTmpContainerRect); } else { mHiddenForCrop = mTmpContainerRect.isEmpty(); // When not animating just set crop to container rect. updateBackgroundVisibility(); mWindowSurfaceController.getContainerRect(mTmpContainerRect); mBackgroundControl.setWindowCrop(mTmpContainerRect); } } } @Override @Override Loading @@ -164,34 +161,24 @@ class SurfaceControlWithBackground extends SurfaceControl { if (mBackgroundControl == null) { if (mBackgroundControl == null) { return; return; } } if (crop.width() < mLastWidth || crop.height() < mLastHeight) { // We're animating and cropping window, compute the appropriate crop for background. calculateBgCrop(crop); mBackgroundControl.setFinalCrop(mTmpContainerRect); } else { // When not animating just set crop to container rect. mWindowSurfaceController.getContainerRect(mTmpContainerRect); mWindowSurfaceController.getContainerRect(mTmpContainerRect); mBackgroundControl.setFinalCrop(mTmpContainerRect); mBackgroundControl.setFinalCrop(mTmpContainerRect); } } } /** Compute background crop based on current animation progress for main surface control. */ /** * Compute background crop based on current animation progress for main surface control and * update {@link #mTmpContainerRect} with new values. */ private void calculateBgCrop(Rect crop) { private void calculateBgCrop(Rect crop) { // Track overall progress of animation by computing cropped portion of status bar. // Track overall progress of animation by computing cropped portion of status bar. final Rect contentInsets = mWindowSurfaceController.mAnimator.mWin.mContentInsets; final Rect contentInsets = mWindowSurfaceController.mAnimator.mWin.mContentInsets; float d = contentInsets.top == 0 ? 0 : (float) crop.top / contentInsets.top; float d = contentInsets.top == 0 ? 0 : (float) crop.top / contentInsets.top; if (d > 1.f) { if (d > 1.f) { // We're running expand animation from launcher, won't compute custom bg crop here. // We're running expand animation from launcher, won't compute custom bg crop here. mTmpContainerRect.set(crop); mTmpContainerRect.setEmpty(); return; return; } } // Compute additional offset for the background when app window is positioned not at (0,0). // E.g. landscape with navigation bar on the left. final Rect winFrame = mWindowSurfaceController.mAnimator.mWin.mFrame; final int offsetX = (int) (winFrame.left * mLastDsDx * d + 0.5); final int offsetY = (int) (winFrame.top * mLastDsDy * d + 0.5); // Compute new scaled width and height for background that will depend on current animation // Compute new scaled width and height for background that will depend on current animation // progress. Those consist of current crop rect for the main surface + scaled areas outside // progress. Those consist of current crop rect for the main surface + scaled areas outside // of letterboxed area. // of letterboxed area. Loading @@ -201,17 +188,39 @@ class SurfaceControlWithBackground extends SurfaceControl { // computing correct frames for letterboxed windows in WindowState. // computing correct frames for letterboxed windows in WindowState. d = d < 0.025f ? 0 : d; d = d < 0.025f ? 0 : d; mWindowSurfaceController.getContainerRect(mTmpContainerRect); mWindowSurfaceController.getContainerRect(mTmpContainerRect); final int backgroundWidth = int backgroundWidth = 0, backgroundHeight = 0; (int) (crop.width() + (mTmpContainerRect.width() - mLastWidth) * (1 - d) + 0.5); // Compute additional offset for the background when app window is positioned not at (0,0). final int backgroundHeight = // E.g. landscape with navigation bar on the left. (int) (crop.height() + (mTmpContainerRect.height() - mLastHeight) * (1 - d) + 0.5); final Rect winFrame = mWindowSurfaceController.mAnimator.mWin.mFrame; int offsetX = (int)((winFrame.left - mTmpContainerRect.left) * mLastDsDx), mTmpContainerRect.set(crop); offsetY = (int) ((winFrame.top - mTmpContainerRect.top) * mLastDsDy); // Make sure that part of background to left/top is visible and scaled. mTmpContainerRect.offset(offsetX, offsetY); // Position and size background. // Set correct width/height, so that area to right/bottom is cropped properly. final int bgPosition = mWindowSurfaceController.mAnimator.mService.getNavBarPosition(); mTmpContainerRect.right = mTmpContainerRect.left + backgroundWidth; mTmpContainerRect.bottom = mTmpContainerRect.top + backgroundHeight; switch (bgPosition) { case NAV_BAR_LEFT: backgroundWidth = (int) ((mTmpContainerRect.width() - mLastWidth) * (1 - d) + 0.5); backgroundHeight = crop.height(); offsetX += crop.left - backgroundWidth; offsetY += crop.top; break; case NAV_BAR_RIGHT: backgroundWidth = (int) ((mTmpContainerRect.width() - mLastWidth) * (1 - d) + 0.5); backgroundHeight = crop.height(); offsetX += crop.right; offsetY += crop.top; break; case NAV_BAR_BOTTOM: backgroundWidth = crop.width(); backgroundHeight = (int) ((mTmpContainerRect.height() - mLastHeight) * (1 - d) + 0.5); offsetX += crop.left; offsetY += crop.bottom; break; } mTmpContainerRect.set(offsetX, offsetY, offsetX + backgroundWidth, offsetY + backgroundHeight); } } @Override @Override Loading Loading @@ -317,7 +326,7 @@ class SurfaceControlWithBackground extends SurfaceControl { return; return; } } final AppWindowToken appWindowToken = mWindowSurfaceController.mAnimator.mWin.mAppToken; final AppWindowToken appWindowToken = mWindowSurfaceController.mAnimator.mWin.mAppToken; if (appWindowToken != null && appWindowToken.fillsParent() && mVisible) { if (!mHiddenForCrop && mVisible && appWindowToken != null && appWindowToken.fillsParent()) { mBackgroundControl.show(); mBackgroundControl.show(); } else { } else { mBackgroundControl.hide(); mBackgroundControl.hide(); Loading