From 7df52862dae1fa33c84725c613b0d9b88c1b28b6 Mon Sep 17 00:00:00 2001 From: Jungshik Jang Date: Mon, 11 Aug 2014 14:35:27 +0900 Subject: [PATCH] Hook up native mhl api to HdmiControl Service. This change hooks up all apis defined in mhl hal to java layer's HdmiMhlController and HdmiControlService. Along with HdmiMhlController, this change includes followings. 1. HdmiMhlLocalDevice A logical container for a mhl device connected to specific hdmi port 2. HdmiMhlFeatureAction A base feature action class for mhl's state behaviors like RAP and RCP. Bug: 16215362 Change-Id: If177999853f60b68bd079549660a3f4982cb9d9e --- .../com/android/server/hdmi/Constants.java | 21 +++++ .../server/hdmi/HdmiCecController.java | 16 ++-- .../server/hdmi/HdmiCecFeatureAction.java | 6 +- .../server/hdmi/HdmiControlService.java | 80 +++++++++++++++++++ 4 files changed, 112 insertions(+), 11 deletions(-) diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java index 0003210fb970a..b55cf62d8cf2d 100644 --- a/services/core/java/com/android/server/hdmi/Constants.java +++ b/services/core/java/com/android/server/hdmi/Constants.java @@ -244,5 +244,26 @@ final class Constants { static final int DISABLED = 0; static final int ENABLED = 1; + // -------------------------------------------------- + // MHL sub command message types. + static final int MHL_MSG_MSGE = 0x02; + static final int MHL_MSG_RCP = 0x10; + static final int MHL_MSG_RCPK = 0x11; + static final int MHL_MSG_RCPE = 0x12; + static final int MHL_MSG_RAP = 0x20; + static final int MHL_MSG_RAPK = 0x21; + + // MHL RAP messages. + static final int MHL_RAP_ACTION_POLL = 0x00; + static final int MHL_RAP_ACTION_CONTENT_ON = 0x10; + static final int MHL_RAP_ACTION_CONTENT_OFF = 0x11; + + static final int MHL_INVALID_ADOPTER_ID = -1; + static final int MHL_INVALID_DEVICE_ID = -1; + + static final int MHL_CBUS_MODE_OCBUS = 1; + static final int MHL_CBUS_MODE_ECBUS_S = 2; + static final int MHL_CBUS_MODE_ECBUS_D = 3; + private Constants() { /* cannot be instantiated */ } } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java index 10e4b6e386c75..cf06ca86dd486 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecController.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java @@ -94,13 +94,14 @@ final class HdmiCecController { // interacts with HAL. private volatile long mNativePtr; - private HdmiControlService mService; + private final HdmiControlService mService; // Stores the local CEC devices in the system. Device type is used for key. private final SparseArray mLocalDevices = new SparseArray<>(); // Private constructor. Use HdmiCecController.create(). - private HdmiCecController() { + private HdmiCecController(HdmiControlService service) { + mService = service; } /** @@ -114,21 +115,20 @@ final class HdmiCecController { * returns {@code null}. */ static HdmiCecController create(HdmiControlService service) { - HdmiCecController controller = new HdmiCecController(); + HdmiCecController controller = new HdmiCecController(service); long nativePtr = nativeInit(controller, service.getServiceLooper().getQueue()); if (nativePtr == 0L) { controller = null; return null; } - controller.init(service, nativePtr); + controller.init(nativePtr); return controller; } - private void init(HdmiControlService service, long nativePtr) { - mService = service; - mIoHandler = new Handler(service.getServiceLooper()); - mControlHandler = new Handler(service.getServiceLooper()); + private void init(long nativePtr) { + mIoHandler = new Handler(mService.getServiceLooper()); + mControlHandler = new Handler(mService.getServiceLooper()); mNativePtr = nativePtr; } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java b/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java index f32e6605f5b22..26d2cde6bd58f 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java @@ -28,9 +28,9 @@ import java.util.ArrayList; import java.util.List; /** - * Encapsulates a sequence of CEC/MHL command exchange for a certain feature. + * Encapsulates a sequence of CEC command exchange for a certain feature. *

- * Many CEC/MHL features are accomplished by CEC devices on the bus exchanging more than one + * Many CEC features are accomplished by CEC devices on the bus exchanging more than one * command. {@link HdmiCecFeatureAction} represents the life cycle of the communication, manages the * state as the process progresses, and if necessary, returns the result to the caller which * initiates the action, through the callback given at the creation of the object. All the actual @@ -42,7 +42,7 @@ import java.util.List; * package private, accessed by {@link HdmiControlService} only. */ abstract class HdmiCecFeatureAction { - private static final String TAG = "FeatureAction"; + private static final String TAG = "HdmiCecFeatureAction"; // Timer handler message used for timeout event protected static final int MSG_TIMEOUT = 100; diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 356db66076ac2..9a8ef3a109d50 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -604,6 +604,18 @@ public final class HdmiControlService extends SystemService { sendCecCommand(command, null); } + @ServiceThreadOnly + void sendMhlSubcommand(int portId, HdmiMhlSubcommand command) { + assertRunOnServiceThread(); + sendMhlSubcommand(portId, command, null); + } + + @ServiceThreadOnly + void sendMhlSubcommand(int portId, HdmiMhlSubcommand command, SendMessageCallback callback) { + assertRunOnServiceThread(); + mMhlController.sendSubcommand(portId, command, callback); + } + /** * Send command on the given CEC message if possible. * If the aborted message is invalid, then it wont send the message. @@ -732,6 +744,74 @@ public final class HdmiControlService extends SystemService { getVendorId(), displayName); } + @ServiceThreadOnly + boolean handleMhlSubcommand(int portId, HdmiMhlSubcommand message) { + assertRunOnServiceThread(); + + HdmiMhlLocalDevice device = mMhlController.getLocalDevice(portId); + if (device != null) { + return device.handleSubcommand(message); + } + Slog.w(TAG, "No mhl device exists[portId:" + portId + ", message:" + message); + return false; + } + + @ServiceThreadOnly + void handleMhlHotplugEvent(int portId, boolean connected) { + assertRunOnServiceThread(); + if (connected) { + HdmiMhlLocalDevice newDevice = new HdmiMhlLocalDevice(this, portId); + HdmiMhlLocalDevice oldDevice = mMhlController.addLocalDevice(newDevice); + if (oldDevice != null) { + oldDevice.onDeviceRemoved(); + Slog.i(TAG, "Old device of port " + portId + " is removed"); + } + } else { + HdmiMhlLocalDevice device = mMhlController.removeLocalDevice(portId); + if (device != null) { + device.onDeviceRemoved(); + } else { + Slog.w(TAG, "No device to remove:[portId=" + portId); + } + } + } + + @ServiceThreadOnly + void handleMhlCbusModeChanged(int portId, int cbusmode) { + assertRunOnServiceThread(); + HdmiMhlLocalDevice device = mMhlController.getLocalDevice(portId); + if (device != null) { + device.setCbusMode(cbusmode); + } else { + Slog.w(TAG, "No mhl device exists for cbus mode change[portId:" + portId + + ", cbusmode:" + cbusmode + "]"); + } + } + + @ServiceThreadOnly + void handleMhlVbusOvercurrent(int portId, boolean on) { + assertRunOnServiceThread(); + HdmiMhlLocalDevice device = mMhlController.getLocalDevice(portId); + if (device != null) { + device.onVbusOvercurrentDetected(on); + } else { + Slog.w(TAG, "No mhl device exists for vbus overcurrent event[portId:" + portId + "]"); + } + } + + @ServiceThreadOnly + void handleCapabilityRegisterChanged(int portId, int adopterId, int deviceId) { + assertRunOnServiceThread(); + HdmiMhlLocalDevice device = mMhlController.getLocalDevice(portId); + // Hot plug event should be called before capability register change event. + if (device != null) { + device.setCapabilityRegister(adopterId, deviceId); + } else { + Slog.w(TAG, "No mhl device exists for capability register change event[portId:" + + portId + ", adopterId:" + adopterId + ", deviceId:" + deviceId + "]"); + } + } + // Record class that monitors the event of the caller of being killed. Used to clean up // the listener list and record list accordingly. private final class HotplugEventListenerRecord implements IBinder.DeathRecipient {