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

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

Merge changes Iff58235b,I1ea44917

* changes:
  DisplayCutout: account for cutout in appWidth/appHeight etc.
  DisplayCutout: Dispatch all non-zero safeInsets
parents c5d1950f 11c25584
Loading
Loading
Loading
Loading
+64 −41
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ import static android.view.Surface.ROTATION_90;
import android.content.res.Resources;
import android.graphics.Matrix;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
@@ -35,12 +34,13 @@ import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Log;
import android.util.PathParser;
import android.util.Size;
import android.util.proto.ProtoOutputStream;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;

import java.util.List;
import java.util.Objects;

/**
 * Represents a part of the display that is not functional for displaying content.
@@ -70,10 +70,12 @@ public final class DisplayCutout {
     *
     * @hide
     */
    public static final DisplayCutout NO_CUTOUT = new DisplayCutout(ZERO_RECT, EMPTY_REGION);
    public static final DisplayCutout NO_CUTOUT = new DisplayCutout(ZERO_RECT, EMPTY_REGION,
            new Size(0, 0));

    private final Rect mSafeInsets;
    private final Region mBounds;
    private final Size mFrameSize;

    /**
     * Creates a DisplayCutout instance.
@@ -83,9 +85,10 @@ public final class DisplayCutout {
     * @hide
     */
    @VisibleForTesting
    public DisplayCutout(Rect safeInsets, Region bounds) {
    public DisplayCutout(Rect safeInsets, Region bounds, Size frameSize) {
        mSafeInsets = safeInsets != null ? safeInsets : ZERO_RECT;
        mBounds = bounds != null ? bounds : Region.obtain();
        mFrameSize = frameSize;
    }

    /**
@@ -164,7 +167,8 @@ public final class DisplayCutout {
        if (o instanceof DisplayCutout) {
            DisplayCutout c = (DisplayCutout) o;
            return mSafeInsets.equals(c.mSafeInsets)
                    && mBounds.equals(c.mBounds);
                    && mBounds.equals(c.mBounds)
                    && Objects.equals(mFrameSize, c.mFrameSize);
        }
        return false;
    }
@@ -217,70 +221,84 @@ public final class DisplayCutout {
        }

        bounds.translate(-insetLeft, -insetTop);
        Size frame = mFrameSize == null ? null : new Size(
                mFrameSize.getWidth() - insetLeft - insetRight,
                mFrameSize.getHeight() - insetTop - insetBottom);

        return new DisplayCutout(safeInsets, bounds);
        return new DisplayCutout(safeInsets, bounds, frame);
    }

    /**
     * Calculates the safe insets relative to the given reference frame.
     * Recalculates the cutout relative to the given reference frame.
     *
     * @return a copy of this instance with the safe insets calculated
     * The safe insets must already have been computed, e.g. with {@link #computeSafeInsets}.
     *
     * @return a copy of this instance with the safe insets recalculated
     * @hide
     */
    public DisplayCutout calculateRelativeTo(Rect frame) {
        if (mBounds.isEmpty() || !Rect.intersects(frame, mBounds.getBounds())) {
        return inset(frame.left, frame.top,
                mFrameSize.getWidth() - frame.right, mFrameSize.getHeight() - frame.bottom);
    }

    /**
     * Calculates the safe insets relative to the given display size.
     *
     * @return a copy of this instance with the safe insets calculated
     * @hide
     */
    public DisplayCutout computeSafeInsets(int width, int height) {
        if (this == NO_CUTOUT || mBounds.isEmpty()) {
            return NO_CUTOUT;
        }

        return DisplayCutout.calculateRelativeTo(frame, Region.obtain(mBounds));
        return computeSafeInsets(new Size(width, height), mBounds);
    }

    private static DisplayCutout calculateRelativeTo(Rect frame, Region bounds) {
    private static DisplayCutout computeSafeInsets(Size displaySize, Region bounds) {
        Rect boundingRect = bounds.getBounds();
        Rect safeRect = new Rect();

        int bestArea = 0;
        int bestVariant = 0;
        for (int variant = ROTATION_0; variant <= ROTATION_270; variant++) {
            int area = calculateInsetVariantArea(frame, boundingRect, variant, safeRect);
            int area = calculateInsetVariantArea(displaySize, boundingRect, variant, safeRect);
            if (bestArea < area) {
                bestArea = area;
                bestVariant = variant;
            }
        }
        calculateInsetVariantArea(frame, boundingRect, bestVariant, safeRect);
        calculateInsetVariantArea(displaySize, boundingRect, bestVariant, safeRect);
        if (safeRect.isEmpty()) {
            // The entire frame overlaps with the cutout.
            safeRect.set(0, frame.height(), 0, 0);
            // The entire displaySize overlaps with the cutout.
            safeRect.set(0, displaySize.getHeight(), 0, 0);
        } else {
            // Convert safeRect to insets relative to frame. We're reusing the rect here to avoid
            // an allocation.
            // Convert safeRect to insets relative to displaySize. We're reusing the rect here to
            // avoid an allocation.
            safeRect.set(
                    Math.max(0, safeRect.left - frame.left),
                    Math.max(0, safeRect.top - frame.top),
                    Math.max(0, frame.right - safeRect.right),
                    Math.max(0, frame.bottom - safeRect.bottom));
                    Math.max(0, safeRect.left),
                    Math.max(0, safeRect.top),
                    Math.max(0, displaySize.getWidth() - safeRect.right),
                    Math.max(0, displaySize.getHeight() - safeRect.bottom));
        }

        bounds.translate(-frame.left, -frame.top);

        return new DisplayCutout(safeRect, bounds);
        return new DisplayCutout(safeRect, bounds, displaySize);
    }

    private static int calculateInsetVariantArea(Rect frame, Rect boundingRect, int variant,
    private static int calculateInsetVariantArea(Size display, Rect boundingRect, int variant,
            Rect outSafeRect) {
        switch (variant) {
            case ROTATION_0:
                outSafeRect.set(frame.left, frame.top, frame.right, boundingRect.top);
                outSafeRect.set(0, 0, display.getWidth(), boundingRect.top);
                break;
            case ROTATION_90:
                outSafeRect.set(frame.left, frame.top, boundingRect.left, frame.bottom);
                outSafeRect.set(0, 0, boundingRect.left, display.getHeight());
                break;
            case ROTATION_180:
                outSafeRect.set(frame.left, boundingRect.bottom, frame.right, frame.bottom);
                outSafeRect.set(0, boundingRect.bottom, display.getWidth(), display.getHeight());
                break;
            case ROTATION_270:
                outSafeRect.set(boundingRect.right, frame.top, frame.right, frame.bottom);
                outSafeRect.set(boundingRect.right, 0, display.getWidth(), display.getHeight());
                break;
        }

@@ -293,21 +311,17 @@ public final class DisplayCutout {


    /**
     * Creates an instance from a bounding polygon.
     * Creates an instance from a bounding rect.
     *
     * @hide
     */
    public static DisplayCutout fromBoundingPolygon(List<Point> points) {
    public static DisplayCutout fromBoundingRect(int left, int top, int right, int bottom) {
        Path path = new Path();
        path.reset();
        for (int i = 0; i < points.size(); i++) {
            Point point = points.get(i);
            if (i == 0) {
                path.moveTo(point.x, point.y);
            } else {
                path.lineTo(point.x, point.y);
            }
        }
        path.moveTo(left, top);
        path.lineTo(left, bottom);
        path.lineTo(right, bottom);
        path.lineTo(right, top);
        path.close();
        return fromBounds(path);
    }
@@ -327,7 +341,7 @@ public final class DisplayCutout {
        Region bounds = new Region();
        bounds.setPath(path, clipRegion);
        clipRegion.recycle();
        return new DisplayCutout(ZERO_RECT, bounds);
        return new DisplayCutout(ZERO_RECT, bounds, null /* frameSize */);
    }

    /**
@@ -407,6 +421,12 @@ public final class DisplayCutout {
                out.writeInt(1);
                out.writeTypedObject(cutout.mSafeInsets, flags);
                out.writeTypedObject(cutout.mBounds, flags);
                if (cutout.mFrameSize != null) {
                    out.writeInt(cutout.mFrameSize.getWidth());
                    out.writeInt(cutout.mFrameSize.getHeight());
                } else {
                    out.writeInt(-1);
                }
            }
        }

@@ -449,7 +469,10 @@ public final class DisplayCutout {
            Rect safeInsets = in.readTypedObject(Rect.CREATOR);
            Region bounds = in.readTypedObject(Region.CREATOR);

            return new DisplayCutout(safeInsets, bounds);
            int width = in.readInt();
            Size frameSize = width >= 0 ? new Size(width, in.readInt()) : null;

            return new DisplayCutout(safeInsets, bounds, frameSize);
        }

        public DisplayCutout get() {
+78 −21
Original line number Diff line number Diff line
@@ -17,26 +17,25 @@
package android.view;

import static android.view.DisplayCutout.NO_CUTOUT;
import static android.view.DisplayCutout.fromBoundingRect;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;

import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.util.Size;
import android.view.DisplayCutout.ParcelableWrapper;

import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.Arrays;

@RunWith(AndroidJUnit4.class)
@SmallTest
@Presubmit
@@ -45,7 +44,7 @@ public class DisplayCutoutTest {
    /** This is not a consistent cutout. Useful for verifying insets in one go though. */
    final DisplayCutout mCutoutNumbers = new DisplayCutout(
            new Rect(1, 2, 3, 4),
            new Region(5, 6, 7, 8));
            new Region(5, 6, 7, 8), new Size(9, 10));

    final DisplayCutout mCutoutTop = createCutoutTop();

@@ -154,51 +153,95 @@ public class DisplayCutoutTest {
        assertEquals(new Rect(49, -2, 74, 98), cutout.getBoundingRect());
    }

    @Test
    public void computeSafeInsets_top() throws Exception {
        DisplayCutout cutout = fromBoundingRect(0, 0, 100, 20)
                .computeSafeInsets(200, 400);

        assertEquals(new Rect(0, 20, 0, 0), cutout.getSafeInsets());
    }

    @Test
    public void computeSafeInsets_left() throws Exception {
        DisplayCutout cutout = fromBoundingRect(0, 0, 20, 100)
                .computeSafeInsets(400, 200);

        assertEquals(new Rect(20, 0, 0, 0), cutout.getSafeInsets());
    }

    @Test
    public void computeSafeInsets_bottom() throws Exception {
        DisplayCutout cutout = fromBoundingRect(0, 180, 100, 200)
                .computeSafeInsets(100, 200);

        assertEquals(new Rect(0, 0, 0, 20), cutout.getSafeInsets());
    }

    @Test
    public void computeSafeInsets_right() throws Exception {
        DisplayCutout cutout = fromBoundingRect(180, 0, 200, 100)
                .computeSafeInsets(200, 100);

        assertEquals(new Rect(0, 0, 20, 0), cutout.getSafeInsets());
    }

    @Test
    public void computeSafeInsets_bounds() throws Exception {
        DisplayCutout cutout = mCutoutTop.computeSafeInsets(1000, 2000);

        assertEquals(mCutoutTop.getBoundingRect(), cutout.getBounds().getBounds());
    }

    @Test
    public void calculateRelativeTo_top() throws Exception {
        DisplayCutout cutout = mCutoutTop.calculateRelativeTo(new Rect(0, 0, 200, 400));
        DisplayCutout cutout = fromBoundingRect(0, 0, 100, 20)
                .computeSafeInsets(200, 400)
                .calculateRelativeTo(new Rect(5, 5, 95, 195));

        assertEquals(new Rect(0, 100, 0, 0), cutout.getSafeInsets());
        assertEquals(new Rect(0, 15, 0, 0), cutout.getSafeInsets());
    }

    @Test
    public void calculateRelativeTo_left() throws Exception {
        DisplayCutout cutout = mCutoutTop.calculateRelativeTo(new Rect(0, 0, 400, 200));
        DisplayCutout cutout = fromBoundingRect(0, 0, 20, 100)
                .computeSafeInsets(400, 200)
                .calculateRelativeTo(new Rect(5, 5, 195, 95));

        assertEquals(new Rect(75, 0, 0, 0), cutout.getSafeInsets());
        assertEquals(new Rect(15, 0, 0, 0), cutout.getSafeInsets());
    }

    @Test
    public void calculateRelativeTo_bottom() throws Exception {
        DisplayCutout cutout = mCutoutTop.calculateRelativeTo(new Rect(0, -300, 200, 100));
        DisplayCutout cutout = fromBoundingRect(0, 180, 100, 200)
                .computeSafeInsets(100, 200)
                .calculateRelativeTo(new Rect(5, 5, 95, 195));

        assertEquals(new Rect(0, 0, 0, 100), cutout.getSafeInsets());
        assertEquals(new Rect(0, 0, 0, 15), cutout.getSafeInsets());
    }

    @Test
    public void calculateRelativeTo_right() throws Exception {
        DisplayCutout cutout = mCutoutTop.calculateRelativeTo(new Rect(-400, -200, 100, 100));
        DisplayCutout cutout = fromBoundingRect(180, 0, 200, 100)
                .computeSafeInsets(200, 100)
                .calculateRelativeTo(new Rect(5, 5, 195, 95));

        assertEquals(new Rect(0, 0, 50, 0), cutout.getSafeInsets());
        assertEquals(new Rect(0, 0, 15, 0), cutout.getSafeInsets());
    }

    @Test
    public void calculateRelativeTo_bounds() throws Exception {
        DisplayCutout cutout = mCutoutTop.calculateRelativeTo(new Rect(-1000, -2000, 100, 200));
        DisplayCutout cutout = fromBoundingRect(0, 0, 100, 20)
                .computeSafeInsets(200, 400)
                .calculateRelativeTo(new Rect(5, 10, 95, 180));

        assertEquals(new Rect(1050, 2000, 1075, 2100), cutout.getBoundingRect());
        assertEquals(new Rect(-5, -10, 95, 10), cutout.getBounds().getBounds());
    }

    @Test
    public void fromBoundingPolygon() throws Exception {
        assertEquals(
                new Rect(50, 0, 75, 100),
                DisplayCutout.fromBoundingPolygon(
                        Arrays.asList(
                                new Point(75, 0),
                                new Point(50, 0),
                                new Point(75, 100),
                                new Point(50, 100))).getBounds().getBounds());
                DisplayCutout.fromBoundingRect(50, 0, 75, 100).getBounds().getBounds());
    }

    @Test
@@ -214,6 +257,19 @@ public class DisplayCutoutTest {
        assertEquals(posAfterWrite, p.dataPosition());
    }

    @Test
    public void parcel_unparcel_withFrame() {
        Parcel p = Parcel.obtain();

        new ParcelableWrapper(mCutoutNumbers).writeToParcel(p, 0);
        int posAfterWrite = p.dataPosition();

        p.setDataPosition(0);

        assertEquals(mCutoutNumbers, ParcelableWrapper.CREATOR.createFromParcel(p).get());
        assertEquals(posAfterWrite, p.dataPosition());
    }

    @Test
    public void parcel_unparcel_nocutout() {
        Parcel p = Parcel.obtain();
@@ -264,6 +320,7 @@ public class DisplayCutoutTest {
    private static DisplayCutout createCutoutWithInsets(int left, int top, int right, int bottom) {
        return new DisplayCutout(
                new Rect(left, top, right, bottom),
                new Region(50, 0, 75, 100));
                new Region(50, 0, 75, 100),
                null);
    }
}
+2 −3
Original line number Diff line number Diff line
@@ -387,11 +387,10 @@ public class ScreenDecorations extends SystemUI implements Tunable {
        }

        private boolean hasCutout() {
            if (mInfo.displayCutout == null) {
            final DisplayCutout displayCutout = mInfo.displayCutout;
            if (displayCutout == null) {
                return false;
            }
            DisplayCutout displayCutout = mInfo.displayCutout.calculateRelativeTo(
                    new Rect(0, 0, mInfo.logicalWidth, mInfo.logicalHeight));
            if (mStart) {
                return displayCutout.getSafeInsetLeft() > 0
                        || displayCutout.getSafeInsetTop() > 0;
+37 −15
Original line number Diff line number Diff line
@@ -2818,16 +2818,20 @@ public class PhoneWindowManager implements WindowManagerPolicy {

    @Override
    public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
            int displayId) {
            int displayId, DisplayCutout displayCutout) {
        int width = fullWidth;
        // TODO(multi-display): Support navigation bar on secondary displays.
        if (displayId == DEFAULT_DISPLAY && mHasNavigationBar) {
            // For a basic navigation bar, when we are in landscape mode we place
            // the navigation bar to the side.
            if (mNavigationBarCanMove && fullWidth > fullHeight) {
                return fullWidth - getNavigationBarWidth(rotation, uiMode);
                width -= getNavigationBarWidth(rotation, uiMode);
            }
        }
        return fullWidth;
        if (displayCutout != null) {
            width -= displayCutout.getSafeInsetLeft() + displayCutout.getSafeInsetRight();
        }
        return width;
    }

    private int getNavigationBarHeight(int rotation, int uiMode) {
@@ -2840,35 +2844,46 @@ public class PhoneWindowManager implements WindowManagerPolicy {

    @Override
    public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
            int displayId) {
            int displayId, DisplayCutout displayCutout) {
        int height = fullHeight;
        // TODO(multi-display): Support navigation bar on secondary displays.
        if (displayId == DEFAULT_DISPLAY && mHasNavigationBar) {
            // For a basic navigation bar, when we are in portrait mode we place
            // the navigation bar to the bottom.
            if (!mNavigationBarCanMove || fullWidth < fullHeight) {
                return fullHeight - getNavigationBarHeight(rotation, uiMode);
                height -= getNavigationBarHeight(rotation, uiMode);
            }
        }
        return fullHeight;
        if (displayCutout != null) {
            height -= displayCutout.getSafeInsetTop() + displayCutout.getSafeInsetBottom();
        }
        return height;
    }

    @Override
    public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
            int displayId) {
        return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode, displayId);
            int displayId, DisplayCutout displayCutout) {
        return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode, displayId,
                displayCutout);
    }

    @Override
    public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
            int displayId) {
            int displayId, DisplayCutout displayCutout) {
        // There is a separate status bar at the top of the display.  We don't count that as part
        // of the fixed decor, since it can hide; however, for purposes of configurations,
        // we do want to exclude it since applications can't generally use that part
        // of the screen.
        // TODO(multi-display): Support status bars on secondary displays.
        if (displayId == DEFAULT_DISPLAY) {
            return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation, uiMode, displayId)
                    - mStatusBarHeight;
            int statusBarHeight = mStatusBarHeight;
            if (displayCutout != null) {
                // If there is a cutout, it may already have accounted for some part of the status
                // bar height.
                statusBarHeight = Math.max(0, mStatusBarHeight - displayCutout.getSafeInsetTop());
            }
            return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation, uiMode, displayId,
                    displayCutout) - statusBarHeight;
        }
        return fullHeight;
    }
@@ -6905,17 +6920,17 @@ public class PhoneWindowManager implements WindowManagerPolicy {

    @Override
    public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
            Rect outInsets) {
            DisplayCutout displayCutout, Rect outInsets) {
        outInsets.setEmpty();

        // Navigation bar and status bar.
        getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets);
        outInsets.top = mStatusBarHeight;
        getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, displayCutout, outInsets);
        outInsets.top = Math.max(outInsets.top, mStatusBarHeight);
    }

    @Override
    public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
            Rect outInsets) {
            DisplayCutout displayCutout, Rect outInsets) {
        outInsets.setEmpty();

        // Only navigation bar
@@ -6929,6 +6944,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                outInsets.left = getNavigationBarWidth(displayRotation, mUiMode);
            }
        }

        if (displayCutout != null) {
            outInsets.left += displayCutout.getSafeInsetLeft();
            outInsets.top += displayCutout.getSafeInsetTop();
            outInsets.right += displayCutout.getSafeInsetRight();
            outInsets.bottom += displayCutout.getSafeInsetBottom();
        }
    }

    @Override
