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 {