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
This commit is contained in:
Jungshik Jang
2014-08-11 14:35:27 +09:00
parent 6d2a9492e2
commit 7df52862da
4 changed files with 112 additions and 11 deletions

View File

@@ -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 */ }
}

View File

@@ -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<HdmiCecLocalDevice> 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;
}

View File

@@ -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.
* <p>
* 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;

View File

@@ -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 <Feature Abort> 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 {