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

Commit 3814f1e2 authored by Nathalie Le Clair's avatar Nathalie Le Clair
Browse files

Process eARC status updates from HAL

Also inform the HDMI HAL which hotplug signal it should use for features
other than eARC, e.g. EDID updates. When eARC is enabled, eARC uses the
physical HPD signal and the other applications need to use the HPD bit
instead.

Bug: 260547935
Test: make and atest

Change-Id: I7dc17270a16ece368d6db6e3674108f960fad63b
parent 40355178
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -599,6 +599,26 @@ final class Constants {
    })
    @interface RcProfileSource {}

    static final int HDMI_EARC_STATUS_IDLE = 0;             // IDLE1
    static final int HDMI_EARC_STATUS_EARC_PENDING = 1;     // DISC1 and DISC2
    static final int HDMI_EARC_STATUS_ARC_PENDING = 2;      // IDLE2 for ARC
    static final int HDMI_EARC_STATUS_EARC_CONNECTED = 3;   // eARC connected
    @IntDef({
            HDMI_EARC_STATUS_IDLE,
            HDMI_EARC_STATUS_EARC_PENDING,
            HDMI_EARC_STATUS_ARC_PENDING,
            HDMI_EARC_STATUS_EARC_CONNECTED
            })
    @interface EarcStatus {}

    static final int HDMI_HPD_TYPE_PHYSICAL = 0;   // Default. Physical hotplug signal.
    static final int HDMI_HPD_TYPE_STATUS_BIT = 1; // HDMI_HPD status bit.
    @IntDef({
            HDMI_HPD_TYPE_PHYSICAL,
            HDMI_HPD_TYPE_STATUS_BIT
    })
    @interface HpdSignalType {}

    private Constants() {
        /* cannot be instantiated */
    }
