/*
 * 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.systemui;

import static android.view.DisplayCutout.BOUNDS_POSITION_BOTTOM;
import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
import static android.view.DisplayCutout.BOUNDS_POSITION_LENGTH;
import static android.view.DisplayCutout.BOUNDS_POSITION_RIGHT;
import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;

import android.annotation.IdRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManager;
import android.hardware.graphics.common.AlphaInterpretation;
import android.hardware.graphics.common.DisplayDecorationSupport;
import android.os.Handler;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings.Secure;
import android.util.DisplayUtils;
import android.util.Log;
import android.util.Size;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.DisplayCutout.BoundsPosition;
import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnLayoutChangeListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.FrameLayout;

import androidx.annotation.VisibleForTesting;

import com.android.internal.util.Preconditions;
import com.android.settingslib.Utils;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.decor.DecorProvider;
import com.android.systemui.decor.DecorProviderFactory;
import com.android.systemui.decor.DecorProviderKt;
import com.android.systemui.decor.FaceScanningProviderFactory;
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;
import com.android.systemui.statusbar.events.PrivacyDotViewController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.concurrency.ThreadFactory;
import com.android.systemui.util.settings.SecureSettings;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executor;

import javax.inject.Inject;

import kotlin.Pair;

/**
 * An overlay that draws screen decorations in software (e.g for rounded corners or display cutout)
 * for antialiasing and emulation purposes.
 */
@SysUISingleton
public class ScreenDecorations extends CoreStartable implements Tunable , Dumpable {
    private static final boolean DEBUG = false;
    private static final String TAG = "ScreenDecorations";

    public static final String SIZE = "sysui_rounded_size";
    public static final String PADDING = "sysui_rounded_content_padding";
    // Provide a way for factory to disable ScreenDecorations to run the Display tests.
    private static final boolean DEBUG_DISABLE_SCREEN_DECORATIONS =
            SystemProperties.getBoolean("debug.disable_screen_decorations", false);
    private static final boolean DEBUG_SCREENSHOT_ROUNDED_CORNERS =
            SystemProperties.getBoolean("debug.screenshot_rounded_corners", false);
    private static final boolean VERBOSE = false;
    static final boolean DEBUG_COLOR = DEBUG_SCREENSHOT_ROUNDED_CORNERS;

    private DisplayManager mDisplayManager;
    @VisibleForTesting
    protected boolean mIsRegistered;
    private final BroadcastDispatcher mBroadcastDispatcher;
    private final Executor mMainExecutor;
    private final TunerService mTunerService;
    private final SecureSettings mSecureSettings;
    @VisibleForTesting
    DisplayManager.DisplayListener mDisplayListener;
    private CameraAvailabilityListener mCameraListener;
    private final UserTracker mUserTracker;
    private final PrivacyDotViewController mDotViewController;
    private final ThreadFactory mThreadFactory;
    private final DecorProviderFactory mDotFactory;
    private final FaceScanningProviderFactory mFaceScanningFactory;
    public final int mFaceScanningViewId;

    @VisibleForTesting
    protected RoundedCornerResDelegate mRoundedCornerResDelegate;
    @VisibleForTesting
    protected DecorProviderFactory mRoundedCornerFactory;
    private int mProviderRefreshToken = 0;
    @VisibleForTesting
    protected OverlayWindow[] mOverlays = null;
    @VisibleForTesting
    @Nullable
    DisplayCutoutView[] mCutoutViews;
    @VisibleForTesting
    ViewGroup mScreenDecorHwcWindow;
    @VisibleForTesting
    ScreenDecorHwcLayer mScreenDecorHwcLayer;
    private WindowManager mWindowManager;
    private int mRotation;
    private SettingObserver mColorInversionSetting;
    private DelayableExecutor mExecutor;
    private Handler mHandler;
    boolean mPendingConfigChange;
    @VisibleForTesting
    String mDisplayUniqueId;
    private int mTintColor = Color.BLACK;
    @VisibleForTesting
    protected DisplayDecorationSupport mHwcScreenDecorationSupport;
    private Display.Mode mDisplayMode;
    @VisibleForTesting
    protected DisplayInfo mDisplayInfo = new DisplayInfo();

    @VisibleForTesting
    protected void showCameraProtection(@NonNull Path protectionPath, @NonNull Rect bounds) {
        if (mFaceScanningFactory.shouldShowFaceScanningAnim()) {
            DisplayCutoutView overlay = (DisplayCutoutView) getOverlayView(
                    mFaceScanningViewId);
            if (overlay != null) {
                overlay.setProtection(protectionPath, bounds);
                overlay.enableShowProtection(true);
                updateOverlayWindowVisibilityIfViewExists(
                        overlay.findViewById(mFaceScanningViewId));
                // immediately return, bc FaceScanningOverlay also renders the camera
                // protection, so we don't need to show the camera protection in
                // mScreenDecorHwcLayer or mCutoutViews
                return;
            }
        }

        if (mScreenDecorHwcLayer != null) {
            mScreenDecorHwcLayer.setProtection(protectionPath, bounds);
            mScreenDecorHwcLayer.enableShowProtection(true);
            return;
        }

        if (mCutoutViews == null) {
            Log.w(TAG, "DisplayCutoutView not initialized onApplyCameraProtection");
            return;
        }

        // Show the extra protection around the front facing camera if necessary
        for (DisplayCutoutView dcv : mCutoutViews) {
            // Check Null since not all mCutoutViews[pos] be inflated at the meanwhile
            if (dcv != null) {
                dcv.setProtection(protectionPath, bounds);
                dcv.enableShowProtection(true);
            }
        }
    }

    @VisibleForTesting
    protected void hideCameraProtection() {
        FaceScanningOverlay faceScanningOverlay =
                (FaceScanningOverlay) getOverlayView(mFaceScanningViewId);
        if (faceScanningOverlay != null) {
            faceScanningOverlay.setHideOverlayRunnable(() -> {
                updateOverlayWindowVisibilityIfViewExists(
                        faceScanningOverlay.findViewById(mFaceScanningViewId));
            });
            faceScanningOverlay.enableShowProtection(false);
        }

        if (mScreenDecorHwcLayer != null) {
            mScreenDecorHwcLayer.enableShowProtection(false);
            return;
        }

        if (mCutoutViews == null) {
            Log.w(TAG, "DisplayCutoutView not initialized onHideCameraProtection");
            return;
        }
        // Go back to the regular anti-aliasing
        for (DisplayCutoutView dcv : mCutoutViews) {
            // Check Null since not all mCutoutViews[pos] be inflated at the meanwhile
            if (dcv != null) {
                dcv.enableShowProtection(false);
            }
        }
    }

