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

Commit b3fca68e authored by Fiona Campbell's avatar Fiona Campbell Committed by Android (Google) Code Review
Browse files

Merge "Add position to displaylayoutconfig"

parents 45287079 d3fc996d
Loading
Loading
Loading
Loading
+44 −19
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.display;

import android.annotation.NonNull;
import android.hardware.devicestate.DeviceStateManager;
import android.os.Environment;
import android.util.IndentingPrintWriter;
@@ -23,8 +24,10 @@ import android.util.Slog;
import android.util.SparseArray;
import android.view.DisplayAddress;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.display.config.layout.Layouts;
import com.android.server.display.config.layout.XmlParser;
import com.android.server.display.layout.DisplayIdProducer;
import com.android.server.display.layout.Layout;

import org.xmlpull.v1.XmlPullParserException;
@@ -48,13 +51,28 @@ class DeviceStateToLayoutMap {

    public static final int STATE_DEFAULT = DeviceStateManager.INVALID_DEVICE_STATE;

    // Direction of the display relative to the default display, whilst in this state
    private static final int POSITION_UNKNOWN = Layout.Display.POSITION_UNKNOWN;
    private static final int POSITION_FRONT = Layout.Display.POSITION_FRONT;
    private static final int POSITION_REAR = Layout.Display.POSITION_REAR;

    private static final String FRONT_STRING = "front";
    private static final String REAR_STRING = "rear";

    private static final String CONFIG_FILE_PATH =
            "etc/displayconfig/display_layout_configuration.xml";

    private final SparseArray<Layout> mLayoutMap = new SparseArray<>();
    private final DisplayIdProducer mIdProducer;

    DeviceStateToLayoutMap(DisplayIdProducer idProducer) {
        this(idProducer, Environment.buildPath(
                Environment.getVendorDirectory(), CONFIG_FILE_PATH));
    }

    DeviceStateToLayoutMap() {
        loadLayoutsFromConfig();
    DeviceStateToLayoutMap(DisplayIdProducer idProducer, File configFile) {
        mIdProducer = idProducer;
        loadLayoutsFromConfig(configFile);
        createLayout(STATE_DEFAULT);
    }

@@ -76,24 +94,11 @@ class DeviceStateToLayoutMap {
        return layout;
    }

    private Layout createLayout(int state) {
        if (mLayoutMap.contains(state)) {
            Slog.e(TAG, "Attempted to create a second layout for state " + state);
            return null;
        }

        final Layout layout = new Layout();
        mLayoutMap.append(state, layout);
        return layout;
    }

    /**
     * Reads display-layout-configuration files to get the layouts to use for this device.
     */
    private void loadLayoutsFromConfig() {
        final File configFile = Environment.buildPath(
                Environment.getVendorDirectory(), CONFIG_FILE_PATH);

    @VisibleForTesting
    void loadLayoutsFromConfig(@NonNull File configFile) {
        if (!configFile.exists()) {
            return;
        }
@@ -109,10 +114,19 @@ class DeviceStateToLayoutMap {
                final int state = l.getState().intValue();
                final Layout layout = createLayout(state);
                for (com.android.server.display.config.layout.Display d: l.getDisplay()) {
                    layout.createDisplayLocked(
                    Layout.Display display = layout.createDisplayLocked(
                            DisplayAddress.fromPhysicalDisplayId(d.getAddress().longValue()),
                            d.isDefaultDisplay(),
                            d.isEnabled());
                            d.isEnabled(),
                            mIdProducer);

                    if (FRONT_STRING.equals(d.getPosition())) {
                        display.setPosition(POSITION_FRONT);
                    } else if (REAR_STRING.equals(d.getPosition())) {
                        display.setPosition(POSITION_REAR);
                    } else {
                        display.setPosition(POSITION_UNKNOWN);
                    }
                }
            }
        } catch (IOException | DatatypeConfigurationException | XmlPullParserException e) {
@@ -120,4 +134,15 @@ class DeviceStateToLayoutMap {
                    + configFile, e);
        }
    }

    private Layout createLayout(int state) {
        if (mLayoutMap.contains(state)) {
            Slog.e(TAG, "Attempted to create a second layout for state " + state);
            return null;
        }

        final Layout layout = new Layout();
        mLayoutMap.append(state, layout);
        return layout;
    }
}
+12 −4
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import android.view.DisplayAddress;
import android.view.DisplayInfo;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.display.layout.DisplayIdProducer;
import com.android.server.display.layout.Layout;

import java.io.PrintWriter;
@@ -82,6 +83,8 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
    private static final int UPDATE_STATE_TRANSITION = 1;
    private static final int UPDATE_STATE_UPDATED = 2;

    private static int sNextNonDefaultDisplayId = DEFAULT_DISPLAY + 1;

    /**
     * Temporary display info, used for comparing display configurations.
     */
@@ -170,6 +173,8 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
    private final ArrayMap<String, Integer> mVirtualDeviceDisplayMapping = new ArrayMap<>();

    private int mNextNonDefaultGroupId = Display.DEFAULT_DISPLAY_GROUP + 1;
    private final DisplayIdProducer mIdProducer = (isDefault) ->
            isDefault ? DEFAULT_DISPLAY : sNextNonDefaultDisplayId++;
    private Layout mCurrentLayout = null;
    private int mDeviceState = DeviceStateManager.INVALID_DEVICE_STATE;
    private int mPendingDeviceState = DeviceStateManager.INVALID_DEVICE_STATE;
@@ -179,7 +184,9 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
    LogicalDisplayMapper(@NonNull Context context, @NonNull DisplayDeviceRepository repo,
            @NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot,
            @NonNull Handler handler) {
        this(context, repo, listener, syncRoot, handler, new DeviceStateToLayoutMap());
        this(context, repo, listener, syncRoot, handler,
                new DeviceStateToLayoutMap((isDefault) -> isDefault ? DEFAULT_DISPLAY
                        : sNextNonDefaultDisplayId++));
    }

    LogicalDisplayMapper(@NonNull Context context, @NonNull DisplayDeviceRepository repo,
@@ -588,7 +595,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {

        // Create a logical display for the new display device
        LogicalDisplay display = createNewLogicalDisplayLocked(
                device, Layout.assignDisplayIdLocked(false /*isDefault*/));
                device, mIdProducer.getId(/* isDefault= */ false));

        applyLayoutLocked();
        updateLogicalDisplaysLocked();
@@ -621,7 +628,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
                        & DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY) != 0
                        && !nextDeviceInfo.address.equals(deviceInfo.address)) {
                    layout.createDisplayLocked(nextDeviceInfo.address,
                            /* isDefault= */ true, /* isEnabled= */ true);
                            /* isDefault= */ true, /* isEnabled= */ true, mIdProducer);
                    applyLayoutLocked();
                    return;
                }
