FileDocCategorySizeDatePackage
HdmiCecLocalDevice.javaAPI DocAndroid 5.1 API33112Thu Mar 12 22:22:42 GMT 2015com.android.server.hdmi

HdmiCecLocalDevice

public abstract class HdmiCecLocalDevice extends Object
Class that models a logical CEC device hosted in this system. Handles initialization, CEC commands that call for actions customized per device type.

Fields Summary
private static final String
TAG
private static final int
MSG_DISABLE_DEVICE_TIMEOUT
private static final int
MSG_USER_CONTROL_RELEASE_TIMEOUT
private static final int
DEVICE_CLEANUP_TIMEOUT
private static final int
FOLLOWER_SAFETY_TIMEOUT
protected final HdmiControlService
mService
protected final int
mDeviceType
protected int
mAddress
protected int
mPreferredAddress
protected android.hardware.hdmi.HdmiDeviceInfo
mDeviceInfo
protected int
mLastKeycode
protected int
mLastKeyRepeatCount
protected final ActiveSource
mActiveSource
private int
mActiveRoutingPath
protected final HdmiCecMessageCache
mCecMessageCache
protected final Object
mLock
private final ArrayList
mActions
private final android.os.Handler
mHandler
protected PendingActionClearedCallback
mPendingActionClearedCallback
Constructors Summary
protected HdmiCecLocalDevice(HdmiControlService service, int deviceType)


         
        mService = service;
        mDeviceType = deviceType;
        mAddress = Constants.ADDR_UNREGISTERED;
        mLock = service.getServiceLock();
    
Methods Summary
voidaddAndStartAction(HdmiCecFeatureAction action)

        assertRunOnServiceThread();
        mActions.add(action);
        if (mService.isPowerStandbyOrTransient()) {
            Slog.i(TAG, "Not ready to start action. Queued for deferred start:" + action);
            return;
        }
        action.start();
    
protected voidassertRunOnServiceThread()

        if (Looper.myLooper() != mService.getServiceLooper()) {
            throw new IllegalStateException("Should run on service thread.");
        }
    
protected booleancanGoToStandby()
Returns true if the local device allows the system to be put to standby. The default implementation returns true.

        return true;
    
protected voidcheckIfPendingActionsCleared()

        if (mActions.isEmpty() && mPendingActionClearedCallback != null) {
            PendingActionClearedCallback callback = mPendingActionClearedCallback;
            // To prevent from calling the callback again during handling the callback itself.
            mPendingActionClearedCallback = null;
            callback.onCleared(this);
        }
    
voidclearAddress()

        assertRunOnServiceThread();
        mAddress = Constants.ADDR_UNREGISTERED;
    
static com.android.server.hdmi.HdmiCecLocalDevicecreate(HdmiControlService service, int deviceType)

        switch (deviceType) {
        case HdmiDeviceInfo.DEVICE_TV:
            return new HdmiCecLocalDeviceTv(service);
        case HdmiDeviceInfo.DEVICE_PLAYBACK:
            return new HdmiCecLocalDevicePlayback(service);
        default:
            return null;
        }
    
protected voiddisableDevice(boolean initiatedByCec, com.android.server.hdmi.HdmiCecLocalDevice$PendingActionClearedCallback origialCallback)
Disable device. {@code callback} is used to get notified when all pending actions are completed or timeout is issued.

param
initiatedByCec true if this sequence is initiated by the reception the CEC messages like <Standby>
param
origialCallback callback interface to get notified when all pending actions are cleared

        mPendingActionClearedCallback = new PendingActionClearedCallback() {
            @Override
            public void onCleared(HdmiCecLocalDevice device) {
                mHandler.removeMessages(MSG_DISABLE_DEVICE_TIMEOUT);
                origialCallback.onCleared(device);
            }
        };
        mHandler.sendMessageDelayed(Message.obtain(mHandler, MSG_DISABLE_DEVICE_TIMEOUT),
                DEVICE_CLEANUP_TIMEOUT);
    
booleandispatchMessage(HdmiCecMessage message)
Dispatch incoming message.