+25 −0
Original line number Diff line number Diff line
@@ -416,6 +416,31 @@ final class HdmiCecController {
        mNativeWrapperImpl.enableSystemCecControl(enabled);
    }

    /**
     * Configures the type of HDP signal that the driver and HAL use for actions other than eARC,
     * such as signaling EDID updates.
     */
    @ServiceThreadOnly
    void setHpdSignalType(@Constants.HpdSignalType int signal, int portId) {
        assertRunOnServiceThread();
        // Stub.
        // TODO: bind to native.
        // TODO: handle error return values here, with logging.
    }

    /**
     * Gets the type of the HDP signal that the driver and HAL use for actions other than eARC,
     * such as signaling EDID updates.
     */
    @ServiceThreadOnly
    @Constants.HpdSignalType
    int getHpdSignalType(int portId) {
        assertRunOnServiceThread();
        // Stub.
        // TODO: bind to native.
        return Constants.HDMI_HPD_TYPE_PHYSICAL;
    }

    /**
     * Informs CEC HAL about the current system language.
     *
+1 −7
Original line number Diff line number Diff line
@@ -67,8 +67,6 @@ abstract class HdmiCecLocalDevice extends HdmiLocalDevice {
    // When it expires, we can assume <User Control Release> is received.
    private static final int FOLLOWER_SAFETY_TIMEOUT = 550;

    protected final HdmiControlService mService;
    protected final int mDeviceType;
    protected int mPreferredAddress;
    @GuardedBy("mLock")
    private HdmiDeviceInfo mDeviceInfo;
@@ -154,8 +152,6 @@ abstract class HdmiCecLocalDevice extends HdmiLocalDevice {
    private int mActiveRoutingPath;

    protected final HdmiCecMessageCache mCecMessageCache = new HdmiCecMessageCache();
    @VisibleForTesting
    protected final Object mLock;

    // A collection of FeatureAction.
    // Note that access to this collection should happen in service thread.
@@ -188,9 +184,7 @@ abstract class HdmiCecLocalDevice extends HdmiLocalDevice {
    protected PendingActionClearedCallback mPendingActionClearedCallback;

    protected HdmiCecLocalDevice(HdmiControlService service, int deviceType) {
        mService = service;
        mDeviceType = deviceType;
        mLock = service.getServiceLock();
        super(service, deviceType);
    }

    // Factory method that returns HdmiCecLocalDevice of corresponding type.
+34 −8
Original line number Diff line number Diff line
@@ -398,6 +398,8 @@ public class HdmiControlService extends SystemService {
    @GuardedBy("mLock")
    private boolean mEarcEnabled;

    private int mEarcPortId = -1;

    // Set to true while the service is in normal mode. While set to false, no input change is
    // allowed. Used for situations where input change can confuse users such as channel auto-scan,
    // system upgrade, etc., a.k.a. "prohibit mode".
@@ -702,15 +704,21 @@ public class HdmiControlService extends SystemService {
        synchronized (mLock) {
            mEarcSupported = false;
            for (HdmiPortInfo port : ports) {
                if (mEarcSupported && port.isEarcSupported()) {
                    // The HDMI specification only allows 1 active eARC connection. Android does not
                    // support devices with multiple eARC-enabled ports.
                boolean earcSupportedOnPort = port.isEarcSupported();
                if (earcSupportedOnPort && mEarcSupported) {
                    // This means that more than 1 port supports eARC.
                    // The HDMI specification only allows 1 active eARC connection.
                    // Android does not support devices with multiple eARC-enabled ports.
                    // Consider eARC not supported in this case.
                    Slog.e(TAG, "HDMI eARC supported on more than 1 port.");
                    mEarcSupported = false;
                    mEarcPortId = -1;
                    break;
                } else if (earcSupportedOnPort) {
                    mEarcPortId = port.getId();
                    mEarcSupported = earcSupportedOnPort;
                }
                mEarcSupported |= port.isEarcSupported();
            }

            mEarcSupported &= (mEarcController != null);
        }
        if (isEarcSupported()) {
@@ -4416,8 +4424,8 @@ public class HdmiControlService extends SystemService {
    protected void initializeEarcLocalDevice(final int initiatedBy) {
        // TODO remove initiatedBy argument if it stays unused
        assertRunOnServiceThread();
        if (isTvDevice() && mEarcLocalDevice == null) {
            mEarcLocalDevice = new HdmiEarcLocalDeviceTx();
        if (mEarcLocalDevice == null) {
            mEarcLocalDevice = HdmiEarcLocalDevice.create(this, HdmiDeviceInfo.DEVICE_TV);
        }
        // TODO create HdmiEarcLocalDeviceRx if we're an audio system device.
    }
@@ -4483,10 +4491,11 @@ public class HdmiControlService extends SystemService {

    @ServiceThreadOnly
    @VisibleForTesting
    protected HdmiEarcLocalDevice getEarcLocalDevice() {
    HdmiEarcLocalDevice getEarcLocalDevice() {
        assertRunOnServiceThread();
        return mEarcLocalDevice;
    }

    private void disableEarcLocalDevice() {
        if (mEarcLocalDevice == null) {
            return;
@@ -4499,5 +4508,22 @@ public class HdmiControlService extends SystemService {
    protected void setEarcEnabledInHal(boolean enabled) {
        assertRunOnServiceThread();
        mEarcController.setEarcEnabled(enabled);
        mCecController.setHpdSignalType(
                enabled ? Constants.HDMI_HPD_TYPE_STATUS_BIT : Constants.HDMI_HPD_TYPE_PHYSICAL,
                mEarcPortId);
    }

    @ServiceThreadOnly
    void handleEarcStateChange(int status, int portId) {
        assertRunOnServiceThread();
        if (!getPortInfo(portId).isEarcSupported()) {
            Slog.w(TAG, "Tried to update eARC status on a port that doesn't support eARC.");
            return;
        }
        // If eARC is disabled, the local device is null. In this case, the HAL shouldn't have
        // reported connection state changes, but even if it did, it won't take effect.
        if (mEarcLocalDevice != null) {
            mEarcLocalDevice.handleEarcStateChange(status);
        }
    }
}
+20 −0
Original line number Diff line number Diff line
@@ -78,5 +78,25 @@ final class HdmiEarcController {
        // TODO: handle error return values here, with logging.
    }

    /**
     * Getter for the current eARC state.
     * @param portId the ID of the port on which to get the connection state
     * @return the current eARC state
     */
    @HdmiAnnotations.ServiceThreadOnly
    @Constants.EarcStatus
    int getState(int portId) {
        // Stub.
        // TODO: bind to native.
        return Constants.HDMI_EARC_STATUS_IDLE;
    }

    final class EarcCallback {
        public void onStateChange(@Constants.EarcStatus int status, int portId) {
            runOnServiceThread(
                    () -> mService.handleEarcStateChange(status, portId));
        }
    }

    // TODO: bind to native.
}
Loading