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

Commit 0a3316bc authored by Jinsuk Kim's avatar Jinsuk Kim
Browse files

Boilerplate class for vendor-specific commands for HdmiControlService

Vendor-specific commands in HDMI-CEC protocol needs to be handled
by OEM. This CL introduces a boilerplate class that should be filled
in to handle it for TV device.

Change-Id: I56b9aac973f1cff27ea8654850334d2d5f6838fe
parent a747435c
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -139,6 +139,10 @@ abstract class HdmiCecLocalDevice {
        return true;
    }

    protected boolean handleVendorSpecificCommand(HdmiCecMessage message) {
        return false;
    }

    final void handleAddressAllocated(int logicalAddress) {
        mAddress = mPreferredAddress = logicalAddress;
        onAddressAllocated(logicalAddress);
+28 −1
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ import android.hardware.hdmi.HdmiCecMessage;
import android.os.RemoteException;
import android.util.Slog;

import java.util.Collections;
import java.util.List;
import java.util.Locale;

/**
@@ -110,4 +112,29 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {

        return true;
    }

    @Override
    protected boolean handleVendorSpecificCommand(HdmiCecMessage message) {
        List<VendorSpecificAction> actions = Collections.emptyList();
        // TODO: Call mService.getActions(VendorSpecificAction.class) to get all the actions.

        // We assume that there can be multiple vendor-specific command actions running
        // at the same time. Pass the message to each action to see if one of them needs it.
        for (VendorSpecificAction action : actions) {
            if (action.processCommand(message)) {
                return true;
            }
        }
        // Handle the message here if it is not already consumed by one of the running actions.
        // Respond with a appropriate vendor-specific command or <Feature Abort>, or create another
        // vendor-specific action:
        //
        // mService.addAndStartAction(new VendorSpecificAction(mService, mAddress));
        //
        // For now, simply reply with <Feature Abort> and mark it consumed by returning true.
        mService.sendCecCommand(HdmiCecMessageBuilder.buildFeatureAbortCommand(
                message.getDestination(), message.getSource(), message.getOpcode(),
                HdmiConstants.ABORT_REFUSED));
        return true;
    }
}
+54 −0
Original line number Diff line number Diff line
package com.android.server.hdmi;

import android.hardware.hdmi.HdmiCecMessage;

/**
 * Handles vendor-specific commands that require a sequence of command exchange,
 * or need to manage some states to complete the processing.
 */
public class VendorSpecificAction extends FeatureAction {

    // Sample state this action can be in.
    private static final int STATE_1 = 1;
    private static final int STATE_2 = 2;

    VendorSpecificAction(HdmiControlService service, int sourceAddress) {
        super(service, sourceAddress);
        // Modify the constructor if additional arguments are necessary.
    }

    @Override
    boolean start() {
        // Do initialization step and update the state accordingly here.
        mState = STATE_1;
        addTimer(STATE_1, TIMEOUT_MS);
        return true;
    }

    @Override
    boolean processCommand(HdmiCecMessage cmd) {
        // Returns true if the command was consumed. Otherwise return false for other
        // actions in progress can be given its turn to process it.
        return false;
    }

    @Override
    void handleTimerEvent(int state) {
        // Ignore the timer event if the current state and the state this event should be
        // handled in are different. Could be an outdated event which should have been cleared by
        // calling {@code mActionTimer.clearTimerMessage()}.
        if (mState != state) {
            return;
        }

        switch (state) {
            case STATE_1:
                mState = STATE_2;
                addTimer(STATE_2, TIMEOUT_MS);
                break;
            case STATE_2:
                finish();
                break;
        }
    }
}