param
message incoming message
return
true if consumed a message; otherwise, return false.

        assertRunOnServiceThread();
        int dest = message.getDestination();
        if (dest != mAddress && dest != Constants.ADDR_BROADCAST) {
            return false;
        }
        // Cache incoming message. Note that it caches only white-listed one.
        mCecMessageCache.cacheMessage(message);
        return onMessage(message);
    
private booleandispatchMessageToAction(HdmiCecMessage message)

        assertRunOnServiceThread();
        boolean processed = false;
        // Use copied action list in that processCommand may remove itself.
        for (HdmiCecFeatureAction action : new ArrayList<>(mActions)) {
            // Iterates all actions to check whether incoming message is consumed.
            boolean result = action.processCommand(message);
            processed = processed || result;
        }
        return processed;
    
protected voiddump(com.android.internal.util.IndentingPrintWriter pw)
Dump internal status of HdmiCecLocalDevice object.

        pw.println("mDeviceType: " + mDeviceType);
        pw.println("mAddress: " + mAddress);
        pw.println("mPreferredAddress: " + mPreferredAddress);
        pw.println("mDeviceInfo: " + mDeviceInfo);
        pw.println("mActiveSource: " + mActiveSource);
        pw.println(String.format("mActiveRoutingPath: 0x%04x", mActiveRoutingPath));
    
java.util.ListgetActions(java.lang.Class clazz)

        assertRunOnServiceThread();
        List<T> actions = Collections.<T>emptyList();
        for (HdmiCecFeatureAction action : mActions) {
            if (action.getClass().equals(clazz)) {
                if (actions.isEmpty()) {
                    actions = new ArrayList<T>();
                }
                actions.add((T) action);
            }
        }
        return actions;
    
intgetActivePath()

        synchronized (mLock) {
            return mActiveRoutingPath;
        }
    
intgetActivePortId()
Returns the ID of the active HDMI port. The active port is the one that has the active routing path connected to it directly or indirectly under the device hierarchy.

        synchronized (mLock) {
            return mService.pathToPortId(mActiveRoutingPath);
        }
    
com.android.server.hdmi.HdmiCecLocalDevice$ActiveSourcegetActiveSource()

        synchronized (mLock) {
            return mActiveSource;
        }
    
HdmiCecMessageCachegetCecMessageCache()

        assertRunOnServiceThread();
        return mCecMessageCache;
    
android.hardware.hdmi.HdmiDeviceInfogetDeviceInfo()

        assertRunOnServiceThread();
        return mDeviceInfo;
    
protected abstract intgetPreferredAddress()
Get the preferred logical address from system properties.

final HdmiControlServicegetService()

        return mService;
    
intgetType()

        return mDeviceType;
    
protected booleanhandleActiveSource(HdmiCecMessage message)

        return false;
    
final voidhandleAddressAllocated(int logicalAddress, int reason)

        assertRunOnServiceThread();
        mAddress = mPreferredAddress = logicalAddress;
        onAddressAllocated(logicalAddress, reason);
        setPreferredAddress(logicalAddress);
    
private voidhandleDisableDeviceTimeout()

        assertRunOnServiceThread();

        // If all actions are not cleared in DEVICE_CLEANUP_TIMEOUT, enforce to finish them.
        // onCleard will be called at the last action's finish method.
        Iterator<HdmiCecFeatureAction> iter = mActions.iterator();
        while (iter.hasNext()) {
            HdmiCecFeatureAction action = iter.next();
            action.finish(false);
            iter.remove();
        }
    
protected booleanhandleGetCecVersion(HdmiCecMessage message)

        assertRunOnServiceThread();
        int version = mService.getCecVersion();
        HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildCecVersion(message.getDestination(),
                message.getSource(), version);
        mService.sendCecCommand(cecMessage);
        return true;
    
protected booleanhandleGetMenuLanguage(HdmiCecMessage message)

        assertRunOnServiceThread();
        Slog.w(TAG, "Only TV can handle <Get Menu Language>:" + message.toString());
        // 'return false' will cause to reply with <Feature Abort>.
        return false;
    
