Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 66994114 authored by Andrii Kulian's avatar Andrii Kulian Committed by android-build-merger
Browse files

Merge "Add black frame behind app window" into oc-dr1-dev

am: cbdaf041

Change-Id: I9ce5cf5aea7f0fd93fbe24664bbd583d5057d3e6
parents a5fc11d7 cbdaf041
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -65,7 +65,8 @@ public class SurfaceControl {
    private static native void nativeSetSize(long nativeObject, int w, int h);
    private static native void nativeSetTransparentRegionHint(long nativeObject, Region region);
    private static native void nativeSetAlpha(long nativeObject, float alpha);
    private static native void nativeSetMatrix(long nativeObject, float dsdx, float dtdx, float dsdy, float dtdy);
    private static native void nativeSetMatrix(long nativeObject, float dsdx, float dtdx,
            float dtdy, float dsdy);
    private static native void nativeSetFlags(long nativeObject, int flags, int mask);
    private static native void nativeSetWindowCrop(long nativeObject, int l, int t, int r, int b);
    private static native void nativeSetFinalCrop(long nativeObject, int l, int t, int r, int b);
+3 −2
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ import java.io.DataOutputStream;
// the surface control.
//
// See cts/hostsidetests/../../SurfaceTraceReceiver.java for parsing side.
class RemoteSurfaceTrace extends SurfaceControl {
class RemoteSurfaceTrace extends SurfaceControlWithBackground {
    static final String TAG = "RemoteSurfaceTrace";

    final FileDescriptor mWriteFd;
@@ -41,7 +41,8 @@ class RemoteSurfaceTrace extends SurfaceControl {
    final WindowManagerService mService;
    final WindowState mWindow;

    RemoteSurfaceTrace(FileDescriptor fd, SurfaceControl wrapped, WindowState window) {
    RemoteSurfaceTrace(FileDescriptor fd, SurfaceControlWithBackground wrapped,
            WindowState window) {
        super(wrapped);

        mWriteFd = fd;
+306 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package com.android.server.wm;

import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.IBinder;
import android.os.Parcel;
import android.view.Surface;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
import android.view.SurfaceSession;

/**
 * SurfaceControl extension that has background sized to match its container.
 */
class SurfaceControlWithBackground extends SurfaceControl {
    // SurfaceControl that holds the background behind opaque letterboxed app windows.
    private SurfaceControl mBackgroundControl;

    // Flags that define whether the background should be shown.
    private boolean mOpaque;
    private boolean mVisible;

    // Way to communicate with corresponding window.
    private WindowSurfaceController mWindowSurfaceController;

    // Rect to hold task bounds when computing metrics for background.
    private Rect mTmpContainerRect = new Rect();

    // Last metrics applied to the main SurfaceControl.
    private float mLastWidth, mLastHeight;
    private float mLastDsDx = 1, mLastDsDy = 1;
    private float mLastX, mLastY;

    public SurfaceControlWithBackground(SurfaceControlWithBackground other) {
        super(other);
        mBackgroundControl = other.mBackgroundControl;
        mOpaque = other.mOpaque;
        mVisible = other.mVisible;
        mWindowSurfaceController = other.mWindowSurfaceController;
    }

    public SurfaceControlWithBackground(SurfaceSession s, String name, int w, int h, int format,
            int flags, int windowType, int ownerUid,
            WindowSurfaceController windowSurfaceController) throws OutOfResourcesException {
        super(s, name, w, h, format, flags, windowType, ownerUid);

        // We should only show background when the window is letterboxed in a task.
        if (!windowSurfaceController.mAnimator.mWin.isLetterboxedAppWindow()) {
            return;
        }
        mWindowSurfaceController = windowSurfaceController;
        mLastWidth = w;
        mLastHeight = h;
        mOpaque = (flags & SurfaceControl.OPAQUE) != 0;
        mWindowSurfaceController.getContainerRect(mTmpContainerRect);
        mBackgroundControl = new SurfaceControl(s, "Background for - " + name,
                mTmpContainerRect.width(), mTmpContainerRect.height(), PixelFormat.OPAQUE,
                flags | SurfaceControl.FX_SURFACE_DIM);
    }

    @Override
    public void setAlpha(float alpha) {
        super.setAlpha(alpha);

        if (mBackgroundControl == null) {
            return;
        }
        mBackgroundControl.setAlpha(alpha);
    }

    @Override
    public void setLayer(int zorder) {
        super.setLayer(zorder);

        if (mBackgroundControl == null) {
            return;
        }
        // TODO: Use setRelativeLayer(Integer.MIN_VALUE) when it's fixed.
        mBackgroundControl.setLayer(zorder - 1);
    }

    @Override
    public void setPosition(float x, float y) {
        super.setPosition(x, y);

        if (mBackgroundControl == null) {
            return;
        }
        mLastX = x;
        mLastY = y;
        updateBgPosition();
    }

    private void updateBgPosition() {
        mWindowSurfaceController.getContainerRect(mTmpContainerRect);
        final Rect winFrame = mWindowSurfaceController.mAnimator.mWin.mFrame;
        final float offsetX = (mTmpContainerRect.left - winFrame.left) * mLastDsDx;
        final float offsetY = (mTmpContainerRect.top - winFrame.top) * mLastDsDy;
        mBackgroundControl.setPosition(mLastX + offsetX, mLastY + offsetY);
    }

    @Override
    public void setSize(int w, int h) {
        super.setSize(w, h);

        if (mBackgroundControl == null) {
            return;
        }
        mLastWidth = w;
        mLastHeight = h;
        mWindowSurfaceController.getContainerRect(mTmpContainerRect);
        mBackgroundControl.setSize(mTmpContainerRect.width(), mTmpContainerRect.height());
    }

    @Override
    public void setWindowCrop(Rect crop) {
        super.setWindowCrop(crop);

        if (mBackgroundControl == null) {
            return;
        }
        if (crop.width() < mLastWidth || crop.height() < mLastHeight) {
            // We're animating and cropping window, compute the appropriate crop for background.
            calculateBgCrop(crop);
            mBackgroundControl.setWindowCrop(mTmpContainerRect);
        } else {
            // When not animating just set crop to container rect.
            mWindowSurfaceController.getContainerRect(mTmpContainerRect);
            mBackgroundControl.setWindowCrop(mTmpContainerRect);
        }
    }

    @Override
    public void setFinalCrop(Rect crop) {
        super.setFinalCrop(crop);

        if (mBackgroundControl == null) {
            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);
            mBackgroundControl.setFinalCrop(mTmpContainerRect);
        }
    }

    /** Compute background crop based on current animation progress for main surface control. */
    private void calculateBgCrop(Rect crop) {
        // Track overall progress of animation by computing cropped portion of status bar.
        final Rect contentInsets = mWindowSurfaceController.mAnimator.mWin.mContentInsets;
        float d = contentInsets.top == 0 ? 0 : (float) crop.top / contentInsets.top;

        // 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
        // progress. Those consist of current crop rect for the main surface + scaled areas outside
        // of letterboxed area.
        mWindowSurfaceController.getContainerRect(mTmpContainerRect);
        final int backgroundWidth =
                (int) (crop.width() + (mTmpContainerRect.width() - mLastWidth) * (1 - d) + 0.5);
        final int backgroundHeight =
                (int) (crop.height() + (mTmpContainerRect.height() - mLastHeight) * (1 - d) + 0.5);

        mTmpContainerRect.set(crop);
        // Make sure that part of background to left/top is visible and scaled.
        mTmpContainerRect.offset(offsetX, offsetY);
        // Set correct width/height, so that area to right/bottom is cropped properly.
        mTmpContainerRect.right = mTmpContainerRect.left + backgroundWidth;
        mTmpContainerRect.bottom = mTmpContainerRect.top + backgroundHeight;
    }

    @Override
    public void setLayerStack(int layerStack) {
        super.setLayerStack(layerStack);

        if (mBackgroundControl == null) {
            return;
        }
        mBackgroundControl.setLayerStack(layerStack);
    }

    @Override
    public void setOpaque(boolean isOpaque) {
        super.setOpaque(isOpaque);
        mOpaque = isOpaque;
        updateBackgroundVisibility();
    }

    @Override
    public void setSecure(boolean isSecure) {
        super.setSecure(isSecure);
    }

    @Override
    public void setMatrix(float dsdx, float dtdx, float dtdy, float dsdy) {
        super.setMatrix(dsdx, dtdx, dtdy, dsdy);

        if (mBackgroundControl == null) {
            return;
        }
        mBackgroundControl.setMatrix(dsdx, dtdx, dtdy, dsdy);
        mLastDsDx = dsdx;
        mLastDsDy = dsdy;
        updateBgPosition();
    }

    @Override
    public void hide() {
        super.hide();
        mVisible = false;
        updateBackgroundVisibility();
    }

    @Override
    public void show() {
        super.show();
        mVisible = true;
        updateBackgroundVisibility();
    }

    @Override
    public void destroy() {
        super.destroy();

        if (mBackgroundControl == null) {
            return;
        }
        mBackgroundControl.destroy();
    }

    @Override
    public void release() {
        super.release();

        if (mBackgroundControl == null) {
            return;
        }
        mBackgroundControl.release();
    }

    @Override
    public void setTransparentRegionHint(Region region) {
        super.setTransparentRegionHint(region);

        if (mBackgroundControl == null) {
            return;
        }
        mBackgroundControl.setTransparentRegionHint(region);
    }

    @Override
    public void deferTransactionUntil(IBinder handle, long frame) {
        super.deferTransactionUntil(handle, frame);

        if (mBackgroundControl == null) {
            return;
        }
        mBackgroundControl.deferTransactionUntil(handle, frame);
    }

    @Override
    public void deferTransactionUntil(Surface barrier, long frame) {
        super.deferTransactionUntil(barrier, frame);

        if (mBackgroundControl == null) {
            return;
        }
        mBackgroundControl.deferTransactionUntil(barrier, frame);
    }

    private void updateBackgroundVisibility() {
        if (mBackgroundControl == null) {
            return;
        }
        if (mOpaque && mVisible) {
            mBackgroundControl.show();
        } else {
            mBackgroundControl.hide();
        }
    }
}
+9 −0
Original line number Diff line number Diff line
@@ -3244,6 +3244,15 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        return !isInMultiWindowMode();
    }

    /** @return true when the window is in fullscreen task, but has non-fullscreen bounds set. */
    boolean isLetterboxedAppWindow() {
        final Task task = getTask();
        final boolean taskIsFullscreen = task != null && task.isFullscreen();
        final boolean appWindowIsFullscreen = mAppToken != null && !mAppToken.hasBounds();

        return taskIsFullscreen && !appWindowIsFullscreen;
    }

    /** Returns the appropriate bounds to use for computing frames. */
    private void getContainerBounds(Rect outBounds) {
        if (isInMultiWindowMode()) {
+15 −1
Original line number Diff line number Diff line
@@ -1200,7 +1200,8 @@ class WindowStateAnimator {
        if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Applying decor to crop win=" + w + " mDecorFrame="
                + w.mDecorFrame + " mSystemDecorRect=" + mSystemDecorRect);

        final boolean fullscreen = w.fillsDisplay();
        final Task task = w.getTask();
        final boolean fullscreen = w.fillsDisplay() || (task != null && task.isFullscreen());
        final boolean isFreeformResizing =
                w.isDragResizing() && w.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM;

@@ -1526,6 +1527,19 @@ class WindowStateAnimator {
        }
    }

    /**
     * Get rect of the task this window is currently in. If there is no task, rect will be set to
     * empty.
     */
    void getContainerRect(Rect rect) {
        final Task task = mWin.getTask();
        if (task != null) {
            task.getDimBounds(rect);
        } else {
            rect.left = rect.top = rect.right = rect.bottom = 0;
        }
    }

    void prepareSurfaceLocked(final boolean recoveringMemory) {
        final WindowState w = mWin;
        if (!hasSurface()) {
Loading