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

Commit bbbfeb61 authored by Milton Wu's avatar Milton Wu Committed by Automerger Merge Worker
Browse files

Merge "Move rounded corner to provider" into tm-dev am: 311ca4d7

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17154523

Change-Id: I0eec48650d441d54fd6fe9834a684ec054512a19
parents 883a93a1 311ca4d7
Loading
Loading
Loading
Loading
+0 −40
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
** Copyright 2020, 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.
-->
<com.android.systemui.RegionInterceptingFrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rounded_corners_bottom"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:id="@+id/left"
        android:layout_width="12dp"
        android:layout_height="12dp"
        android:layout_gravity="left|bottom"
        android:tint="#ff000000"
        android:visibility="gone"
        android:src="@drawable/rounded_corner_bottom"/>

    <ImageView
        android:id="@+id/right"
        android:layout_width="12dp"
        android:layout_height="12dp"
        android:tint="#ff000000"
        android:visibility="gone"
        android:layout_gravity="right|bottom"
        android:src="@drawable/rounded_corner_bottom"/>

</com.android.systemui.RegionInterceptingFrameLayout>
+0 −40
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
** Copyright 2020, 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.
-->
<com.android.systemui.RegionInterceptingFrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rounded_corners_top"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:id="@+id/left"
        android:layout_width="12dp"
        android:layout_height="12dp"
        android:layout_gravity="left|top"
        android:tint="#ff000000"
        android:visibility="gone"
        android:src="@drawable/rounded_corner_top"/>

    <ImageView
        android:id="@+id/right"
        android:layout_width="12dp"
        android:layout_height="12dp"
        android:tint="#ff000000"
        android:visibility="gone"
        android:layout_gravity="right|top"
        android:src="@drawable/rounded_corner_top"/>

</com.android.systemui.RegionInterceptingFrameLayout>
+6 −0
Original line number Diff line number Diff line
@@ -167,5 +167,11 @@
    <item type="id" name="action_move_bottom_right"/>
    <item type="id" name="action_move_to_edge_and_hide"/>
    <item type="id" name="action_move_out_edge_and_show"/>

    <!-- rounded corner view id -->
    <item type="id" name="rounded_corner_top_left"/>
    <item type="id" name="rounded_corner_top_right"/>
    <item type="id" name="rounded_corner_bottom_left"/>
    <item type="id" name="rounded_corner_bottom_right"/>
</resources>
+6 −1
Original line number Diff line number Diff line
@@ -365,10 +365,15 @@ class ScreenDecorHwcLayer(context: Context, displayDecorationSupport: DisplayDec
     * Update the rounded corner size.
     */
    fun updateRoundedCornerSize(top: Int, bottom: Int) {
        if (roundedCornerTopSize == top && roundedCornerBottomSize == bottom) {
            return
        }
        roundedCornerTopSize = top
        roundedCornerBottomSize = bottom
        updateRoundedCornerDrawableBounds()
        invalidate()

        // Use requestLayout() to trigger transparent region recalculated
        requestLayout()
    }

    private fun updateRoundedCornerDrawableBounds() {
+64 −205
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ import com.android.systemui.decor.DecorProviderFactory;
import com.android.systemui.decor.DecorProviderKt;
import com.android.systemui.decor.OverlayWindow;
import com.android.systemui.decor.PrivacyDotDecorProviderFactory;
import com.android.systemui.decor.RoundedCornerDecorProviderFactory;
import com.android.systemui.decor.RoundedCornerResDelegate;
import com.android.systemui.qs.SettingObserver;
import com.android.systemui.settings.UserTracker;
@@ -138,6 +139,9 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
    @VisibleForTesting
    protected RoundedCornerResDelegate mRoundedCornerResDelegate;
    @VisibleForTesting
    protected DecorProviderFactory mRoundedCornerFactory;
    private int mProviderRefreshToken = 0;
    @VisibleForTesting
    protected OverlayWindow[] mOverlays = null;
    @Nullable
    private DisplayCutoutView[] mCutoutViews;
@@ -292,11 +296,11 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
        mDisplayUniqueId = mContext.getDisplay().getUniqueId();
        mRoundedCornerResDelegate = new RoundedCornerResDelegate(mContext.getResources(),
                mDisplayUniqueId);
        mRoundedCornerFactory = new RoundedCornerDecorProviderFactory(mRoundedCornerResDelegate);
        mWindowManager = mContext.getSystemService(WindowManager.class);
        mDisplayManager = mContext.getSystemService(DisplayManager.class);
        mHwcScreenDecorationSupport = mContext.getDisplay().getDisplayDecorationSupport();
        updateRoundedCornerDrawable();
        updateRoundedCornerRadii();
        updateHwLayerRoundedCornerDrawable();
        setupDecorations();
        setupCameraListener();

@@ -348,7 +352,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
                final String newUniqueId = mContext.getDisplay().getUniqueId();
                if (!Objects.equals(newUniqueId, mDisplayUniqueId)) {
                    mDisplayUniqueId = newUniqueId;
                    mRoundedCornerResDelegate.reloadAll(newUniqueId);
                    mRoundedCornerResDelegate.updateDisplayUniqueId(newUniqueId, null);
                    final DisplayDecorationSupport newScreenDecorationSupport =
                            mContext.getDisplay().getDisplayDecorationSupport();
                    // When the value of mSupportHwcScreenDecoration is changed, re-setup the whole
@@ -359,12 +363,12 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
                        setupDecorations();
                        return;
                    }
                    updateRoundedCornerDrawable();
                    updateHwLayerRoundedCornerDrawable();
                }
                if (mScreenDecorHwcLayer != null) {
                    mScreenDecorHwcLayer.onDisplayChanged(displayId);
                }
                updateOrientation();
                updateView();
            }
        };