@@ -1036,7 +1043,8 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
            return;
        }
        final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
        layout.createDisplayLocked(info.address, /* isDefault= */ true, /* isEnabled= */ true);
        layout.createDisplayLocked(info.address, /* isDefault= */ true, /* isEnabled= */ true,
                mIdProducer);
    }

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

package com.android.server.display.layout;

/**
 * Interface for producing logical display ids.
 */
public interface DisplayIdProducer {

    /**
     * Generates a new display ID
     * @param isDefault if requested display is the default display.
     * @return the next unique logical display Id.
     */
    int getId(boolean isDefault);
}
+66 −5
Original line number Diff line number Diff line
@@ -50,15 +50,33 @@ public class Layout {
        return mDisplays.toString();
    }

    @Override
    public boolean equals(Object obj) {

        if (!(obj instanceof  Layout)) {
            return false;
        }

        Layout otherLayout = (Layout) obj;
        return this.mDisplays.equals(otherLayout.mDisplays);
    }

    @Override
    public int hashCode() {
        return mDisplays.hashCode();
    }

    /**
     * Creates a simple 1:1 LogicalDisplay mapping for the specified DisplayDevice.
     *
     * @param address Address of the device.
     * @param isDefault Indicates if the device is meant to be the default display.
     * @param isEnabled Indicates if this display is usable and can be switched on
     * @return The new layout.
     */
    public Display createDisplayLocked(
            @NonNull DisplayAddress address, boolean isDefault, boolean isEnabled) {
            @NonNull DisplayAddress address, boolean isDefault, boolean isEnabled,
            DisplayIdProducer idProducer) {
        if (contains(address)) {
            Slog.w(TAG, "Attempting to add second definition for display-device: " + address);
            return null;
@@ -74,7 +92,7 @@ public class Layout {
        // Note that the logical display ID is saved into the layout, so when switching between
        // different layouts, a logical display can be destroyed and later recreated with the
        // same logical display ID.
        final int logicalDisplayId = assignDisplayIdLocked(isDefault);
        final int logicalDisplayId = idProducer.getId(isDefault);
        final Display display = new Display(address, logicalDisplayId, isEnabled);

        mDisplays.add(display);
@@ -158,25 +176,64 @@ public class Layout {
     * Describes how a {@link LogicalDisplay} is built from {@link DisplayDevice}s.
     */
    public static class Display {
        public static final int POSITION_UNKNOWN = -1;
        public static final int POSITION_FRONT = 0;
        public static final int POSITION_REAR = 1;

        // Address of the display device to map to this display.
        private final DisplayAddress mAddress;

        // Logical Display ID to apply to this display.
        private final int mLogicalDisplayId;

        // Indicates that this display is not usable and should remain off.
        // Indicates if this display is usable and can be switched on
        private final boolean mIsEnabled;

        // The direction the display faces
        // {@link DeviceStateToLayoutMap.POSITION_FRONT} or
        // {@link DeviceStateToLayoutMap.POSITION_REAR}.
        // {@link DeviceStateToLayoutMap.POSITION_UNKNOWN} is unspecified.
        private int mPosition;

        Display(@NonNull DisplayAddress address, int logicalDisplayId, boolean isEnabled) {
            mAddress = address;
            mLogicalDisplayId = logicalDisplayId;
            mIsEnabled = isEnabled;
            mPosition = POSITION_UNKNOWN;
        }

        @Override
        public String toString() {
            return "{addr: " + mAddress + ", dispId: " + mLogicalDisplayId
                    + "(" + (mIsEnabled ? "ON" : "OFF") + ")}";
            return "{"
                    + "dispId: " + mLogicalDisplayId
                    + "(" + (mIsEnabled ? "ON" : "OFF") + ")"
                    + ", addr: " + mAddress
                    +  ((mPosition == POSITION_UNKNOWN) ? "" : ", position: " + mPosition)
                    + "}";
        }

        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof Display)) {
                return false;
            }

            Display otherDisplay = (Display) obj;

            return otherDisplay.mIsEnabled == this.mIsEnabled
                    && otherDisplay.mPosition == this.mPosition
                    && otherDisplay.mLogicalDisplayId == this.mLogicalDisplayId
                    && this.mAddress.equals(otherDisplay.mAddress);
        }

        @Override
        public int hashCode() {
            int result = 1;
            result = 31 * result + Boolean.hashCode(mIsEnabled);
            result = 31 * result + mPosition;
            result = 31 * result + mLogicalDisplayId;
            result = 31 * result + mAddress.hashCode();
            return result;
        }

        public DisplayAddress getAddress() {
@@ -190,5 +247,9 @@ public class Layout {
        public boolean isEnabled() {
            return mIsEnabled;
        }

        public void setPosition(int position) {
            mPosition = position;
        }
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@
    <xs:complexType name="display">
        <xs:sequence>
            <xs:element name="address" type="xs:nonNegativeInteger"/>
            <xs:element name="position" type="xs:string" minOccurs="0" maxOccurs="1" />
        </xs:sequence>
        <xs:attribute name="enabled" type="xs:boolean" use="optional" />
        <xs:attribute name="defaultDisplay" type="xs:boolean" use="optional" />
Loading