protected booleanhandleGiveDevicePowerStatus(HdmiCecMessage message)

        mService.sendCecCommand(HdmiCecMessageBuilder.buildReportPowerStatus(
                mAddress, message.getSource(), mService.getPowerStatus()));
        return true;
    
protected booleanhandleGiveDeviceVendorId()

        assertRunOnServiceThread();
        int vendorId = mService.getVendorId();
        HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildDeviceVendorIdCommand(
                mAddress, vendorId);
        mService.sendCecCommand(cecMessage);
        return true;
    
protected booleanhandleGiveOsdName(HdmiCecMessage message)

        assertRunOnServiceThread();
        // Note that since this method is called after logical address allocation is done,
        // mDeviceInfo should not be null.
        HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildSetOsdNameCommand(
                mAddress, message.getSource(), mDeviceInfo.getDisplayName());
        if (cecMessage != null) {
            mService.sendCecCommand(cecMessage);
        } else {
            Slog.w(TAG, "Failed to build <Get Osd Name>:" + mDeviceInfo.getDisplayName());
        }
        return true;
    
protected booleanhandleGivePhysicalAddress()

        assertRunOnServiceThread();

        int physicalAddress = mService.getPhysicalAddress();
        HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
                mAddress, physicalAddress, mDeviceType);
        mService.sendCecCommand(cecMessage);
        return true;
    
protected booleanhandleImageViewOn(HdmiCecMessage message)

        return false;
    
protected booleanhandleInactiveSource(HdmiCecMessage message)

        return false;
    
protected booleanhandleInitiateArc(HdmiCecMessage message)

        return false;
    
protected booleanhandleMenuRequest(HdmiCecMessage message)

        // Always report menu active to receive Remote Control.
        mService.sendCecCommand(HdmiCecMessageBuilder.buildReportMenuStatus(
                mAddress, message.getSource(), Constants.MENU_STATE_ACTIVATED));
        return true;
    
protected booleanhandleMenuStatus(HdmiCecMessage message)

        return false;
    
protected booleanhandleRecordStatus(HdmiCecMessage message)

        return false;
    
protected booleanhandleRecordTvScreen(HdmiCecMessage message)

        // The default behavior of <Record TV Screen> is replying <Feature Abort> with
        // "Cannot provide source".
        mService.maySendFeatureAbortCommand(message, Constants.ABORT_CANNOT_PROVIDE_SOURCE);
        return true;
    
protected booleanhandleReportAudioStatus(HdmiCecMessage message)

        return false;
    
protected booleanhandleReportPhysicalAddress(HdmiCecMessage message)

        return false;
    
protected booleanhandleReportPowerStatus(HdmiCecMessage message)

        return false;
    
protected booleanhandleRequestActiveSource(HdmiCecMessage message)

        return false;
    
protected booleanhandleRoutingChange(HdmiCecMessage message)

        return false;
    
protected booleanhandleRoutingInformation(HdmiCecMessage message)

        return false;
    
protected booleanhandleSetOsdName(HdmiCecMessage message)

        // The default behavior of <Set Osd Name> is doing nothing.
        return true;
    
protected booleanhandleSetStreamPath(HdmiCecMessage message)

        return false;
    
protected booleanhandleSetSystemAudioMode(HdmiCecMessage message)

        return false;
    
protected booleanhandleStandby(HdmiCecMessage message)

        assertRunOnServiceThread();
        // Seq #12
        if (mService.isControlEnabled() && !mService.isProhibitMode()
                && mService.isPowerOnOrTransient()) {
            mService.standby();
            return true;
        }
        return false;
    
protected booleanhandleSystemAudioModeStatus(HdmiCecMessage message)

        return false;
    
protected booleanhandleTerminateArc(HdmiCecMessage message)

        return false;
    
protected booleanhandleTextViewOn(HdmiCecMessage message)

        return false;
    
protected booleanhandleTimerClearedStatus(HdmiCecMessage message)

        return false;
    
protected booleanhandleTimerStatus(HdmiCecMessage message)

        return false;
    