    private CameraAvailabilityListener.CameraTransitionCallback mCameraTransitionCallback =
            new CameraAvailabilityListener.CameraTransitionCallback() {
        @Override
        public void onApplyCameraProtection(@NonNull Path protectionPath, @NonNull Rect bounds) {
            showCameraProtection(protectionPath, bounds);
        }

        @Override
        public void onHideCameraProtection() {
            hideCameraProtection();
        }
    };

    @VisibleForTesting
    PrivacyDotViewController.ShowingListener mPrivacyDotShowingListener =
            new PrivacyDotViewController.ShowingListener() {
        @Override
        public void onPrivacyDotShown(@Nullable View v) {
            updateOverlayWindowVisibilityIfViewExists(v);
        }

        @Override
        public void onPrivacyDotHidden(@Nullable View v) {
            updateOverlayWindowVisibilityIfViewExists(v);
        }
    };

    @VisibleForTesting
    protected void updateOverlayWindowVisibilityIfViewExists(@Nullable View view) {
        if (view == null) {
            return;
        }
        mExecutor.execute(() -> {
            // We don't need to control the window visibility if rounded corners or cutout is drawn
            // on sw layer since the overlay windows are always visible in this case.
            if (mOverlays == null || !shouldOptimizeVisibility()) {
                return;
            }

            for (final OverlayWindow overlay : mOverlays) {
                if (overlay == null) {
                    continue;
                }
                if (overlay.getView(view.getId()) != null) {
                    overlay.getRootView().setVisibility(getWindowVisibility(overlay, true));
                    return;
                }
            }
        });
    }

    private static boolean eq(DisplayDecorationSupport a, DisplayDecorationSupport b) {
        if (a == null) return (b == null);
        if (b == null) return false;
        return a.format == b.format && a.alphaInterpretation == b.alphaInterpretation;
    }

    @Inject
    public ScreenDecorations(Context context,
            @Main Executor mainExecutor,
            SecureSettings secureSettings,
            BroadcastDispatcher broadcastDispatcher,
            TunerService tunerService,
            UserTracker userTracker,
            PrivacyDotViewController dotViewController,
            ThreadFactory threadFactory,
            PrivacyDotDecorProviderFactory dotFactory,
            FaceScanningProviderFactory faceScanningFactory) {
        super(context);
        mMainExecutor = mainExecutor;
        mSecureSettings = secureSettings;
        mBroadcastDispatcher = broadcastDispatcher;
        mTunerService = tunerService;
        mUserTracker = userTracker;
        mDotViewController = dotViewController;
        mThreadFactory = threadFactory;
        mDotFactory = dotFactory;
        mFaceScanningFactory = faceScanningFactory;
        mFaceScanningViewId = com.android.systemui.R.id.face_scanning_anim;
    }

    @Override
    public void start() {
        if (DEBUG_DISABLE_SCREEN_DECORATIONS) {
            Log.i(TAG, "ScreenDecorations is disabled");
            return;
        }
        mHandler = mThreadFactory.buildHandlerOnNewThread("ScreenDecorations");
        mExecutor = mThreadFactory.buildDelayableExecutorOnHandler(mHandler);
        mExecutor.execute(this::startOnScreenDecorationsThread);
        mDotViewController.setUiExecutor(mExecutor);
    }

    private boolean isPrivacyDotEnabled() {
        return mDotFactory.getHasProviders();
    }

    @NonNull
    private List<DecorProvider> getProviders(boolean hasHwLayer) {
        List<DecorProvider> decorProviders = new ArrayList<>(mDotFactory.getProviders());
        decorProviders.addAll(mFaceScanningFactory.getProviders());
        if (!hasHwLayer) {
            decorProviders.addAll(mRoundedCornerFactory.getProviders());
        }
        return decorProviders;
    }

    /**
     * Check that newProviders is the same list with decorProviders inside mOverlay.
     * @param newProviders expected comparing DecorProviders
     * @return true if same provider list
     */
    @VisibleForTesting
    boolean hasSameProviders(@NonNull List<DecorProvider> newProviders) {
        final ArrayList<Integer> overlayViewIds = new ArrayList<>();
        if (mOverlays != null) {
            for (OverlayWindow overlay : mOverlays) {
                if (overlay == null) {
                    continue;
                }
                overlayViewIds.addAll(overlay.getViewIds());
            }
        }
        if (overlayViewIds.size() != newProviders.size()) {
            return false;
        }

        for (DecorProvider provider: newProviders) {
            if (!overlayViewIds.contains(provider.getViewId())) {
                return false;
            }
        }
        return true;
    }

