diff --git a/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java b/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java index af716242210ed..d137580e9eea4 100755 --- a/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java +++ b/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java @@ -16,6 +16,7 @@ package com.android.server.hdmi; +import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiDeviceInfo; import android.util.Slog; @@ -51,8 +52,10 @@ final class DeviceDiscoveryAction extends HdmiCecFeatureAction { private static final int STATE_WAITING_FOR_OSD_NAME = 3; // State in which the action is waiting for gathering vendor id of non-local devices. private static final int STATE_WAITING_FOR_VENDOR_ID = 4; - // State in which the action is waiting for devices to be ready + // State in which the action is waiting for devices to be ready. private static final int STATE_WAITING_FOR_DEVICES = 5; + // State in which the action is waiting for gathering power status of non-local devices. + private static final int STATE_WAITING_FOR_POWER = 6; /** * Interface used to report result of device discovery. @@ -74,6 +77,7 @@ final class DeviceDiscoveryAction extends HdmiCecFeatureAction { private int mPhysicalAddress = Constants.INVALID_PHYSICAL_ADDRESS; private int mPortId = Constants.INVALID_PORT_ID; private int mVendorId = Constants.UNKNOWN_VENDOR_ID; + private int mPowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN; private String mDisplayName = ""; private int mDeviceType = HdmiDeviceInfo.DEVICE_INACTIVE; @@ -83,7 +87,7 @@ final class DeviceDiscoveryAction extends HdmiCecFeatureAction { private HdmiDeviceInfo toHdmiDeviceInfo() { return new HdmiDeviceInfo(mLogicalAddress, mPhysicalAddress, mPortId, mDeviceType, - mVendorId, mDisplayName); + mVendorId, mDisplayName, mPowerStatus); } } @@ -237,6 +241,29 @@ final class DeviceDiscoveryAction extends HdmiCecFeatureAction { addTimer(mState, HdmiConfig.TIMEOUT_MS); } + private void startPowerStatusStage() { + Slog.v(TAG, "Start [Power Status Stage]:" + mDevices.size()); + mProcessedDeviceCount = 0; + mState = STATE_WAITING_FOR_POWER; + + checkAndProceedStage(); + } + + private void queryPowerStatus(int address) { + if (!verifyValidLogicalAddress(address)) { + checkAndProceedStage(); + return; + } + + mActionTimer.clearTimerMessage(); + + if (mayProcessMessageIfCached(address, Constants.MESSAGE_REPORT_POWER_STATUS)) { + return; + } + sendCommand(HdmiCecMessageBuilder.buildGiveDevicePowerStatus(getSourceAddress(), address)); + addTimer(mState, HdmiConfig.TIMEOUT_MS); + } + private boolean mayProcessMessageIfCached(int address, int opcode) { HdmiCecMessage message = getCecMessageCache().getMessage(address, opcode); if (message != null) { @@ -275,6 +302,16 @@ final class DeviceDiscoveryAction extends HdmiCecFeatureAction { return true; } return false; + case STATE_WAITING_FOR_POWER: + if (cmd.getOpcode() == Constants.MESSAGE_REPORT_POWER_STATUS) { + handleReportPowerStatus(cmd); + return true; + } else if ((cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT) + && ((cmd.getParams()[0] & 0xFF) == Constants.MESSAGE_REPORT_POWER_STATUS)) { + handleReportPowerStatus(cmd); + return true; + } + return false; case STATE_WAITING_FOR_DEVICE_POLLING: // Fall through. default: @@ -359,6 +396,26 @@ final class DeviceDiscoveryAction extends HdmiCecFeatureAction { checkAndProceedStage(); } + private void handleReportPowerStatus(HdmiCecMessage cmd) { + Preconditions.checkState(mProcessedDeviceCount < mDevices.size()); + + DeviceInfo current = mDevices.get(mProcessedDeviceCount); + if (current.mLogicalAddress != cmd.getSource()) { + Slog.w(TAG, "Unmatched address[expected:" + current.mLogicalAddress + ", actual:" + + cmd.getSource()); + return; + } + + if (cmd.getOpcode() != Constants.MESSAGE_FEATURE_ABORT) { + byte[] params = cmd.getParams(); + int powerStatus = params[0] & 0xFF; + current.mPowerStatus = powerStatus; + } + + increaseProcessedDeviceCount(); + checkAndProceedStage(); + } + private void increaseProcessedDeviceCount() { mProcessedDeviceCount++; mTimeoutRetry = 0; @@ -402,6 +459,9 @@ final class DeviceDiscoveryAction extends HdmiCecFeatureAction { startVendorIdStage(); return; case STATE_WAITING_FOR_VENDOR_ID: + startPowerStatusStage(); + return; + case STATE_WAITING_FOR_POWER: wrapUpAndFinish(); return; default: @@ -427,6 +487,9 @@ final class DeviceDiscoveryAction extends HdmiCecFeatureAction { case STATE_WAITING_FOR_VENDOR_ID: queryVendorId(address); return; + case STATE_WAITING_FOR_POWER: + queryPowerStatus(address); + return; default: return; } @@ -448,7 +511,11 @@ final class DeviceDiscoveryAction extends HdmiCecFeatureAction { } mTimeoutRetry = 0; Slog.v(TAG, "Timeout[State=" + mState + ", Processed=" + mProcessedDeviceCount); - removeDevice(mProcessedDeviceCount); + if (mState != STATE_WAITING_FOR_POWER) { + removeDevice(mProcessedDeviceCount); + } else { + increaseProcessedDeviceCount(); + } checkAndProceedStage(); } } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java index c9eef0f5fbb76..1029a0d7677d1 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java @@ -1087,6 +1087,10 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { @ServiceThreadOnly private void launchDeviceDiscovery() { assertRunOnServiceThread(); + if (hasAction(DeviceDiscoveryAction.class)) { + Slog.i(TAG, "Device Discovery Action is in progress. Restarting."); + removeAction(DeviceDiscoveryAction.class); + } DeviceDiscoveryAction action = new DeviceDiscoveryAction(this, new DeviceDiscoveryCallback() { @Override