protected booleanhandleUserControlPressed(HdmiCecMessage message)

        assertRunOnServiceThread();
        mHandler.removeMessages(MSG_USER_CONTROL_RELEASE_TIMEOUT);
        if (mService.isPowerOnOrTransient() && isPowerOffOrToggleCommand(message)) {
            mService.standby();
            return true;
        } else if (mService.isPowerStandbyOrTransient() && isPowerOnOrToggleCommand(message)) {
            mService.wakeUp();
            return true;
        }

        final long downTime = SystemClock.uptimeMillis();
        final byte[] params = message.getParams();
        final int keycode = HdmiCecKeycode.cecKeycodeAndParamsToAndroidKey(params);
        int keyRepeatCount = 0;
        if (mLastKeycode != HdmiCecKeycode.UNSUPPORTED_KEYCODE) {
            if (keycode == mLastKeycode) {
                keyRepeatCount = mLastKeyRepeatCount + 1;
            } else {
                injectKeyEvent(downTime, KeyEvent.ACTION_UP, mLastKeycode, 0);
            }
        }
        mLastKeycode = keycode;
        mLastKeyRepeatCount = keyRepeatCount;

        if (keycode != HdmiCecKeycode.UNSUPPORTED_KEYCODE) {
            injectKeyEvent(downTime, KeyEvent.ACTION_DOWN, keycode, keyRepeatCount);
            mHandler.sendMessageDelayed(Message.obtain(mHandler, MSG_USER_CONTROL_RELEASE_TIMEOUT),
                    FOLLOWER_SAFETY_TIMEOUT);
            return true;
        }
        return false;
    
protected booleanhandleUserControlReleased()

        assertRunOnServiceThread();
        mHandler.removeMessages(MSG_USER_CONTROL_RELEASE_TIMEOUT);
        mLastKeyRepeatCount = 0;
        if (mLastKeycode != HdmiCecKeycode.UNSUPPORTED_KEYCODE) {
            final long upTime = SystemClock.uptimeMillis();
            injectKeyEvent(upTime, KeyEvent.ACTION_UP, mLastKeycode, 0);
            mLastKeycode = HdmiCecKeycode.UNSUPPORTED_KEYCODE;
            return true;
        }
        return false;
    
protected booleanhandleVendorCommand(HdmiCecMessage message)

        if (!mService.invokeVendorCommandListenersOnReceived(mDeviceType, message.getSource(),
                message.getDestination(), message.getParams(), false)) {
            // Vendor command listener may not have been registered yet. Respond with
            // <Feature Abort> [NOT_IN_CORRECT_MODE] so that the sender can try again later.
            mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE);
        }
        return true;
    
protected booleanhandleVendorCommandWithId(HdmiCecMessage message)

        byte[] params = message.getParams();
        int vendorId = HdmiUtils.threeBytesToInt(params);
        if (vendorId == mService.getVendorId()) {
            if (!mService.invokeVendorCommandListenersOnReceived(mDeviceType, message.getSource(),
                    message.getDestination(), params, true)) {
                mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE);
            }
        } else if (message.getDestination() != Constants.ADDR_BROADCAST &&
                message.getSource() != Constants.ADDR_UNREGISTERED) {
            Slog.v(TAG, "Wrong direct vendor command. Replying with <Feature Abort>");
            mService.maySendFeatureAbortCommand(message, Constants.ABORT_UNRECOGNIZED_OPCODE);
        } else {
            Slog.v(TAG, "Wrong broadcast vendor command. Ignoring");
        }
        return true;
    
booleanhasAction(java.lang.Class clazz)

        assertRunOnServiceThread();
        for (HdmiCecFeatureAction action : mActions) {
            if (action.getClass().equals(clazz)) {
                return true;
            }
        }
        return false;
    
voidinit()

        assertRunOnServiceThread();
        mPreferredAddress = getPreferredAddress();
    
