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

Commit 138686da authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes I3a966bc7,I91e6832d

* changes:
  Adjust window layout for DisplayCutout
  Display Cutout: Add emulation
parents 6e54c901 dcc92eda
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -10163,6 +10163,16 @@ public final class Settings {
         */
        public static final String POLICY_CONTROL = "policy_control";

        /**
         * {@link android.view.DisplayCutout DisplayCutout} emulation mode.
         *
         * @hide
         */
        public static final String EMULATE_DISPLAY_CUTOUT = "emulate_display_cutout";

        /** @hide */ public static final int EMULATE_DISPLAY_CUTOUT_OFF = 0;
        /** @hide */ public static final int EMULATE_DISPLAY_CUTOUT_ON = 1;

        /**
         * Defines global zen mode.  ZEN_MODE_OFF, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
         * or ZEN_MODE_NO_INTERRUPTIONS.
+29 −0
Original line number Diff line number Diff line
@@ -1268,6 +1268,35 @@ public interface WindowManager extends ViewManager {
        }, formatToHexString = true)
        public int flags;

        /** @hide */
        @Retention(RetentionPolicy.SOURCE)
        @IntDef(
            flag = true,
            value = {
                    LayoutParams.FLAG2_LAYOUT_IN_DISPLAY_CUTOUT_AREA,
            })
        @interface Flags2 {}

        /**
         * Window flag: allow placing the window within the area that overlaps with the
         * display cutout.
         *
         * <p>
         * The window must correctly position its contents to take the display cutout into account.
         *
         * @see DisplayCutout
         * @hide for now
         */
        public static final long FLAG2_LAYOUT_IN_DISPLAY_CUTOUT_AREA = 0x00000001;

        /**
         * Various behavioral options/flags.  Default is none.
         *
         * @see #FLAG2_LAYOUT_IN_DISPLAY_CUTOUT_AREA
         * @hide for now
         */
        @Flags2 public long flags2;

        /**
         * If the window has requested hardware acceleration, but this is not
         * allowed in the process it is in, then still render it as if it is
+1 −0
Original line number Diff line number Diff line
@@ -194,6 +194,7 @@ public class SettingsBackupTest {
                    Settings.Global.DROPBOX_RESERVE_PERCENT,
                    Settings.Global.DROPBOX_TAG_PREFIX,
                    Settings.Global.EMERGENCY_AFFORDANCE_NEEDED,
                    Settings.Global.EMULATE_DISPLAY_CUTOUT,
                    Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED,
                    Settings.Global.ENABLE_CACHE_QUOTA_CALCULATION,
                    Settings.Global.ENABLE_CELLULAR_ON_BOOT,
+1 −0
Original line number Diff line number Diff line
@@ -337,6 +337,7 @@
        <item>com.android.systemui.LatencyTester</item>
        <item>com.android.systemui.globalactions.GlobalActionsComponent</item>
        <item>com.android.systemui.RoundedCorners</item>
        <item>com.android.systemui.EmulatedDisplayCutout</item>
    </string-array>

    <!-- SystemUI vender service, used in config_systemUIServiceComponents. -->
+140 −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.systemui;

import android.content.Context;
import android.database.ContentObserver;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.provider.Settings;
import android.view.DisplayCutout;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowInsets;
import android.view.WindowManager;

import java.util.ArrayList;

/**
 * Emulates a display cutout by drawing its shape in an overlay as supplied by
 * {@link DisplayCutout}.
 */
public class EmulatedDisplayCutout extends SystemUI {
    private View mOverlay;
    private boolean mAttached;
    private WindowManager mWindowManager;

    @Override
    public void start() {
        mWindowManager = mContext.getSystemService(WindowManager.class);
        mContext.getContentResolver().registerContentObserver(
                Settings.Global.getUriFor(Settings.Global.EMULATE_DISPLAY_CUTOUT),
                false, mObserver, UserHandle.USER_ALL);
        mObserver.onChange(false);
    }

    private void setAttached(boolean attached) {
        if (attached && !mAttached) {
            if (mOverlay == null) {
                mOverlay = new CutoutView(mContext);
                mOverlay.setLayoutParams(getLayoutParams());
            }
            mWindowManager.addView(mOverlay, mOverlay.getLayoutParams());
            mAttached = true;
        } else if (!attached && mAttached) {
            mWindowManager.removeView(mOverlay);
            mAttached = false;
        }
    }

    private WindowManager.LayoutParams getLayoutParams() {
        final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT,
                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                        | 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
                        | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR,
                PixelFormat.TRANSLUCENT);
        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS
                | WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
        lp.setTitle("EmulatedDisplayCutout");
        lp.gravity = Gravity.TOP;
        return lp;
    }

    private ContentObserver mObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
        @Override
        public void onChange(boolean selfChange) {
            boolean emulateCutout = Settings.Global.getInt(
                    mContext.getContentResolver(), Settings.Global.EMULATE_DISPLAY_CUTOUT,
                    Settings.Global.EMULATE_DISPLAY_CUTOUT_OFF)
                    != Settings.Global.EMULATE_DISPLAY_CUTOUT_OFF;
            setAttached(emulateCutout);
        }
    };

    private static class CutoutView extends View {
        private Paint mPaint = new Paint();
        private Path mPath = new Path();
        private ArrayList<Point> mBoundingPolygon = new ArrayList<>();

        CutoutView(Context context) {
            super(context);
        }

        @Override
        public WindowInsets onApplyWindowInsets(WindowInsets insets) {
            insets.getDisplayCutout().getBoundingPolygon(mBoundingPolygon);
            invalidate();
            return insets.consumeCutout();
        }

        @Override
        protected void onDraw(Canvas canvas) {
            if (!mBoundingPolygon.isEmpty()) {
                mPaint.setColor(Color.DKGRAY);
                mPaint.setStyle(Paint.Style.FILL);

                mPath.reset();
                for (int i = 0; i < mBoundingPolygon.size(); i++) {
                    Point point = mBoundingPolygon.get(i);
                    if (i == 0) {
                        mPath.moveTo(point.x, point.y);
                    } else {
                        mPath.lineTo(point.x, point.y);
                    }
                }
                mPath.close();
                canvas.drawPath(mPath, mPaint);
            }
        }
    }
}
Loading