am 5814bf1c: am 0608b932: CEC: Add a callback for vendor when HDMI control setting is changed.

* commit '5814bf1c7bc4b8abed781c1667305d843e7079fb':
  CEC: Add a callback for vendor when HDMI control setting is changed.
This commit is contained in:
Yuncheol Heo
2014-10-20 09:19:49 +00:00
committed by Android Git Automerger
5 changed files with 89 additions and 23 deletions

View File

@@ -3,7 +3,6 @@ package android.hardware.hdmi;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.SystemApi; import android.annotation.SystemApi;
import android.hardware.hdmi.HdmiControlManager.VendorCommandListener; import android.hardware.hdmi.HdmiControlManager.VendorCommandListener;
import android.hardware.hdmi.IHdmiVendorCommandListener;
import android.os.RemoteException; import android.os.RemoteException;
import android.util.Log; import android.util.Log;
@@ -91,8 +90,13 @@ public abstract class HdmiClient {
final VendorCommandListener listener) { final VendorCommandListener listener) {
return new IHdmiVendorCommandListener.Stub() { return new IHdmiVendorCommandListener.Stub() {
@Override @Override
public void onReceived(int srcAddress, byte[] params, boolean hasVendorId) { public void onReceived(int srcAddress, int destAddress, byte[] params,
listener.onReceived(srcAddress, params, hasVendorId); boolean hasVendorId) {
listener.onReceived(srcAddress, destAddress, params, hasVendorId);
}
@Override
public void onControlStateChanged(boolean enabled, int reason) {
listener.onControlStateChanged(enabled, reason);
} }
}; };
} }

View File

@@ -236,6 +236,15 @@ public final class HdmiControlManager {
/** Clear timer error - CEC is disabled. */ /** Clear timer error - CEC is disabled. */
public static final int CLEAR_TIMER_STATUS_CEC_DISABLE = 0xA2; public static final int CLEAR_TIMER_STATUS_CEC_DISABLE = 0xA2;
/** The HdmiControlService is started. */
public static final int CONTROL_STATE_CHANGED_REASON_START = 0;
/** The state of HdmiControlService is changed by changing of settings. */
public static final int CONTROL_STATE_CHANGED_REASON_SETTING = 1;
/** The HdmiControlService is enabled to wake up. */
public static final int CONTROL_STATE_CHANGED_REASON_WAKEUP = 2;
/** The HdmiControlService will be disabled to standby. */
public static final int CONTROL_STATE_CHANGED_REASON_STANDBY = 3;
// True if we have a logical device of type playback hosted in the system. // True if we have a logical device of type playback hosted in the system.
private final boolean mHasPlaybackDevice; private final boolean mHasPlaybackDevice;
// True if we have a logical device of type TV hosted in the system. // True if we have a logical device of type TV hosted in the system.
@@ -339,11 +348,29 @@ public final class HdmiControlManager {
* Called when a vendor command is received. * Called when a vendor command is received.
* *
* @param srcAddress source logical address * @param srcAddress source logical address
* @param destAddress destination logical address
* @param params vendor-specific parameters * @param params vendor-specific parameters
* @param hasVendorId {@code true} if the command is <Vendor Command * @param hasVendorId {@code true} if the command is <Vendor Command
* With ID>. The first 3 bytes of params is vendor id. * With ID>. The first 3 bytes of params is vendor id.
*/ */
void onReceived(int srcAddress, byte[] params, boolean hasVendorId); void onReceived(int srcAddress, int destAddress, byte[] params, boolean hasVendorId);
/**
* The callback is called:
* <ul>
* <li> before HdmiControlService is disabled.
* <li> after HdmiControlService is enabled and the local address is assigned.
* </ul>
* The client shouldn't hold the thread too long since this is a blocking call.
*
* @param enabled {@code true} if HdmiControlService is enabled.
* @param reason the reason code why the state of HdmiControlService is changed.
* @see #CONTROL_STATE_CHANGED_REASON_START
* @see #CONTROL_STATE_CHANGED_REASON_SETTING
* @see #CONTROL_STATE_CHANGED_REASON_WAKEUP
* @see #CONTROL_STATE_CHANGED_REASON_STANDBY
*/
void onControlStateChanged(boolean enabled, int reason);
} }
/** /**

View File

@@ -23,5 +23,6 @@ package android.hardware.hdmi;
* @hide * @hide
*/ */
oneway interface IHdmiVendorCommandListener { oneway interface IHdmiVendorCommandListener {
void onReceived(int logicalAddress, in byte[] operands, boolean hasVendorId); void onReceived(int logicalAddress, int destAddress, in byte[] operands, boolean hasVendorId);
void onControlStateChanged(boolean enabled, int reason);
} }

