From d4a94db1cd44a536d535de890a0a14919a39a0dc Mon Sep 17 00:00:00 2001 From: Jinsuk Kim Date: Fri, 12 Sep 2014 13:51:10 +0900 Subject: [PATCH] CEC: Bug fixes for vendor-specific command handling - Add sendStandby() - Respond with [INCORRECT_MODE] when the listener is not ready Bug: 17379243 Bug: 17358887 Change-Id: I26a4157a70f11206978763fbbe69e4190e3e1d5c --- .../hardware/hdmi/IHdmiControlService.aidl | 1 + .../server/hdmi/HdmiCecLocalDevice.java | 17 +++++++++++--- .../server/hdmi/HdmiCecLocalDeviceTv.java | 10 +++++++++ .../server/hdmi/HdmiControlService.java | 22 ++++++++++++++++++- 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl index 602f866333cc0..4866a9a9b6e21 100644 --- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl +++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl @@ -62,6 +62,7 @@ interface IHdmiControlService { void sendVendorCommand(int deviceType, int targetAddress, in byte[] params, boolean hasVendorId); void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType); + void sendStandby(int deviceType, int deviceId); void setHdmiRecordListener(IHdmiRecordListener callback); void startOneTouchRecord(int recorderAddress, in byte[] recordSource); void stopOneTouchRecord(int recorderAddress); diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java index 2f36181d64fab..41ac589ff5b89 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java @@ -517,8 +517,12 @@ abstract class HdmiCecLocalDevice { } protected boolean handleVendorCommand(HdmiCecMessage message) { - mService.invokeVendorCommandListeners(mDeviceType, message.getSource(), - message.getParams(), false); + if (!mService.invokeVendorCommandListeners(mDeviceType, message.getSource(), + message.getParams(), false)) { + // Vendor command listener may not have been registered yet. Respond with + // [NOT_IN_CORRECT_MODE] so that the sender can try again later. + mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE); + } return true; } @@ -526,7 +530,10 @@ abstract class HdmiCecLocalDevice { byte[] params = message.getParams(); int vendorId = HdmiUtils.threeBytesToInt(params); if (vendorId == mService.getVendorId()) { - mService.invokeVendorCommandListeners(mDeviceType, message.getSource(), params, true); + if (!mService.invokeVendorCommandListeners(mDeviceType, message.getSource(), 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 "); @@ -537,6 +544,10 @@ abstract class HdmiCecLocalDevice { return true; } + protected void sendStandby(int deviceId) { + // Do nothing. + } + protected boolean handleSetOsdName(HdmiCecMessage message) { // The default behavior of is doing nothing. return true; diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index c9b7b45919bcd..9033c38fb7da9 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -1651,6 +1651,16 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { return true; } + @Override + protected void sendStandby(int deviceId) { + HdmiDeviceInfo targetDevice = mDeviceInfos.get(deviceId); + if (targetDevice == null) { + return; + } + int targetAddress = targetDevice.getLogicalAddress(); + mService.sendCecCommand(HdmiCecMessageBuilder.buildStandby(mAddress, targetAddress)); + } + @Override protected void dump(final IndentingPrintWriter pw) { super.dump(pw); diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 55eb180e291b3..9a4000c33e83d 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -1344,6 +1344,22 @@ public final class HdmiControlService extends SystemService { }); } + @Override + public void sendStandby(final int deviceType, final int deviceId) { + enforceAccessPermission(); + runOnServiceThread(new Runnable() { + @Override + public void run() { + HdmiCecLocalDevice device = mCecController.getLocalDevice(deviceType); + if (device == null) { + Slog.w(TAG, "Local device not available"); + return; + } + device.sendStandby(deviceId); + } + }); + } + @Override public void setHdmiRecordListener(IHdmiRecordListener listener) { HdmiControlService.this.setHdmiRecordListener(listener); @@ -1869,9 +1885,12 @@ public final class HdmiControlService extends SystemService { } } - void invokeVendorCommandListeners(int deviceType, int srcAddress, byte[] params, + boolean invokeVendorCommandListeners(int deviceType, int srcAddress, byte[] params, boolean hasVendorId) { synchronized (mLock) { + if (mVendorCommandListenerRecords.isEmpty()) { + return false; + } for (VendorCommandListenerRecord record : mVendorCommandListenerRecords) { if (record.mDeviceType != deviceType) { continue; @@ -1882,6 +1901,7 @@ public final class HdmiControlService extends SystemService { Slog.e(TAG, "Failed to notify vendor command reception", e); } } + return true; } }