static voidinjectKeyEvent(long time, int action, int keycode, int repeat)

        KeyEvent keyEvent = KeyEvent.obtain(time, time, action, keycode,
                repeat, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
                InputDevice.SOURCE_HDMI, null);
        InputManager.getInstance().injectInputEvent(keyEvent,
                InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
        keyEvent.recycle();
   
booleanisAddressOf(int addr)

        assertRunOnServiceThread();
        return addr == mAddress;
    
final booleanisConnectedToArcPort(int path)

        assertRunOnServiceThread();
        return mService.isConnectedToArcPort(path);
    
protected booleanisInputReady(int deviceId)
Returns true if the TV input associated with the CEC device is ready to accept further processing such as input switching. This is used to buffer certain CEC commands and process it later if the input is not ready yet. For other types of local devices(non-TV), this method returns true by default to let the commands be processed right away.

        return true;
    
static booleanisPowerOffOrToggleCommand(HdmiCecMessage message)

        byte[] params = message.getParams();
        return message.getOpcode() == Constants.MESSAGE_USER_CONTROL_PRESSED
                && (params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER
                        || params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER_OFF_FUNCTION
                        || params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION);
    
static booleanisPowerOnOrToggleCommand(HdmiCecMessage message)

        byte[] params = message.getParams();
        return message.getOpcode() == Constants.MESSAGE_USER_CONTROL_PRESSED
                && (params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER
                        || params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER_ON_FUNCTION
                        || params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION);
    
protected abstract voidonAddressAllocated(int logicalAddress, int reason)
Called once a logical address of the local device is allocated.

voidonHotplug(int portId, boolean connected)
Called when a hot-plug event issued.

param
portId id of port where a hot-plug event happened
param
connected whether to connected or not on the event

    
protected final booleanonMessage(HdmiCecMessage message)

        assertRunOnServiceThread();
        if (dispatchMessageToAction(message)) {
            return true;
        }
        switch (message.getOpcode()) {
            case Constants.MESSAGE_ACTIVE_SOURCE:
                return handleActiveSource(message);
            case Constants.MESSAGE_INACTIVE_SOURCE:
                return handleInactiveSource(message);
            case Constants.MESSAGE_REQUEST_ACTIVE_SOURCE:
                return handleRequestActiveSource(message);
            case Constants.MESSAGE_GET_MENU_LANGUAGE:
                return handleGetMenuLanguage(message);
            case Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS:
                return handleGivePhysicalAddress();
            case Constants.MESSAGE_GIVE_OSD_NAME:
                return handleGiveOsdName(message);
            case Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID:
                return handleGiveDeviceVendorId();
            case Constants.MESSAGE_GET_CEC_VERSION:
                return handleGetCecVersion(message);
            case Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS:
                return handleReportPhysicalAddress(message);
            case Constants.MESSAGE_ROUTING_CHANGE:
                return handleRoutingChange(message);
            case Constants.MESSAGE_ROUTING_INFORMATION:
                return handleRoutingInformation(message);
            case Constants.MESSAGE_INITIATE_ARC:
                return handleInitiateArc(message);
            case Constants.MESSAGE_TERMINATE_ARC:
                return handleTerminateArc(message);
            case Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE:
                return handleSetSystemAudioMode(message);
            case Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS:
                return handleSystemAudioModeStatus(message);
            case Constants.MESSAGE_REPORT_AUDIO_STATUS:
                return handleReportAudioStatus(message);
            case Constants.MESSAGE_STANDBY:
                return handleStandby(message);
            case Constants.MESSAGE_TEXT_VIEW_ON:
                return handleTextViewOn(message);
            case Constants.MESSAGE_IMAGE_VIEW_ON:
                return handleImageViewOn(message);
            case Constants.MESSAGE_USER_CONTROL_PRESSED:
                return handleUserControlPressed(message);
            case Constants.MESSAGE_USER_CONTROL_RELEASED:
                return handleUserControlReleased();
            case Constants.MESSAGE_SET_STREAM_PATH:
                return handleSetStreamPath(message);
            case Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS:
                return handleGiveDevicePowerStatus(message);
            case Constants.MESSAGE_MENU_REQUEST:
                return handleMenuRequest(message);
            case Constants.MESSAGE_MENU_STATUS:
                return handleMenuStatus(message);
            case Constants.MESSAGE_VENDOR_COMMAND:
                return handleVendorCommand(message);
            case Constants.MESSAGE_VENDOR_COMMAND_WITH_ID:
                return handleVendorCommandWithId(message);
            case Constants.MESSAGE_SET_OSD_NAME:
                return handleSetOsdName(message);
            case Constants.MESSAGE_RECORD_TV_SCREEN:
                return handleRecordTvScreen(message);
            case Constants.MESSAGE_TIMER_CLEARED_STATUS:
                return handleTimerClearedStatus(message);
            case Constants.MESSAGE_REPORT_POWER_STATUS:
                return handleReportPowerStatus(message);
            case Constants.MESSAGE_TIMER_STATUS:
                return handleTimerStatus(message);
            case Constants.MESSAGE_RECORD_STATUS:
                return handleRecordStatus(message);
            default:
                return false;
        }
    
protected voidonStandby(boolean initiatedByCec)
Called when the system goes to standby mode.

param
initiatedByCec true if this power sequence is initiated by the reception the CEC messages like <Standby>

intpathToPortId(int newPath)

        assertRunOnServiceThread();
        return mService.pathToPortId(newPath);
    
voidremoveAction(HdmiCecFeatureAction action)
Remove the given {@link HdmiCecFeatureAction} object from the action queue.

param
action {@link HdmiCecFeatureAction} to remove

        assertRunOnServiceThread();
        action.finish(false);
        mActions.remove(action);
        checkIfPendingActionsCleared();
    
voidremoveAction(java.lang.Class clazz)

        assertRunOnServiceThread();
        removeActionExcept(clazz, null);
    
voidremoveActionExcept(java.lang.Class clazz, HdmiCecFeatureAction exception)

        assertRunOnServiceThread();
        Iterator<HdmiCecFeatureAction> iter = mActions.iterator();
        while (iter.hasNext()) {
            HdmiCecFeatureAction action = iter.next();
            if (action != exception && action.getClass().equals(clazz)) {
                action.finish(false);
                iter.remove();
            }
        }
        checkIfPendingActionsCleared();
    
protected voidsendKeyEvent(int keyCode, boolean isPressed)
Send a key event to other device.

param
keyCode key code defined in {@link android.view.KeyEvent}
param
isPressed {@code true} for key down event

        Slog.w(TAG, "sendKeyEvent not implemented");
    
protected voidsendStandby(int deviceId)

        // Do nothing.
    
voidsendUserControlPressedAndReleased(int targetAddress, int cecKeycode)

        mService.sendCecCommand(HdmiCecMessageBuilder.buildUserControlPressed(
                mAddress, targetAddress, cecKeycode));
        mService.sendCecCommand(HdmiCecMessageBuilder.buildUserControlReleased(
                mAddress, targetAddress));
    
voidsetActivePath(int path)

        synchronized (mLock) {
            mActiveRoutingPath = path;
        }
        mService.setActivePortId(pathToPortId(path));
    
voidsetActivePortId(int portId)
Update the active port.

param
portId the new active port id

        // We update active routing path instead, since we get the active port id from
        // the active routing path.
        setActivePath(mService.portIdToPath(portId));
    
voidsetActiveSource(com.android.server.hdmi.HdmiCecLocalDevice$ActiveSource newActive)

        setActiveSource(newActive.logicalAddress, newActive.physicalAddress);
    
voidsetActiveSource(android.hardware.hdmi.HdmiDeviceInfo info)

        setActiveSource(info.getLogicalAddress(), info.getPhysicalAddress());
    
voidsetActiveSource(int logicalAddress, int physicalAddress)

        synchronized (mLock) {
            mActiveSource.logicalAddress = logicalAddress;
            mActiveSource.physicalAddress = physicalAddress;
        }
        mService.setLastInputForMhl(Constants.INVALID_PORT_ID);
    
voidsetDeviceInfo(android.hardware.hdmi.HdmiDeviceInfo info)

        assertRunOnServiceThread();
        mDeviceInfo = info;
    
protected abstract voidsetPreferredAddress(int addr)
Set the preferred logical address to system properties.

voidstartQueuedActions()

        assertRunOnServiceThread();
        for (HdmiCecFeatureAction action : mActions) {
            if (!action.started()) {
                Slog.i(TAG, "Starting queued action:" + action);
                action.start();
            }
        }