    private void startOnScreenDecorationsThread() {
        mWindowManager = mContext.getSystemService(WindowManager.class);
        mDisplayManager = mContext.getSystemService(DisplayManager.class);
        mContext.getDisplay().getDisplayInfo(mDisplayInfo);
        mRotation = mDisplayInfo.rotation;
        mDisplayMode = mDisplayInfo.getMode();
        mDisplayUniqueId = mDisplayInfo.uniqueId;
        mRoundedCornerResDelegate = new RoundedCornerResDelegate(mContext.getResources(),
                mDisplayUniqueId);
        mRoundedCornerResDelegate.setPhysicalPixelDisplaySizeRatio(
                getPhysicalPixelDisplaySizeRatio());
        mRoundedCornerFactory = new RoundedCornerDecorProviderFactory(mRoundedCornerResDelegate);
        mHwcScreenDecorationSupport = mContext.getDisplay().getDisplayDecorationSupport();
        updateHwLayerRoundedCornerDrawable();
        setupDecorations();
        setupCameraListener();

        mDisplayListener = new DisplayManager.DisplayListener() {
            @Override
            public void onDisplayAdded(int displayId) {
                // do nothing
            }

            @Override
            public void onDisplayRemoved(int displayId) {
                // do nothing
            }

            @Override
            public void onDisplayChanged(int displayId) {
                mContext.getDisplay().getDisplayInfo(mDisplayInfo);
                final int newRotation = mDisplayInfo.rotation;
                final Display.Mode newDisplayMode = mDisplayInfo.getMode();
                if ((mOverlays != null || mScreenDecorHwcWindow != null)
                        && (mRotation != newRotation
                        || displayModeChanged(mDisplayMode, newDisplayMode))) {
                    // We cannot immediately update the orientation. Otherwise
                    // WindowManager is still deferring layout until it has finished dispatching
                    // the config changes, which may cause divergence between what we draw
                    // (new orientation), and where we are placed on the screen (old orientation).
                    // Instead we wait until either:
                    // - we are trying to redraw. This because WM resized our window and told us to.
                    // - the config change has been dispatched, so WM is no longer deferring layout.
                    mPendingConfigChange = true;
                    if (DEBUG) {
                        if (mRotation != newRotation) {
                            Log.i(TAG, "Rotation changed, deferring " + newRotation
                                            + ", staying at " + mRotation);
                        }
                        if (displayModeChanged(mDisplayMode, newDisplayMode)) {
                            Log.i(TAG, "Resolution changed, deferring " + newDisplayMode
                                    + ", staying at " + mDisplayMode);
                        }
                    }

                    if (mOverlays != null) {
                        for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
                            if (mOverlays[i] != null) {
                                final ViewGroup overlayView = mOverlays[i].getRootView();
                                overlayView.getViewTreeObserver().addOnPreDrawListener(
                                        new RestartingPreDrawListener(
                                                overlayView, i, newRotation, newDisplayMode));
                            }
                        }
                    }

                    if (mScreenDecorHwcWindow != null) {
                        mScreenDecorHwcWindow.getViewTreeObserver().addOnPreDrawListener(
                                new RestartingPreDrawListener(
                                        mScreenDecorHwcWindow,
                                        -1, // Pass -1 for views with no specific position.
                                        newRotation, newDisplayMode));
                    }
                    if (mScreenDecorHwcLayer != null) {
                        mScreenDecorHwcLayer.pendingConfigChange = true;
                    }
                }

                final String newUniqueId = mDisplayInfo.uniqueId;
                if (!Objects.equals(newUniqueId, mDisplayUniqueId)) {
                    mDisplayUniqueId = newUniqueId;
                    final DisplayDecorationSupport newScreenDecorationSupport =
                            mContext.getDisplay().getDisplayDecorationSupport();

                    mRoundedCornerResDelegate.updateDisplayUniqueId(newUniqueId, null);

                    // When providers or the value of mSupportHwcScreenDecoration is changed,
                    // re-setup the whole screen decoration.
                    if (!hasSameProviders(getProviders(newScreenDecorationSupport != null))
                            || !eq(newScreenDecorationSupport, mHwcScreenDecorationSupport)) {
                        mHwcScreenDecorationSupport = newScreenDecorationSupport;
                        removeAllOverlays();
                        setupDecorations();
                        return;
                    }

                    if (mScreenDecorHwcLayer != null) {
                        updateHwLayerRoundedCornerDrawable();
                        updateHwLayerRoundedCornerExistAndSize();
                    }

                    updateOverlayProviderViews();
                }

                final float newRatio = getPhysicalPixelDisplaySizeRatio();
                if (mRoundedCornerResDelegate.getPhysicalPixelDisplaySizeRatio() != newRatio) {
                    mRoundedCornerResDelegate.setPhysicalPixelDisplaySizeRatio(newRatio);
                    if (mScreenDecorHwcLayer != null) {
                        updateHwLayerRoundedCornerExistAndSize();
                    }
                    updateOverlayProviderViews();
                }

                if (mCutoutViews != null) {
                    final int size = mCutoutViews.length;
                    for (int i = 0; i < size; i++) {
                        final DisplayCutoutView cutoutView = mCutoutViews[i];
                        if (cutoutView == null) {
                            continue;
                        }
                        cutoutView.onDisplayChanged(displayId);
                    }
                }
                if (mScreenDecorHwcLayer != null) {
                    mScreenDecorHwcLayer.onDisplayChanged(displayId);
                }
            }
        };

        mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
        updateConfiguration();
    }

    @Nullable
    private View getOverlayView(@IdRes int id) {
        if (mOverlays == null) {
            return null;
        }

        for (final OverlayWindow overlay : mOverlays) {
            if (overlay == null) {
                continue;
            }
            final View view = overlay.getView(id);
            if (view != null) {
                return view;
            }
        }
        return null;
    }

    private void removeRedundantOverlayViews(@NonNull List<DecorProvider> decorProviders) {
        if (mOverlays == null) {
            return;
        }
        int[] viewIds = decorProviders.stream().mapToInt(DecorProvider::getViewId).toArray();
        for (final OverlayWindow overlay : mOverlays) {
            if (overlay == null) {
                continue;
            }
            overlay.removeRedundantViews(viewIds);
        }
    }

    private void removeOverlayView(@IdRes int id) {
        if (mOverlays == null) {
            return;
        }

        for (final OverlayWindow overlay : mOverlays) {
            if (overlay == null) {
                continue;
            }

            overlay.removeView(id);
        }
    }

    private void setupDecorations() {
        if (hasRoundedCorners() || shouldDrawCutout() || isPrivacyDotEnabled()
                || mFaceScanningFactory.getHasProviders()) {

            List<DecorProvider> decorProviders = getProviders(mHwcScreenDecorationSupport != null);
            removeRedundantOverlayViews(decorProviders);

            if (mHwcScreenDecorationSupport != null) {
                createHwcOverlay();
            } else {
                removeHwcOverlay();
            }

            final DisplayCutout cutout = getCutout();
            final boolean shouldOptimizeVisibility = shouldOptimizeVisibility();
            for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
                if (shouldShowSwLayerCutout(i, cutout)
                        || shouldShowSwLayerFaceScan(i, cutout)
                        || shouldShowSwLayerRoundedCorner(i, cutout)
                        || shouldShowSwLayerPrivacyDot(i, cutout)) {
                    Pair<List<DecorProvider>, List<DecorProvider>> pair =
                            DecorProviderKt.partitionAlignedBound(decorProviders, i);
                    decorProviders = pair.getSecond();
                    createOverlay(i, pair.getFirst(), shouldOptimizeVisibility);
                } else {
                    removeOverlay(i);
                }
            }

            if (shouldOptimizeVisibility) {
                mDotViewController.setShowingListener(mPrivacyDotShowingListener);
            } else {
                mDotViewController.setShowingListener(null);
            }
            final View tl, tr, bl, br;
            if ((tl = getOverlayView(R.id.privacy_dot_top_left_container)) != null
                    && (tr = getOverlayView(R.id.privacy_dot_top_right_container)) != null
                    && (bl = getOverlayView(R.id.privacy_dot_bottom_left_container)) != null
                    && (br = getOverlayView(R.id.privacy_dot_bottom_right_container)) != null) {
                // Overlays have been created, send the dots to the controller
                //TODO: need a better way to do this
                mDotViewController.initialize(tl, tr, bl, br);
            }
        } else {
            removeAllOverlays();
            removeHwcOverlay();
        }

        if (hasOverlays() || hasHwcOverlay()) {
            if (mIsRegistered) {
                return;
            }

            mMainExecutor.execute(() -> mTunerService.addTunable(this, SIZE));

            // Watch color inversion and invert the overlay as needed.
            if (mColorInversionSetting == null) {
                mColorInversionSetting = new SettingObserver(mSecureSettings, mHandler,
                        Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
                        mUserTracker.getUserId()) {
                    @Override
                    protected void handleValueChanged(int value, boolean observedChange) {
                        updateColorInversion(value);
                    }
                };
            }
            mColorInversionSetting.setListening(true);
            mColorInversionSetting.onChange(false);
            updateColorInversion(mColorInversionSetting.getValue());

            IntentFilter filter = new IntentFilter();
            filter.addAction(Intent.ACTION_USER_SWITCHED);
            mBroadcastDispatcher.registerReceiver(mUserSwitchIntentReceiver, filter,
                    mExecutor, UserHandle.ALL);
            mIsRegistered = true;
        } else {
            mMainExecutor.execute(() -> mTunerService.removeTunable(this));

            if (mColorInversionSetting != null) {
                mColorInversionSetting.setListening(false);
            }

            mBroadcastDispatcher.unregisterReceiver(mUserSwitchIntentReceiver);
            mIsRegistered = false;
        }
    }

    @VisibleForTesting
    DisplayCutout getCutout() {
        return mContext.getDisplay().getCutout();
    }

    @VisibleForTesting
    boolean hasOverlays() {
        if (mOverlays == null) {
            return false;
        }

        for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
            if (mOverlays[i] != null) {
                return true;
            }
        }
        mOverlays = null;
        return false;
    }

    private void removeAllOverlays() {
        if (mOverlays == null) {
            return;
        }

        for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
            if (mOverlays[i] != null) {
                removeOverlay(i);
            }
        }
        mOverlays = null;
    }

    private void removeOverlay(@BoundsPosition int pos) {
        if (mOverlays == null || mOverlays[pos] == null) {
            return;
        }
        mWindowManager.removeViewImmediate(mOverlays[pos].getRootView());
        mOverlays[pos] = null;
    }

    @View.Visibility
    private int getWindowVisibility(@NonNull OverlayWindow overlay,
            boolean shouldOptimizeVisibility) {
        if (!shouldOptimizeVisibility) {
            // All overlays have visible views so there's no need to optimize visibility.
            // For example, the rounded corners could exist in each overlay and since the rounded
            // corners are always visible, there's no need to optimize visibility.
            return View.VISIBLE;
        }

        // Optimize if it's just the privacy dot & face scanning animation, since the privacy
        // dot and face scanning overlay aren't always visible.
        int[] ids = {
                R.id.privacy_dot_top_left_container,
                R.id.privacy_dot_top_right_container,
                R.id.privacy_dot_bottom_left_container,
                R.id.privacy_dot_bottom_right_container,
                mFaceScanningViewId
        };
        for (int id: ids) {
            final View notAlwaysVisibleViews = overlay.getView(id);
            if (notAlwaysVisibleViews != null
                    && notAlwaysVisibleViews.getVisibility() == View.VISIBLE) {
                // Overlay is VISIBLE if one the views inside this overlay is VISIBLE
                return View.VISIBLE;
            }
        }

        // Only non-visible views in this overlay, so set overlay to INVISIBLE
        return View.INVISIBLE;
    }

    private void createOverlay(
            @BoundsPosition int pos,
            @NonNull List<DecorProvider> decorProviders,
            boolean shouldOptimizeVisibility) {
        if (mOverlays == null) {
            mOverlays = new OverlayWindow[BOUNDS_POSITION_LENGTH];
        }

        if (mOverlays[pos] != null) {
            initOverlay(mOverlays[pos], decorProviders, shouldOptimizeVisibility);
            return;
        }
        mOverlays[pos] = new OverlayWindow(mContext);
        initOverlay(mOverlays[pos], decorProviders, shouldOptimizeVisibility);
        final ViewGroup overlayView = mOverlays[pos].getRootView();
        overlayView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
        overlayView.setAlpha(0);
        overlayView.setForceDarkAllowed(false);

        // Only show cutout in mOverlays when hwc doesn't support screen decoration
        if (mHwcScreenDecorationSupport == null) {
            if (mCutoutViews == null) {
                mCutoutViews = new DisplayCutoutView[BOUNDS_POSITION_LENGTH];
            }
            mCutoutViews[pos] = new DisplayCutoutView(mContext, pos);
            overlayView.addView(mCutoutViews[pos]);
            mCutoutViews[pos].updateRotation(mRotation);
        }

        mWindowManager.addView(overlayView, getWindowLayoutParams(pos));

        overlayView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
            @Override
            public void onLayoutChange(View v, int left, int top, int right, int bottom,
                    int oldLeft, int oldTop, int oldRight, int oldBottom) {
                overlayView.removeOnLayoutChangeListener(this);
                overlayView.animate()
                        .alpha(1)
                        .setDuration(1000)
                        .start();
            }
        });

        overlayView.getRootView().getViewTreeObserver().addOnPreDrawListener(
                new ValidatingPreDrawListener(overlayView.getRootView()));
    }

    private boolean hasHwcOverlay() {
        return mScreenDecorHwcWindow != null;
    }

    private void removeHwcOverlay() {
        if (mScreenDecorHwcWindow == null) {
            return;
        }
        mWindowManager.removeViewImmediate(mScreenDecorHwcWindow);
        mScreenDecorHwcWindow = null;
        mScreenDecorHwcLayer = null;
    }

    private void createHwcOverlay() {
        if (mScreenDecorHwcWindow != null) {
            return;
        }
        mScreenDecorHwcWindow = (ViewGroup) LayoutInflater.from(mContext).inflate(
                R.layout.screen_decor_hwc_layer, null);
        mScreenDecorHwcLayer = new ScreenDecorHwcLayer(mContext, mHwcScreenDecorationSupport);
        mScreenDecorHwcWindow.addView(mScreenDecorHwcLayer, new FrameLayout.LayoutParams(
                MATCH_PARENT, MATCH_PARENT, Gravity.TOP | Gravity.START));
        mWindowManager.addView(mScreenDecorHwcWindow, getHwcWindowLayoutParams());
        updateHwLayerRoundedCornerExistAndSize();
        updateHwLayerRoundedCornerDrawable();
        mScreenDecorHwcWindow.getViewTreeObserver().addOnPreDrawListener(
                new ValidatingPreDrawListener(mScreenDecorHwcWindow));
    }

    /**
     * Init OverlayWindow with decorProviders
     */
    private void initOverlay(
            @NonNull OverlayWindow overlay,
            @NonNull List<DecorProvider> decorProviders,
            boolean shouldOptimizeVisibility) {
        if (!overlay.hasSameProviders(decorProviders)) {
            decorProviders.forEach(provider -> {
                if (overlay.getView(provider.getViewId()) != null) {
                    return;
                }
                removeOverlayView(provider.getViewId());
                overlay.addDecorProvider(provider, mRotation);
            });
        }
        // Use visibility of privacy dot views & face scanning view to determine the overlay's
        // visibility if the screen decoration SW layer overlay isn't persistenly showing
        // (ie: rounded corners always showing in SW layer)
        overlay.getRootView().setVisibility(getWindowVisibility(overlay, shouldOptimizeVisibility));
    }

    @VisibleForTesting
    WindowManager.LayoutParams getWindowLayoutParams(@BoundsPosition int pos) {
        final WindowManager.LayoutParams lp = getWindowLayoutBaseParams();
        lp.width = getWidthLayoutParamByPos(pos);
        lp.height = getHeightLayoutParamByPos(pos);
        lp.setTitle(getWindowTitleByPos(pos));
        lp.gravity = getOverlayWindowGravity(pos);
        return lp;
    }

    private WindowManager.LayoutParams getHwcWindowLayoutParams() {
        final WindowManager.LayoutParams lp = getWindowLayoutBaseParams();
        lp.width = MATCH_PARENT;
        lp.height = MATCH_PARENT;
        lp.setTitle("ScreenDecorHwcOverlay");
        lp.gravity = Gravity.TOP | Gravity.START;
        if (!DEBUG_COLOR) {
            lp.setColorMode(ActivityInfo.COLOR_MODE_A8);
        }
        return lp;
    }

    private WindowManager.LayoutParams getWindowLayoutBaseParams() {
        final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
                        | WindowManager.LayoutParams.FLAG_SLIPPERY
                        | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
                PixelFormat.TRANSLUCENT);
        lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS
                | WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;

        // FLAG_SLIPPERY can only be set by trusted overlays
        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;

        if (!DEBUG_SCREENSHOT_ROUNDED_CORNERS) {
            lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
        }

        lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
        lp.setFitInsetsTypes(0 /* types */);
        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
        return lp;
    }

    private int getWidthLayoutParamByPos(@BoundsPosition int pos) {
        final int rotatedPos = getBoundPositionFromRotation(pos, mRotation);
        return rotatedPos == BOUNDS_POSITION_TOP || rotatedPos == BOUNDS_POSITION_BOTTOM
                ? MATCH_PARENT : WRAP_CONTENT;
    }

    private int getHeightLayoutParamByPos(@BoundsPosition int pos) {
        final int rotatedPos = getBoundPositionFromRotation(pos, mRotation);
        return rotatedPos == BOUNDS_POSITION_TOP || rotatedPos == BOUNDS_POSITION_BOTTOM
                ? WRAP_CONTENT : MATCH_PARENT;
    }

    private static String getWindowTitleByPos(@BoundsPosition int pos) {
        switch (pos) {
            case BOUNDS_POSITION_LEFT:
                return "ScreenDecorOverlayLeft";
            case BOUNDS_POSITION_TOP:
                return "ScreenDecorOverlay";
            case BOUNDS_POSITION_RIGHT:
                return "ScreenDecorOverlayRight";
            case BOUNDS_POSITION_BOTTOM:
                return "ScreenDecorOverlayBottom";
            default:
                throw new IllegalArgumentException("unknown bound position: " + pos);
        }
    }

    private static boolean displayModeChanged(Display.Mode oldMode, Display.Mode newMode) {
        if (oldMode == null) {
            return true;
        }

        // We purposely ignore refresh rate and id changes here, because we don't need to
        // invalidate for those, and they can trigger the refresh rate to increase
        return oldMode.getPhysicalWidth() != newMode.getPhysicalWidth()
                || oldMode.getPhysicalHeight() != newMode.getPhysicalHeight();
    }

    private int getOverlayWindowGravity(@BoundsPosition int pos) {
        final int rotated = getBoundPositionFromRotation(pos, mRotation);
        switch (rotated) {
            case BOUNDS_POSITION_TOP:
                return Gravity.TOP;
            case BOUNDS_POSITION_BOTTOM:
                return Gravity.BOTTOM;
            case BOUNDS_POSITION_LEFT:
                return Gravity.LEFT;
            case BOUNDS_POSITION_RIGHT:
                return Gravity.RIGHT;
            default:
                throw new IllegalArgumentException("unknown bound position: " + pos);
        }
    }

    @VisibleForTesting
    static int getBoundPositionFromRotation(@BoundsPosition int pos, int rotation) {
        return (pos - rotation) < 0
                ? pos - rotation + DisplayCutout.BOUNDS_POSITION_LENGTH
                : pos - rotation;
    }

    private void setupCameraListener() {
        Resources res = mContext.getResources();
        boolean enabled = res.getBoolean(R.bool.config_enableDisplayCutoutProtection);
        if (enabled) {
            mCameraListener = CameraAvailabilityListener.Factory.build(mContext, mExecutor);
            mCameraListener.addTransitionCallback(mCameraTransitionCallback);
            mCameraListener.startListening();
        }
    }

    private final BroadcastReceiver mUserSwitchIntentReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            int newUserId = ActivityManager.getCurrentUser();
            if (DEBUG) {
                Log.d(TAG, "UserSwitched newUserId=" + newUserId);
            }
            // update color inversion setting to the new user
            mColorInversionSetting.setUserId(newUserId);
            updateColorInversion(mColorInversionSetting.getValue());
        }
    };

    private void updateColorInversion(int colorsInvertedValue) {
        mTintColor = colorsInvertedValue != 0 ? Color.WHITE : Color.BLACK;
        if (DEBUG_COLOR) {
            mTintColor = Color.RED;
        }

        if (mOverlays == null) {
            return;
        }

        // When the hwc supports screen decorations, the layer will use the A8 color mode which
        // won't be affected by the color inversion. If the composition goes the client composition
        // route, the color inversion will be handled by the RenderEngine.
        final Set<Integer> viewsMayNeedColorUpdate = new HashSet<>();
        if (mHwcScreenDecorationSupport == null) {
            ColorStateList tintList = ColorStateList.valueOf(mTintColor);
            mRoundedCornerResDelegate.setColorTintList(tintList);
            viewsMayNeedColorUpdate.add(R.id.rounded_corner_top_left);
            viewsMayNeedColorUpdate.add(R.id.rounded_corner_top_right);
            viewsMayNeedColorUpdate.add(R.id.rounded_corner_bottom_left);
            viewsMayNeedColorUpdate.add(R.id.rounded_corner_bottom_right);
            viewsMayNeedColorUpdate.add(R.id.display_cutout);
        }
        if (mFaceScanningFactory.getHasProviders()) {
            viewsMayNeedColorUpdate.add(mFaceScanningViewId);
        }
        final Integer[] views = new Integer[viewsMayNeedColorUpdate.size()];
        viewsMayNeedColorUpdate.toArray(views);
        for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
            if (mOverlays[i] == null) {
                continue;
            }
            final ViewGroup overlayView = mOverlays[i].getRootView();
            final int size = overlayView.getChildCount();
            View child;
            for (int j = 0; j < size; j++) {
                child = overlayView.getChildAt(j);
                if (viewsMayNeedColorUpdate.contains(child.getId())
                        && child instanceof DisplayCutoutView) {
                    ((DisplayCutoutView) child).setColor(mTintColor);
                }
            }
            mOverlays[i].onReloadResAndMeasure(views, mProviderRefreshToken,
                    mRotation, mDisplayUniqueId);
        }
    }

    @VisibleForTesting
    float getPhysicalPixelDisplaySizeRatio() {
        mContext.getDisplay().getDisplayInfo(mDisplayInfo);
        final Display.Mode maxDisplayMode =
                DisplayUtils.getMaximumResolutionDisplayMode(mDisplayInfo.supportedModes);
        if (maxDisplayMode == null) {
            return 1f;
        }
        return DisplayUtils.getPhysicalPixelDisplaySizeRatio(
                maxDisplayMode.getPhysicalWidth(), maxDisplayMode.getPhysicalHeight(),
                mDisplayInfo.getNaturalWidth(), mDisplayInfo.getNaturalHeight());
    }

    @Override
    protected void onConfigurationChanged(Configuration newConfig) {
        if (DEBUG_DISABLE_SCREEN_DECORATIONS) {
            Log.i(TAG, "ScreenDecorations is disabled");
            return;
        }

        mExecutor.execute(() -> {
            int oldRotation = mRotation;
            mPendingConfigChange = false;
            updateConfiguration();
            if (DEBUG) Log.i(TAG, "onConfigChanged from rot " + oldRotation + " to " + mRotation);
            setupDecorations();
            if (mOverlays != null) {
                // Updating the layout params ensures that ViewRootImpl will call relayoutWindow(),
                // which ensures that the forced seamless rotation will end, even if we updated
                // the rotation before window manager was ready (and was still waiting for sending
                // the updated rotation).
                updateLayoutParams();
            }
        });
    }

    private static String alphaInterpretationToString(int alpha) {
        switch (alpha) {
            case AlphaInterpretation.COVERAGE: return "COVERAGE";
            case AlphaInterpretation.MASK:     return "MASK";
            default:                           return "Unknown: " + alpha;
        }
    }

    @Override
    public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
        pw.println("ScreenDecorations state:");
        pw.println("  DEBUG_DISABLE_SCREEN_DECORATIONS:" + DEBUG_DISABLE_SCREEN_DECORATIONS);
        if (DEBUG_DISABLE_SCREEN_DECORATIONS) {
            return;
        }

        pw.println("  mIsPrivacyDotEnabled:" + isPrivacyDotEnabled());
        pw.println("  shouldOptimizeOverlayVisibility:" + shouldOptimizeVisibility());
        final boolean supportsShowingFaceScanningAnim = mFaceScanningFactory.getHasProviders();
        pw.println("    supportsShowingFaceScanningAnim:" + supportsShowingFaceScanningAnim);
        if (supportsShowingFaceScanningAnim) {
            pw.println("      canShowFaceScanningAnim:"
                    + mFaceScanningFactory.canShowFaceScanningAnim());
            pw.println("      shouldShowFaceScanningAnim (at time dump was taken):"
                    + mFaceScanningFactory.shouldShowFaceScanningAnim());
        }
        pw.println("  mPendingConfigChange:" + mPendingConfigChange);
        if (mHwcScreenDecorationSupport != null) {
            pw.println("  mHwcScreenDecorationSupport:");
            pw.println("    format="
                    + PixelFormat.formatToString(mHwcScreenDecorationSupport.format));
            pw.println("    alphaInterpretation="
                    + alphaInterpretationToString(mHwcScreenDecorationSupport.alphaInterpretation));
        } else {
            pw.println("  mHwcScreenDecorationSupport: null");
        }
        if (mScreenDecorHwcLayer != null) {
            pw.println("  mScreenDecorHwcLayer:");
            pw.println("    transparentRegion=" + mScreenDecorHwcLayer.transparentRect);
        } else {
            pw.println("  mScreenDecorHwcLayer: null");
        }
        if (mOverlays != null) {
            pw.println("  mOverlays(left,top,right,bottom)=("
                    + (mOverlays[BOUNDS_POSITION_LEFT] != null) + ","
                    + (mOverlays[BOUNDS_POSITION_TOP] != null) + ","
                    + (mOverlays[BOUNDS_POSITION_RIGHT] != null) + ","
                    + (mOverlays[BOUNDS_POSITION_BOTTOM] != null) + ")");

            for (int i = BOUNDS_POSITION_LEFT; i < BOUNDS_POSITION_LENGTH; i++) {
                if (mOverlays[i] != null) {
                    mOverlays[i].dump(pw, getWindowTitleByPos(i));
                }
            }
        }
        mRoundedCornerResDelegate.dump(pw, args);
    }

    private void updateConfiguration() {
        Preconditions.checkState(mHandler.getLooper().getThread() == Thread.currentThread(),
                "must call on " + mHandler.getLooper().getThread()
                        + ", but was " + Thread.currentThread());

        mContext.getDisplay().getDisplayInfo(mDisplayInfo);
        final int newRotation = mDisplayInfo.rotation;
        if (mRotation != newRotation) {
            mDotViewController.setNewRotation(newRotation);
        }
        final Display.Mode newMod = mDisplayInfo.getMode();

        if (!mPendingConfigChange
                && (newRotation != mRotation || displayModeChanged(mDisplayMode, newMod))) {
            mRotation = newRotation;
            mDisplayMode = newMod;
            if (mScreenDecorHwcLayer != null) {
                mScreenDecorHwcLayer.pendingConfigChange = false;
                mScreenDecorHwcLayer.updateRotation(mRotation);
                updateHwLayerRoundedCornerExistAndSize();
                updateHwLayerRoundedCornerDrawable();
            }
            updateLayoutParams();
            // update cutout view rotation
            if (mCutoutViews != null) {
                for (final DisplayCutoutView cutoutView: mCutoutViews) {
                    if (cutoutView == null) {
                        continue;
                    }
                    cutoutView.updateRotation(mRotation);
                }
            }

            // update all provider views inside overlay
            updateOverlayProviderViews();
        }

        if (mFaceScanningFactory.getHasProviders()) {
            FaceScanningOverlay faceScanningOverlay =
                    (FaceScanningOverlay) getOverlayView(mFaceScanningViewId);
            if (faceScanningOverlay != null) {
                faceScanningOverlay.setFaceScanningAnimColor(
                        Utils.getColorAttrDefaultColor(faceScanningOverlay.getContext(),
                                com.android.systemui.R.attr.wallpaperTextColorAccent));
            }
        }
    }

    private boolean hasRoundedCorners() {
        return mRoundedCornerFactory.getHasProviders();
    }

    private boolean isDefaultShownOverlayPos(@BoundsPosition int pos,
            @Nullable DisplayCutout cutout) {
        // for cutout is null or cutout with only waterfall.
        final boolean emptyBoundsOrWaterfall = cutout == null || cutout.isBoundsEmpty();
        // Shows rounded corner on left and right overlays only when there is no top or bottom
        // cutout.
        final int rotatedTop = getBoundPositionFromRotation(BOUNDS_POSITION_TOP, mRotation);
        final int rotatedBottom = getBoundPositionFromRotation(BOUNDS_POSITION_BOTTOM, mRotation);
        if (emptyBoundsOrWaterfall || !cutout.getBoundingRectsAll()[rotatedTop].isEmpty()
                || !cutout.getBoundingRectsAll()[rotatedBottom].isEmpty()) {
            return pos == BOUNDS_POSITION_TOP || pos == BOUNDS_POSITION_BOTTOM;
        } else {
            return pos == BOUNDS_POSITION_LEFT || pos == BOUNDS_POSITION_RIGHT;
        }
    }

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

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

    private boolean shouldShowSwLayerFaceScan(@BoundsPosition int pos,
            @Nullable DisplayCutout cutout) {
        return mFaceScanningFactory.getHasProviders() && isDefaultShownOverlayPos(pos, 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()
                && mHwcScreenDecorationSupport == null);
    }

    private boolean shouldOptimizeVisibility() {
        return (isPrivacyDotEnabled() || mFaceScanningFactory.getHasProviders())
                && (mHwcScreenDecorationSupport != null
                    || (!hasRoundedCorners() && !shouldDrawCutout())
                );
    }

    private boolean shouldDrawCutout() {
        return shouldDrawCutout(mContext);
    }

    static boolean shouldDrawCutout(Context context) {
        return DisplayCutout.getFillBuiltInDisplayCutout(
                context.getResources(), context.getDisplay().getUniqueId());
    }

    private void updateOverlayProviderViews() {
        if (mOverlays == null) {
            return;
        }
        ++mProviderRefreshToken;
        for (final OverlayWindow overlay: mOverlays) {
            if (overlay == null) {
                continue;
            }
            overlay.onReloadResAndMeasure(null, mProviderRefreshToken, mRotation, mDisplayUniqueId);
        }
    }

    private void updateLayoutParams() {
        //ToDo: We should skip unnecessary call to update view layout.
        Trace.beginSection("ScreenDecorations#updateLayoutParams");
        if (mScreenDecorHwcWindow != null) {
            mWindowManager.updateViewLayout(mScreenDecorHwcWindow, getHwcWindowLayoutParams());
        }

        if (mOverlays != null) {
            for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
                if (mOverlays[i] == null) {
                    continue;
                }
                mWindowManager.updateViewLayout(
                        mOverlays[i].getRootView(), getWindowLayoutParams(i));
            }
        }
        Trace.endSection();
    }

    @Override
    public void onTuningChanged(String key, String newValue) {
        if (DEBUG_DISABLE_SCREEN_DECORATIONS) {
            Log.i(TAG, "ScreenDecorations is disabled");
            return;
        }
        mExecutor.execute(() -> {
            if (mOverlays == null || !SIZE.equals(key)) {
                return;
            }
            try {
                final int sizeFactor = Integer.parseInt(newValue);
                mRoundedCornerResDelegate.setTuningSizeFactor(sizeFactor);
            } catch (NumberFormatException e) {
                mRoundedCornerResDelegate.setTuningSizeFactor(null);
            }
            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;
                }
                overlay.onReloadResAndMeasure(filterIds, mProviderRefreshToken, mRotation,
                        mDisplayUniqueId);
            }
            updateHwLayerRoundedCornerExistAndSize();
        });
    }

    private void updateHwLayerRoundedCornerDrawable() {
        if (mScreenDecorHwcLayer == null) {
            return;
        }

        final Drawable topDrawable = mRoundedCornerResDelegate.getTopRoundedDrawable();
        final Drawable bottomDrawable = mRoundedCornerResDelegate.getBottomRoundedDrawable();

        if (topDrawable == null || bottomDrawable == null) {
            return;
        }
        mScreenDecorHwcLayer.updateRoundedCornerDrawable(topDrawable, bottomDrawable);
    }

    private void updateHwLayerRoundedCornerExistAndSize() {
        if (mScreenDecorHwcLayer == null) {
            return;
        }
        mScreenDecorHwcLayer.updateRoundedCornerExistenceAndSize(
                mRoundedCornerResDelegate.getHasTop(),
                mRoundedCornerResDelegate.getHasBottom(),
                mRoundedCornerResDelegate.getTopRoundedSize().getWidth(),
                mRoundedCornerResDelegate.getBottomRoundedSize().getWidth());
    }

    @VisibleForTesting
    protected void setSize(View view, Size pixelSize) {
        LayoutParams params = view.getLayoutParams();
        params.width = pixelSize.getWidth();
        params.height = pixelSize.getHeight();
        view.setLayoutParams(params);
    }

    public static class DisplayCutoutView extends DisplayCutoutBaseView {
        final List<Rect> mBounds = new ArrayList();
        final Rect mBoundingRect = new Rect();
        Rect mTotalBounds = new Rect();

        private int mColor = Color.BLACK;
        private int mRotation;
        private int mInitialPosition;
        private int mPosition;

        public DisplayCutoutView(Context context, @BoundsPosition int pos) {
            super(context);
            mInitialPosition = pos;

            paint.setColor(mColor);
            paint.setStyle(Paint.Style.FILL);
            setId(R.id.display_cutout);
            if (DEBUG) {
                getViewTreeObserver().addOnDrawListener(() -> Log.i(TAG,
                        getWindowTitleByPos(pos) + " drawn in rot " + mRotation));
            }
        }

        public void setColor(int color) {
            mColor = color;
            paint.setColor(mColor);
            invalidate();
        }

        @Override
        public void updateRotation(int rotation) {
            mRotation = rotation;
            super.updateRotation(rotation);
        }

        @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
        @Override
        public void updateCutout() {
            if (!isAttachedToWindow() || pendingConfigChange) {
                return;
            }
            mPosition = getBoundPositionFromRotation(mInitialPosition, mRotation);
            requestLayout();
            getDisplay().getDisplayInfo(displayInfo);
            mBounds.clear();
            mBoundingRect.setEmpty();
            cutoutPath.reset();
            int newVisible;
            if (shouldDrawCutout(getContext()) && hasCutout()) {
                mBounds.addAll(displayInfo.displayCutout.getBoundingRects());
                localBounds(mBoundingRect);
                updateGravity();
                updateBoundingPath();
                invalidate();
                newVisible = VISIBLE;
            } else {
                newVisible = GONE;
            }
            if (newVisible != getVisibility()) {
                setVisibility(newVisible);
            }
        }

        private void updateBoundingPath() {
            final Path path = displayInfo.displayCutout.getCutoutPath();
            if (path != null) {
                cutoutPath.set(path);
            } else {
                cutoutPath.reset();
            }
        }

        private void updateGravity() {
            LayoutParams lp = getLayoutParams();
            if (lp instanceof FrameLayout.LayoutParams) {
                FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) lp;
                int newGravity = getGravity(displayInfo.displayCutout);
                if (flp.gravity != newGravity) {
                    flp.gravity = newGravity;
                    setLayoutParams(flp);
                }
            }
        }

        private boolean hasCutout() {
            final DisplayCutout displayCutout = displayInfo.displayCutout;
            if (displayCutout == null) {
                return false;
            }

            if (mPosition == BOUNDS_POSITION_LEFT) {
                return !displayCutout.getBoundingRectLeft().isEmpty();
            } else if (mPosition == BOUNDS_POSITION_TOP) {
                return !displayCutout.getBoundingRectTop().isEmpty();
            } else if (mPosition == BOUNDS_POSITION_BOTTOM) {
                return !displayCutout.getBoundingRectBottom().isEmpty();
            } else if (mPosition == BOUNDS_POSITION_RIGHT) {
                return !displayCutout.getBoundingRectRight().isEmpty();
            }
            return false;
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            if (mBounds.isEmpty()) {
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
                return;
            }

            if (showProtection) {
                // Make sure that our measured height encompasses the protection
                mTotalBounds.union(mBoundingRect);
                mTotalBounds.union((int) protectionRect.left, (int) protectionRect.top,
                        (int) protectionRect.right, (int) protectionRect.bottom);
                setMeasuredDimension(
                        resolveSizeAndState(mTotalBounds.width(), widthMeasureSpec, 0),
                        resolveSizeAndState(mTotalBounds.height(), heightMeasureSpec, 0));
            } else {
                setMeasuredDimension(
                        resolveSizeAndState(mBoundingRect.width(), widthMeasureSpec, 0),
                        resolveSizeAndState(mBoundingRect.height(), heightMeasureSpec, 0));
            }
        }

        public static void boundsFromDirection(DisplayCutout displayCutout, int gravity,
                Rect out) {
            switch (gravity) {
                case Gravity.TOP:
                    out.set(displayCutout.getBoundingRectTop());
                    break;
                case Gravity.LEFT:
                    out.set(displayCutout.getBoundingRectLeft());
                    break;
                case Gravity.BOTTOM:
                    out.set(displayCutout.getBoundingRectBottom());
                    break;
                case Gravity.RIGHT:
                    out.set(displayCutout.getBoundingRectRight());
                    break;
                default:
                    out.setEmpty();
            }
        }

        private void localBounds(Rect out) {
            DisplayCutout displayCutout = displayInfo.displayCutout;
            boundsFromDirection(displayCutout, getGravity(displayCutout), out);
        }

        private int getGravity(DisplayCutout displayCutout) {
            if (mPosition == BOUNDS_POSITION_LEFT) {
                if (!displayCutout.getBoundingRectLeft().isEmpty()) {
                    return Gravity.LEFT;
                }
            } else if (mPosition == BOUNDS_POSITION_TOP) {
                if (!displayCutout.getBoundingRectTop().isEmpty()) {
                    return Gravity.TOP;
                }
            } else if (mPosition == BOUNDS_POSITION_BOTTOM) {
                if (!displayCutout.getBoundingRectBottom().isEmpty()) {
                    return Gravity.BOTTOM;
                }
            } else if (mPosition == BOUNDS_POSITION_RIGHT) {
                if (!displayCutout.getBoundingRectRight().isEmpty()) {
                    return Gravity.RIGHT;
                }
            }
            return Gravity.NO_GRAVITY;
        }
    }

    /**
     * A pre-draw listener, that cancels the draw and restarts the traversal with the updated
     * window attributes.
     */
    private class RestartingPreDrawListener implements ViewTreeObserver.OnPreDrawListener {

        private final View mView;
        private final int mTargetRotation;
        private final Display.Mode mTargetDisplayMode;
        // Pass -1 for ScreenDecorHwcLayer since it's a fullscreen window and has no specific
        // position.
        private final int mPosition;

        private RestartingPreDrawListener(View view, @BoundsPosition int position,
                int targetRotation, Display.Mode targetDisplayMode) {
            mView = view;
            mTargetRotation = targetRotation;
            mTargetDisplayMode = targetDisplayMode;
            mPosition = position;
        }

        @Override
        public boolean onPreDraw() {
            mView.getViewTreeObserver().removeOnPreDrawListener(this);
            if (mTargetRotation == mRotation
                    && !displayModeChanged(mDisplayMode, mTargetDisplayMode)) {
                if (DEBUG) {
                    final String title = mPosition < 0 ? "ScreenDecorHwcLayer"
                            : getWindowTitleByPos(mPosition);
                    Log.i(TAG, title + " already in target rot "
                            + mTargetRotation + " and in target resolution "
                            + mTargetDisplayMode.getPhysicalWidth() + "x"
                            + mTargetDisplayMode.getPhysicalHeight()
                            + ", allow draw without restarting it");
                }
                return true;
            }

            mPendingConfigChange = false;
            // This changes the window attributes - we need to restart the traversal for them to
            // take effect.
            updateConfiguration();
            if (DEBUG) {
                final String title = mPosition < 0 ? "ScreenDecorHwcLayer"
                        : getWindowTitleByPos(mPosition);
                Log.i(TAG, title
                        + " restarting listener fired, restarting draw for rot " + mRotation
                        + ", resolution " + mDisplayMode.getPhysicalWidth() + "x"
                        + mDisplayMode.getPhysicalHeight());
            }
            mView.invalidate();
            return false;
        }
    }

    /**
     * A pre-draw listener, that validates that the rotation and display resolution we draw in
     * matches the display's rotation and resolution before continuing the draw.
     *
     * This is to prevent a race condition, where we have not received the display changed event
     * yet, and would thus draw in an old orientation.
     */
    private class ValidatingPreDrawListener implements ViewTreeObserver.OnPreDrawListener {

        private final View mView;

        public ValidatingPreDrawListener(View view) {
            mView = view;
        }

        @Override
        public boolean onPreDraw() {
            mContext.getDisplay().getDisplayInfo(mDisplayInfo);
            final int displayRotation = mDisplayInfo.rotation;
            final Display.Mode displayMode = mDisplayInfo.getMode();
            if ((displayRotation != mRotation || displayModeChanged(mDisplayMode, displayMode))
                    && !mPendingConfigChange) {
                if (DEBUG) {
                    if (displayRotation != mRotation) {
                        Log.i(TAG, "Drawing rot " + mRotation + ", but display is at rot "
                                + displayRotation + ". Restarting draw");
                    }
                    if (displayModeChanged(mDisplayMode, displayMode)) {
                        Log.i(TAG, "Drawing at " + mDisplayMode.getPhysicalWidth()
                                + "x" + mDisplayMode.getPhysicalHeight() + ", but display is at "
                                + displayMode.getPhysicalWidth() + "x"
                                + displayMode.getPhysicalHeight() + ". Restarting draw");
                    }
                }
                mView.invalidate();
                return false;
            }
            return true;
        }
    }
}
