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

HotplugDetectionAction

public final class HotplugDetectionAction extends HdmiCecFeatureAction
Feature action that handles hot-plug detection mechanism. Hot-plug event is initiated by timer after device discovery action.

Check all devices every 15 secs except for system audio. If system audio is on, check hot-plug for audio system every 5 secs. For other devices, keep 15 secs period.

Fields Summary
private static final String
TAG
private static final int
POLLING_INTERVAL_MS
private static final int
TIMEOUT_COUNT
private static final int
AVR_COUNT_MAX
private static final int
STATE_WAIT_FOR_NEXT_POLLING
private static final int
NUM_OF_ADDRESS
private int
mTimeoutCount
private int
mAvrStatusCount
Constructors Summary
HotplugDetectionAction(HdmiCecLocalDevice source)
Constructor

param
source {@link HdmiCecLocalDevice} instance


               
      
        super(source);
    
Methods Summary
private voidaddDevice(int addedAddress)

        // Sending <Give Physical Address> will initiate new device action.
        sendCommand(HdmiCecMessageBuilder.buildGivePhysicalAddress(getSourceAddress(),
                addedAddress));
    
private static java.util.BitSetaddressListToBitSet(java.util.List list)

        BitSet set = new BitSet(NUM_OF_ADDRESS);
        for (Integer value : list) {
            set.set(value);
        }
        return set;
    
private voidcheckHotplug(java.util.List ackedAddress, boolean audioOnly)

        BitSet currentInfos = infoListToBitSet(tv().getDeviceInfoList(false), audioOnly);
        BitSet polledResult = addressListToBitSet(ackedAddress);

        // At first, check removed devices.
        BitSet removed = complement(currentInfos, polledResult);
        int index = -1;
        while ((index = removed.nextSetBit(index + 1)) != -1) {
            if (index == Constants.ADDR_AUDIO_SYSTEM) {
                ++mAvrStatusCount;
                Slog.w(TAG, "Ack not returned from AVR. count: " + mAvrStatusCount);
                if (mAvrStatusCount < AVR_COUNT_MAX) {
                    continue;
                }
            }
            Slog.v(TAG, "Remove device by hot-plug detection:" + index);
            removeDevice(index);
        }

        // Reset the counter if the ack is returned from AVR.
        if (!removed.get(Constants.ADDR_AUDIO_SYSTEM)) {
            mAvrStatusCount = 0;
        }

        // Next, check added devices.
        BitSet added = complement(polledResult, currentInfos);
        index = -1;
        while ((index = added.nextSetBit(index + 1)) != -1) {
            Slog.v(TAG, "Add device by hot-plug detection:" + index);
            addDevice(index);
        }
    
private static java.util.BitSetcomplement(java.util.BitSet first, java.util.BitSet second)

        // Need to clone it so that it doesn't touch original set.
        BitSet clone = (BitSet) first.clone();
        clone.andNot(second);
        return clone;
    
voidhandleTimerEvent(int state)

        if (mState != state) {
            return;
        }

        if (mState == STATE_WAIT_FOR_NEXT_POLLING) {
            mTimeoutCount = (mTimeoutCount + 1) % TIMEOUT_COUNT;
            pollDevices();
        }
    
private static java.util.BitSetinfoListToBitSet(java.util.List infoList, boolean audioOnly)

        BitSet set = new BitSet(NUM_OF_ADDRESS);
        for (HdmiDeviceInfo info : infoList) {
            if (audioOnly) {
                if (info.getDeviceType() == HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM) {
                    set.set(info.getLogicalAddress());
                }
            } else {
                set.set(info.getLogicalAddress());
            }
        }
        return set;
    
private voidmayCancelDeviceSelect(int address)

        List<DeviceSelectAction> actions = getActions(DeviceSelectAction.class);
        if (actions.isEmpty()) {
            return;
        }

        // Should have only one Device Select Action
        DeviceSelectAction action = actions.get(0);
        if (action.getTargetAddress() == address) {
            removeAction(DeviceSelectAction.class);
        }
    
private voidmayCancelOneTouchRecord(int address)

        List<OneTouchRecordAction> actions = getActions(OneTouchRecordAction.class);
        for (OneTouchRecordAction action : actions) {
            if (action.getRecorderAddress() == address) {
                removeAction(action);
            }
        }
    
private voidmayChangeRoutingPath(int address)

        HdmiDeviceInfo info = tv().getCecDeviceInfo(address);
        if (info != null) {
            tv().handleRemoveActiveRoutingPath(info.getPhysicalAddress());
        }
    
private voidmayDisableSystemAudioAndARC(int address)

        if (HdmiUtils.getTypeFromAddress(address) != HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM) {
            return;
        }

        // Turn off system audio mode and update settings.
        tv().setSystemAudioMode(false, true);
        if (tv().isArcEstabilished()) {
            addAndStartAction(new RequestArcTerminationAction(localDevice(), address));
        }
    
private voidpollAllDevices()

        Slog.v(TAG, "Poll all devices.");

        pollDevices(new DevicePollingCallback() {
            @Override
            public void onPollingFinished(List<Integer> ackedAddress) {
                checkHotplug(ackedAddress, false);
            }
        }, Constants.POLL_ITERATION_IN_ORDER
                | Constants.POLL_STRATEGY_REMOTES_DEVICES, HdmiConfig.HOTPLUG_DETECTION_RETRY);
    
voidpollAllDevicesNow()
Start device polling immediately.

        // Clear existing timer to avoid overlapped execution
        mActionTimer.clearTimerMessage();

        mTimeoutCount = 0;
        mState = STATE_WAIT_FOR_NEXT_POLLING;
        pollAllDevices();

        addTimer(mState, POLLING_INTERVAL_MS);
    
private voidpollAudioSystem()

        Slog.v(TAG, "Poll audio system.");

        pollDevices(new DevicePollingCallback() {
            @Override
            public void onPollingFinished(List<Integer> ackedAddress) {
                checkHotplug(ackedAddress, true);
            }
        }, Constants.POLL_ITERATION_IN_ORDER
                | Constants.POLL_STRATEGY_SYSTEM_AUDIO, HdmiConfig.HOTPLUG_DETECTION_RETRY);
    
private voidpollDevices()

        // All device check called every 15 seconds.
        if (mTimeoutCount == 0) {
            pollAllDevices();
        } else {
            if (tv().isSystemAudioActivated()) {
                pollAudioSystem();
            }
        }

        addTimer(mState, POLLING_INTERVAL_MS);
    
booleanprocessCommand(HdmiCecMessage cmd)

        // No-op
        return false;
    
private voidremoveDevice(int removedAddress)

        mayChangeRoutingPath(removedAddress);
        mayCancelDeviceSelect(removedAddress);
        mayCancelOneTouchRecord(removedAddress);
        mayDisableSystemAudioAndARC(removedAddress);

        tv().removeCecDevice(removedAddress);
    
booleanstart()

        Slog.v(TAG, "Hot-plug dection started.");

        mState = STATE_WAIT_FOR_NEXT_POLLING;
        mTimeoutCount = 0;

        // Start timer without polling.
        // The first check for all devices will be initiated 15 seconds later.
        addTimer(mState, POLLING_INTERVAL_MS);
        return true;