View File

@@ -516,8 +516,8 @@ abstract class HdmiCecLocalDevice {
} }
protected boolean handleVendorCommand(HdmiCecMessage message) { protected boolean handleVendorCommand(HdmiCecMessage message) {
if (!mService.invokeVendorCommandListeners(mDeviceType, message.getSource(), if (!mService.invokeVendorCommandListenersOnReceived(mDeviceType, message.getSource(),
message.getParams(), false)) { message.getDestination(), message.getParams(), false)) {
// Vendor command listener may not have been registered yet. Respond with // Vendor command listener may not have been registered yet. Respond with
// <Feature Abort> [NOT_IN_CORRECT_MODE] so that the sender can try again later. // <Feature Abort> [NOT_IN_CORRECT_MODE] so that the sender can try again later.
mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE); mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE);
@@ -529,8 +529,8 @@ abstract class HdmiCecLocalDevice {
byte[] params = message.getParams(); byte[] params = message.getParams();
int vendorId = HdmiUtils.threeBytesToInt(params); int vendorId = HdmiUtils.threeBytesToInt(params);
if (vendorId == mService.getVendorId()) { if (vendorId == mService.getVendorId()) {
if (!mService.invokeVendorCommandListeners(mDeviceType, message.getSource(), params, if (!mService.invokeVendorCommandListenersOnReceived(mDeviceType, message.getSource(),
true)) { message.getDestination(), params, true)) {
mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE); mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE);
} }
} else if (message.getDestination() != Constants.ADDR_BROADCAST && } else if (message.getDestination() != Constants.ADDR_BROADCAST &&

View File

@@ -316,20 +316,23 @@ public final class HdmiControlService extends SystemService {
mMessageValidator = new HdmiCecMessageValidator(this); mMessageValidator = new HdmiCecMessageValidator(this);
publishBinderService(Context.HDMI_CONTROL_SERVICE, new BinderService()); publishBinderService(Context.HDMI_CONTROL_SERVICE, new BinderService());
// Register broadcast receiver for power state change.
if (mCecController != null) { if (mCecController != null) {
// Register broadcast receiver for power state change.
IntentFilter filter = new IntentFilter(); IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
getContext().registerReceiver(mHdmiControlBroadcastReceiver, filter); getContext().registerReceiver(mHdmiControlBroadcastReceiver, filter);
// Register ContentObserver to monitor the settings change.
registerContentObserver();
} }
} }
/** /**
* Called when the initialization of local devices is complete. * Called when the initialization of local devices is complete.
*/ */
private void onInitializeCecComplete() { private void onInitializeCecComplete(int initiatedBy) {
if (mPowerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON) { if (mPowerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON) {
mPowerStatus = HdmiControlManager.POWER_STATUS_ON; mPowerStatus = HdmiControlManager.POWER_STATUS_ON;
} }
@@ -337,7 +340,22 @@ public final class HdmiControlService extends SystemService {
if (isTvDevice()) { if (isTvDevice()) {
mCecController.setOption(OPTION_CEC_AUTO_WAKEUP, toInt(tv().getAutoWakeup())); mCecController.setOption(OPTION_CEC_AUTO_WAKEUP, toInt(tv().getAutoWakeup()));
registerContentObserver(); }
int reason = -1;
switch (initiatedBy) {
case INITIATED_BY_BOOT_UP:
reason = HdmiControlManager.CONTROL_STATE_CHANGED_REASON_START;
break;
case INITIATED_BY_ENABLE_CEC:
reason = HdmiControlManager.CONTROL_STATE_CHANGED_REASON_SETTING;
break;
case INITIATED_BY_SCREEN_ON:
case INITIATED_BY_WAKE_UP_MESSAGE:
reason = HdmiControlManager.CONTROL_STATE_CHANGED_REASON_WAKEUP;
break;
}
if (reason != -1) {
invokeVendorCommandListenersOnControlStateChanged(true, reason);
} }
} }
@@ -402,10 +420,6 @@ public final class HdmiControlService extends SystemService {
Global.putInt(cr, key, toInt(value)); Global.putInt(cr, key, toInt(value));
} }
private void unregisterSettingsObserver() {
getContext().getContentResolver().unregisterContentObserver(mSettingsObserver);
}
private void initializeCec(int initiatedBy) { private void initializeCec(int initiatedBy) {
mCecController.setOption(OPTION_CEC_SERVICE_CONTROL, ENABLED); mCecController.setOption(OPTION_CEC_SERVICE_CONTROL, ENABLED);
initializeLocalDevices(initiatedBy); initializeLocalDevices(initiatedBy);
@@ -460,7 +474,7 @@ public final class HdmiControlService extends SystemService {
if (initiatedBy != INITIATED_BY_HOTPLUG) { if (initiatedBy != INITIATED_BY_HOTPLUG) {
// In case of the hotplug we don't call onInitializeCecComplete() // In case of the hotplug we don't call onInitializeCecComplete()
// since we reallocate the logical address only. // since we reallocate the logical address only.
onInitializeCecComplete(); onInitializeCecComplete(initiatedBy);
} }
notifyAddressAllocated(allocatedDevices, initiatedBy); notifyAddressAllocated(allocatedDevices, initiatedBy);
} }
@@ -1789,6 +1803,8 @@ public final class HdmiControlService extends SystemService {
private void onStandby() { private void onStandby() {
assertRunOnServiceThread(); assertRunOnServiceThread();
mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY; mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY;
invokeVendorCommandListenersOnControlStateChanged(false,
HdmiControlManager.CONTROL_STATE_CHANGED_REASON_STANDBY);
final List<HdmiCecLocalDevice> devices = getAllLocalDevices(); final List<HdmiCecLocalDevice> devices = getAllLocalDevices();
disableDevices(new PendingActionClearedCallback() { disableDevices(new PendingActionClearedCallback() {
@@ -1827,9 +1843,6 @@ public final class HdmiControlService extends SystemService {
for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) { for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {
device.disableDevice(mStandbyMessageReceived, callback); device.disableDevice(mStandbyMessageReceived, callback);
} }
if (isTvDevice()) {
unregisterSettingsObserver();
}
} }
mMhlController.clearAllLocalDevices(); mMhlController.clearAllLocalDevices();
@@ -1874,8 +1887,8 @@ public final class HdmiControlService extends SystemService {
} }
} }
boolean invokeVendorCommandListeners(int deviceType, int srcAddress, byte[] params, boolean invokeVendorCommandListenersOnReceived(int deviceType, int srcAddress, int destAddress,
boolean hasVendorId) { byte[] params, boolean hasVendorId) {
synchronized (mLock) { synchronized (mLock) {
if (mVendorCommandListenerRecords.isEmpty()) { if (mVendorCommandListenerRecords.isEmpty()) {
return false; return false;
@@ -1885,7 +1898,7 @@ public final class HdmiControlService extends SystemService {
continue; continue;
} }
try { try {
record.mListener.onReceived(srcAddress, params, hasVendorId); record.mListener.onReceived(srcAddress, destAddress, params, hasVendorId);
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "Failed to notify vendor command reception", e); Slog.e(TAG, "Failed to notify vendor command reception", e);
} }
@@ -1894,6 +1907,22 @@ public final class HdmiControlService extends SystemService {
} }
} }
boolean invokeVendorCommandListenersOnControlStateChanged(boolean enabled, int reason) {
synchronized (mLock) {
if (mVendorCommandListenerRecords.isEmpty()) {
return false;
}
for (VendorCommandListenerRecord record : mVendorCommandListenerRecords) {
try {
record.mListener.onControlStateChanged(enabled, reason);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to notify control-state-changed to vendor handler", e);
}
}
return true;
}
}
private void addHdmiMhlVendorCommandListener(IHdmiMhlVendorCommandListener listener) { private void addHdmiMhlVendorCommandListener(IHdmiMhlVendorCommandListener listener) {
HdmiMhlVendorCommandListenerRecord record = HdmiMhlVendorCommandListenerRecord record =
new HdmiMhlVendorCommandListenerRecord(listener); new HdmiMhlVendorCommandListenerRecord(listener);
@@ -1943,6 +1972,11 @@ public final class HdmiControlService extends SystemService {
void setControlEnabled(boolean enabled) { void setControlEnabled(boolean enabled) {
assertRunOnServiceThread(); assertRunOnServiceThread();
if (!enabled) {
// Call the vendor handler before the service is disabled.
invokeVendorCommandListenersOnControlStateChanged(false,
HdmiControlManager.CONTROL_STATE_CHANGED_REASON_SETTING);
}
int value = toInt(enabled); int value = toInt(enabled);
mCecController.setOption(OPTION_CEC_ENABLE, value); mCecController.setOption(OPTION_CEC_ENABLE, value);
mMhlController.setOption(OPTION_MHL_ENABLE, value); mMhlController.setOption(OPTION_MHL_ENABLE, value);