@@ -406,22 +410,22 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
    }

    private void setupDecorations() {
        List<DecorProvider> decorProviders = mDotFactory.getProviders();

        if (hasRoundedCorners() || shouldDrawCutout() || !decorProviders.isEmpty()) {
        if (hasRoundedCorners() || shouldDrawCutout() || isPrivacyDotEnabled()) {
            List<DecorProvider> decorProviders = new ArrayList<>(mDotFactory.getProviders());
            if (mHwcScreenDecorationSupport != null) {
                createHwcOverlay();
            } else {
                removeHwcOverlay();
                decorProviders.addAll(mRoundedCornerFactory.getProviders());
            }
            final DisplayCutout cutout = getCutout();
            for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
                if (shouldShowCutout(i, cutout) || shouldShowRoundedCorner(i, cutout)
                        || shouldShowPrivacyDot(i, cutout)) {
                if (shouldShowSwLayerCutout(i, cutout) || shouldShowSwLayerRoundedCorner(i, cutout)
                        || shouldShowSwLayerPrivacyDot(i, cutout)) {
                    Pair<List<DecorProvider>, List<DecorProvider>> pair =
                            DecorProviderKt.partitionAlignedBound(decorProviders, i);
                    decorProviders = pair.getSecond();
                    createOverlay(i, cutout, pair.getFirst());
                    createOverlay(i, pair.getFirst());
                } else {
                    removeOverlay(i);
                }
@@ -522,7 +526,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab

    private void createOverlay(
            @BoundsPosition int pos,
            @Nullable DisplayCutout cutout,
            @NonNull List<DecorProvider> decorProviders) {
        if (mOverlays == null) {
            mOverlays = new OverlayWindow[BOUNDS_POSITION_LENGTH];
@@ -547,7 +550,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
            mCutoutViews[pos] = new DisplayCutoutView(mContext, pos);
            mCutoutViews[pos].setColor(mTintColor);
            overlayView.addView(mCutoutViews[pos]);
            updateView(pos, cutout);
            mCutoutViews[pos].updateRotation(mRotation);
        }

        mWindowManager.addView(overlayView, getWindowLayoutParams(pos));
@@ -603,7 +606,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
    private OverlayWindow overlayForPosition(
            @BoundsPosition int pos,
            @NonNull List<DecorProvider> decorProviders) {
        final OverlayWindow currentOverlay = new OverlayWindow(LayoutInflater.from(mContext), pos);
        final OverlayWindow currentOverlay = new OverlayWindow(mContext);
        decorProviders.forEach(provider -> {
            removeOverlayView(provider.getViewId());
            currentOverlay.addDecorProvider(provider, mRotation);
@@ -617,22 +620,16 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
        return currentOverlay;
    }

    private void updateView(@BoundsPosition int pos, @Nullable DisplayCutout cutout) {
        if (mOverlays == null || mOverlays[pos] == null || mHwcScreenDecorationSupport != null) {
    private void updateView() {
        if (mOverlays == null) {
            return;
        }

        // update rounded corner view rotation
        updateRoundedCornerView(pos, R.id.left, cutout);
        updateRoundedCornerView(pos, R.id.right, cutout);
        updateRoundedCornerSize(
                mRoundedCornerResDelegate.getTopRoundedSize(),
                mRoundedCornerResDelegate.getBottomRoundedSize());
        updateRoundedCornerImageView();

        // update cutout view rotation
        if (mCutoutViews != null && mCutoutViews[pos] != null) {
            mCutoutViews[pos].updateRotation(mRotation);
        ++mProviderRefreshToken;
        for (final OverlayWindow overlay: mOverlays) {
            if (overlay == null) {
                continue;
            }
            overlay.onReloadResAndMeasure(null, mProviderRefreshToken, mRotation, mDisplayUniqueId);
        }
    }

@@ -806,7 +803,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
            int oldRotation = mRotation;
            mPendingRotationChange = false;
            updateOrientation();
            updateRoundedCornerRadii();
            if (DEBUG) Log.i(TAG, "onConfigChanged from rot " + oldRotation + " to " + mRotation);
            setupDecorations();
            if (mOverlays != null) {
@@ -866,109 +862,32 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
            mDotViewController.setNewRotation(newRotation);
        }

        if (mPendingRotationChange) {
            return;
        }
        if (newRotation != mRotation) {
        if (!mPendingRotationChange && newRotation != mRotation) {
            mRotation = newRotation;
            if (mScreenDecorHwcLayer != null) {
                mScreenDecorHwcLayer.pendingRotationChange = false;
                mScreenDecorHwcLayer.updateRotation(mRotation);
                updateHwLayerRoundedCornerSize();
                updateHwLayerRoundedCornerDrawable();
            }
            if (mOverlays != null) {
            updateLayoutParams();
                final DisplayCutout cutout = getCutout();
                for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
                    if (mOverlays[i] == null) {
            // update cutout view rotation
            if (mCutoutViews != null) {
                for (final DisplayCutoutView cutoutView: mCutoutViews) {
                    if (cutoutView == null) {
                        continue;
                    }
                    updateView(i, cutout);
                }
                    cutoutView.updateRotation(mRotation);
                }
            }
        }

    private void updateRoundedCornerRadii() {
        // We should eventually move to just using the intrinsic size of the drawables since
        // they should be sized to the exact pixels they want to cover. Therefore I'm purposely not
        // upgrading all of the configs to contain (width, height) pairs. Instead assume that a
        // device configured using the single integer config value is okay with drawing the corners
        // as a square
        final Size oldRoundedDefaultTop = mRoundedCornerResDelegate.getTopRoundedSize();
        final Size oldRoundedDefaultBottom = mRoundedCornerResDelegate.getBottomRoundedSize();
        mRoundedCornerResDelegate.reloadAll(mDisplayUniqueId);
        final Size newRoundedDefaultTop = mRoundedCornerResDelegate.getTopRoundedSize();
        final Size newRoundedDefaultBottom = mRoundedCornerResDelegate.getBottomRoundedSize();

        if (oldRoundedDefaultTop.getWidth() != newRoundedDefaultTop.getWidth()
                || oldRoundedDefaultBottom.getWidth() != newRoundedDefaultBottom.getWidth()) {
            onTuningChanged(SIZE, null);
        }
        // update views
        updateView();
    }

    private void updateRoundedCornerView(@BoundsPosition int pos, int id,
            @Nullable DisplayCutout cutout) {
        final View rounded = mOverlays[pos].getRootView().findViewById(id);
        if (rounded == null) {
            return;
        }
        rounded.setVisibility(View.GONE);
        if (shouldShowRoundedCorner(pos, cutout)) {
            final int gravity = getRoundedCornerGravity(pos, id == R.id.left);
            ((FrameLayout.LayoutParams) rounded.getLayoutParams()).gravity = gravity;
            setRoundedCornerOrientation(rounded, gravity);
            rounded.setVisibility(View.VISIBLE);
        }
    }

    private int getRoundedCornerGravity(@BoundsPosition int pos, boolean isStart) {
        final int rotatedPos = getBoundPositionFromRotation(pos, mRotation);
        switch (rotatedPos) {
            case BOUNDS_POSITION_LEFT:
                return isStart ? Gravity.TOP | Gravity.LEFT : Gravity.BOTTOM | Gravity.LEFT;
            case BOUNDS_POSITION_TOP:
                return isStart ? Gravity.TOP | Gravity.LEFT : Gravity.TOP | Gravity.RIGHT;
            case BOUNDS_POSITION_RIGHT:
                return isStart ? Gravity.TOP | Gravity.RIGHT : Gravity.BOTTOM | Gravity.RIGHT;
            case BOUNDS_POSITION_BOTTOM:
                return isStart ? Gravity.BOTTOM | Gravity.LEFT : Gravity.BOTTOM | Gravity.RIGHT;
            default:
                throw new IllegalArgumentException("Incorrect position: " + rotatedPos);
        }
    }

    /**
     * Configures the rounded corner drawable's view matrix based on the gravity.
     *
     * The gravity describes which corner to configure for, and the drawable we are rotating is
     * assumed to be oriented for the top-left corner of the device regardless of the target corner.
     * Therefore we need to rotate 180 degrees to get a bottom-left corner, and mirror in the x- or
     * y-axis for the top-right and bottom-left corners.
     */
    private void setRoundedCornerOrientation(View corner, int gravity) {
        corner.setRotation(0);
        corner.setScaleX(1);
        corner.setScaleY(1);
        switch (gravity) {
            case Gravity.TOP | Gravity.LEFT:
                return;
            case Gravity.TOP | Gravity.RIGHT:
                corner.setScaleX(-1); // flip X axis
                return;
            case Gravity.BOTTOM | Gravity.LEFT:
                corner.setScaleY(-1); // flip Y axis
                return;
            case Gravity.BOTTOM | Gravity.RIGHT:
                corner.setRotation(180);
                return;
            default:
                throw new IllegalArgumentException("Unsupported gravity: " + gravity);
        }
    }
    private boolean hasRoundedCorners() {
        return mRoundedCornerResDelegate.getBottomRoundedSize().getWidth() > 0
                || mRoundedCornerResDelegate.getTopRoundedSize().getWidth() > 0
                || mRoundedCornerResDelegate.isMultipleRadius();
        return mRoundedCornerFactory.getHasProviders();
    }

    private boolean isDefaultShownOverlayPos(@BoundsPosition int pos,
@@ -987,17 +906,19 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
        }
    }

    private boolean shouldShowRoundedCorner(@BoundsPosition int pos,
    private boolean shouldShowSwLayerRoundedCorner(@BoundsPosition int pos,
            @Nullable DisplayCutout cutout) {
        return hasRoundedCorners() && isDefaultShownOverlayPos(pos, cutout)
                && mHwcScreenDecorationSupport == null;
    }

    private boolean shouldShowPrivacyDot(@BoundsPosition int pos, @Nullable DisplayCutout cutout) {
    private boolean shouldShowSwLayerPrivacyDot(@BoundsPosition int pos,
            @Nullable DisplayCutout cutout) {
        return isPrivacyDotEnabled() && isDefaultShownOverlayPos(pos, cutout);
    }

    private boolean shouldShowCutout(@BoundsPosition int pos, @Nullable DisplayCutout cutout) {
    private boolean shouldShowSwLayerCutout(@BoundsPosition int pos,
            @Nullable DisplayCutout cutout) {
        final Rect[] bounds = cutout == null ? null : cutout.getBoundingRectsAll();
        final int rotatedPos = getBoundPositionFromRotation(pos, mRotation);
        return (bounds != null && !bounds[rotatedPos].isEmpty()
@@ -1032,52 +953,31 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
            return;
        }
        mExecutor.execute(() -> {
            if (mOverlays == null) return;
            if (SIZE.equals(key)) {
                if (newValue != null) {
                    try {
                        mRoundedCornerResDelegate.updateTuningSizeFactor(
                                Integer.parseInt(newValue));
                    } catch (Exception e) {
                    }
                }
                updateRoundedCornerSize(
                        mRoundedCornerResDelegate.getTopRoundedSize(),
                        mRoundedCornerResDelegate.getBottomRoundedSize());
            }
        });
    }

    private void updateRoundedCornerDrawable() {
        mRoundedCornerResDelegate.reloadAll(mDisplayUniqueId);
        updateRoundedCornerImageView();
    }

    private void updateRoundedCornerImageView() {
        final Drawable top = mRoundedCornerResDelegate.getTopRoundedDrawable();
        final Drawable bottom = mRoundedCornerResDelegate.getBottomRoundedDrawable();

        if (mScreenDecorHwcLayer != null) {
            mScreenDecorHwcLayer.updateRoundedCornerDrawable(top, bottom);
            return;
        }

        if (mOverlays == null) {
            if (mOverlays == null || !SIZE.equals(key)) {
                return;
            }
        final ColorStateList colorStateList = ColorStateList.valueOf(mTintColor);
        for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
            if (mOverlays[i] == null) {
            ++mProviderRefreshToken;
            try {
                final int sizeFactor = Integer.parseInt(newValue);
                mRoundedCornerResDelegate.updateTuningSizeFactor(sizeFactor, mProviderRefreshToken);
            } catch (NumberFormatException e) {
                mRoundedCornerResDelegate.updateTuningSizeFactor(null, mProviderRefreshToken);
            }
            Integer[] filterIds = {
                    R.id.rounded_corner_top_left,
                    R.id.rounded_corner_top_right,
                    R.id.rounded_corner_bottom_left,
                    R.id.rounded_corner_bottom_right
            };
            for (final OverlayWindow overlay: mOverlays) {
                if (overlay == null) {
                    continue;
                }
            final ViewGroup overlayView = mOverlays[i].getRootView();
            ((ImageView) overlayView.findViewById(R.id.left)).setImageTintList(colorStateList);
            ((ImageView) overlayView.findViewById(R.id.right)).setImageTintList(colorStateList);
            ((ImageView) overlayView.findViewById(R.id.left)).setImageDrawable(
                    isTopRoundedCorner(i, R.id.left) ? top : bottom);
            ((ImageView) overlayView.findViewById(R.id.right)).setImageDrawable(
                    isTopRoundedCorner(i, R.id.right) ? top : bottom);
                overlay.onReloadResAndMeasure(filterIds, mProviderRefreshToken, mRotation,
                        mDisplayUniqueId);
            }
            updateHwLayerRoundedCornerSize();
        });
    }

    private void updateHwLayerRoundedCornerDrawable() {
@@ -1094,25 +994,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
        mScreenDecorHwcLayer.updateRoundedCornerDrawable(topDrawable, bottomDrawable);
    }

    @VisibleForTesting
    boolean isTopRoundedCorner(@BoundsPosition int pos, int id) {
        switch (pos) {
            case BOUNDS_POSITION_LEFT:
            case BOUNDS_POSITION_RIGHT:
                if (mRotation == ROTATION_270) {
                    return id == R.id.left ? false : true;
                } else {
                    return id == R.id.left ? true : false;
                }
            case BOUNDS_POSITION_TOP:
                return true;
            case BOUNDS_POSITION_BOTTOM:
                return false;
            default:
                throw new IllegalArgumentException("Unknown bounds position");
        }
    }

    private void updateHwLayerRoundedCornerSize() {
        if (mScreenDecorHwcLayer == null) {
            return;
@@ -1124,28 +1005,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
        mScreenDecorHwcLayer.updateRoundedCornerSize(topWidth, bottomWidth);
    }

    private void updateRoundedCornerSize(Size sizeTop, Size sizeBottom) {

        if (mScreenDecorHwcLayer != null) {
            mScreenDecorHwcLayer.updateRoundedCornerSize(sizeTop.getWidth(), sizeBottom.getWidth());
            return;
        }

        if (mOverlays == null) {
            return;
        }
        for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
            if (mOverlays[i] == null) {
                continue;
            }
            final ViewGroup overlayView = mOverlays[i].getRootView();
            setSize(overlayView.findViewById(R.id.left),
                    isTopRoundedCorner(i, R.id.left) ? sizeTop : sizeBottom);
            setSize(overlayView.findViewById(R.id.right),
                    isTopRoundedCorner(i, R.id.right) ? sizeTop : sizeBottom);
        }
    }

    @VisibleForTesting
    protected void setSize(View view, Size pixelSize) {
        LayoutParams params = view.getLayoutParams();
Loading