+12 −10
Original line number Diff line number Diff line
@@ -922,7 +922,7 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
     * button bar.
     */
    public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation,
            int uiMode, int displayId);
            int uiMode, int displayId, DisplayCutout displayCutout);

    /**
     * Return the display height available after excluding any screen
@@ -930,25 +930,25 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
     * button bar.
     */
    public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation,
            int uiMode, int displayId);
            int uiMode, int displayId, DisplayCutout displayCutout);

    /**
     * Return the available screen width that we should report for the
     * configuration.  This must be no larger than
     * {@link #getNonDecorDisplayWidth(int, int, int, int int, int)}; it may be smaller than
     * that to account for more transient decoration like a status bar.
     * {@link #getNonDecorDisplayWidth(int, int, int, int, int, DisplayCutout)}; it may be smaller
     * than that to account for more transient decoration like a status bar.
     */
    public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation,
            int uiMode, int displayId);
            int uiMode, int displayId, DisplayCutout displayCutout);

    /**
     * Return the available screen height that we should report for the
     * configuration.  This must be no larger than
     * {@link #getNonDecorDisplayHeight(int, int, int, int, int)}; it may be smaller than
     * that to account for more transient decoration like a status bar.
     * {@link #getNonDecorDisplayHeight(int, int, int, int, int, DisplayCutout)}; it may be smaller
     * than that to account for more transient decoration like a status bar.
     */
    public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation,
            int uiMode, int displayId);
            int uiMode, int displayId, DisplayCutout displayCutout);

    /**
     * Return whether the given window can become the Keyguard window. Typically returns true for
@@ -1639,10 +1639,11 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
     * @param displayRotation the current display rotation
     * @param displayWidth the current display width
     * @param displayHeight the current display height
     * @param displayCutout the current display cutout
     * @param outInsets the insets to return
     */
    public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
            Rect outInsets);
            DisplayCutout displayCutout, Rect outInsets);


    /**
@@ -1666,10 +1667,11 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
     * @param displayRotation the current display rotation
     * @param displayWidth the current display width
     * @param displayHeight the current display height
     * @param displayCutout the current display cutout
     * @param outInsets the insets to return
     */
    public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
            Rect outInsets);
            DisplayCutout displayCutout, Rect outInsets);

    /**
     * @return True if a specified {@param dockSide} is allowed on the current device, or false
Loading