From f17024873b10dabed069e502030dd85d6257c0c4 Mon Sep 17 00:00:00 2001 From: Yuncheol Heo Date: Thu, 27 Nov 2014 19:52:01 +0900 Subject: [PATCH] CEC: make it sure to send vendor commands when changing a setting. - Remove 'oneway' from IHdmiVendorCommandListener. - Add flush() method to HdmiCecController. - Use IoThread for HdmiCecController. Bug: 18495592 Change-Id: I497f7b49e94dd4402058ecc89cb5b7a3d58bf1e1 --- .../hdmi/IHdmiVendorCommandListener.aidl | 2 +- .../server/hdmi/HdmiCecController.java | 16 ++++- .../server/hdmi/HdmiControlService.java | 58 +++++++++++++------ 3 files changed, 56 insertions(+), 20 deletions(-) diff --git a/core/java/android/hardware/hdmi/IHdmiVendorCommandListener.aidl b/core/java/android/hardware/hdmi/IHdmiVendorCommandListener.aidl index a16e8787df8a1..c708d2030bb09 100644 --- a/core/java/android/hardware/hdmi/IHdmiVendorCommandListener.aidl +++ b/core/java/android/hardware/hdmi/IHdmiVendorCommandListener.aidl @@ -22,7 +22,7 @@ package android.hardware.hdmi; * * @hide */ -oneway interface IHdmiVendorCommandListener { +interface IHdmiVendorCommandListener { void onReceived(int logicalAddress, int destAddress, in byte[] operands, boolean hasVendorId); void onControlStateChanged(boolean enabled, int reason); } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java index 0e8788a7fa56a..1486feea0e63f 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecController.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java @@ -129,7 +129,7 @@ final class HdmiCecController { } private void init(long nativePtr) { - mIoHandler = new Handler(mService.getServiceLooper()); + mIoHandler = new Handler(mService.getIoLooper()); mControlHandler = new Handler(mService.getServiceLooper()); mNativePtr = nativePtr; } @@ -324,6 +324,7 @@ final class HdmiCecController { @ServiceThreadOnly void setOption(int flag, int value) { assertRunOnServiceThread(); + HdmiLogger.debug("setOption: [flag:%d, value:%d]", flag, value); nativeSetOption(mNativePtr, flag, value); } @@ -501,6 +502,19 @@ final class HdmiCecController { mControlHandler.post(runnable); } + @ServiceThreadOnly + void flush(final Runnable runnable) { + assertRunOnServiceThread(); + runOnIoThread(new Runnable() { + @Override + public void run() { + // This ensures the runnable for cleanup is performed after all the pending + // commands are processed by IO thread. + runOnServiceThread(runnable); + } + }); + } + private boolean isAcceptableAddress(int address) { // Can access command targeting devices available in local device or broadcast command. if (address == Constants.ADDR_BROADCAST) { diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 8a25f6251faa3..5f8b3899486ef 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -2021,30 +2021,52 @@ public final class HdmiControlService extends SystemService { void setControlEnabled(boolean enabled) { assertRunOnServiceThread(); - if (!enabled) { - // Call the vendor handler before the service is disabled. - invokeVendorCommandListenersOnControlStateChanged(false, - HdmiControlManager.CONTROL_STATE_CHANGED_REASON_SETTING); - } - int value = toInt(enabled); - mCecController.setOption(OPTION_CEC_ENABLE, value); - mMhlController.setOption(OPTION_MHL_ENABLE, value); - synchronized (mLock) { mHdmiControlEnabled = enabled; } if (enabled) { - initializeCec(INITIATED_BY_ENABLE_CEC); - } else { - disableDevices(new PendingActionClearedCallback() { - @Override - public void onCleared(HdmiCecLocalDevice device) { - assertRunOnServiceThread(); - clearLocalDevices(); - } - }); + enableHdmiControlService(); + return; } + // Call the vendor handler before the service is disabled. + invokeVendorCommandListenersOnControlStateChanged(false, + HdmiControlManager.CONTROL_STATE_CHANGED_REASON_SETTING); + // Post the remained tasks in the service thread again to give the vendor-issued-tasks + // a chance to run. + runOnServiceThread(new Runnable() { + @Override + public void run() { + disableHdmiControlService(); + } + }); + return; + } + + @ServiceThreadOnly + private void enableHdmiControlService() { + mCecController.setOption(OPTION_CEC_ENABLE, ENABLED); + mMhlController.setOption(OPTION_MHL_ENABLE, ENABLED); + + initializeCec(INITIATED_BY_ENABLE_CEC); + } + + @ServiceThreadOnly + private void disableHdmiControlService() { + disableDevices(new PendingActionClearedCallback() { + @Override + public void onCleared(HdmiCecLocalDevice device) { + assertRunOnServiceThread(); + mCecController.flush(new Runnable() { + @Override + public void run() { + mCecController.setOption(OPTION_CEC_ENABLE, DISABLED); + mMhlController.setOption(OPTION_MHL_ENABLE, DISABLED); + clearLocalDevices(); + } + }); + } + }); } @ServiceThreadOnly