summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/hardware/hdmi/HdmiClient.java10
-rw-r--r--core/java/android/hardware/hdmi/HdmiControlManager.java29
-rw-r--r--core/java/android/hardware/hdmi/IHdmiVendorCommandListener.aidl3
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java8
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java62
5 files changed, 89 insertions, 23 deletions
diff --git a/core/java/android/hardware/hdmi/HdmiClient.java b/core/java/android/hardware/hdmi/HdmiClient.java
index aba90e4..c2b9846 100644
--- a/core/java/android/hardware/hdmi/HdmiClient.java
+++ b/core/java/android/hardware/hdmi/HdmiClient.java
@@ -3,7 +3,6 @@ package android.hardware.hdmi;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.hardware.hdmi.HdmiControlManager.VendorCommandListener;
-import android.hardware.hdmi.IHdmiVendorCommandListener;
import android.os.RemoteException;
import android.util.Log;
@@ -91,8 +90,13 @@ public abstract class HdmiClient {
final VendorCommandListener listener) {
return new IHdmiVendorCommandListener.Stub() {
@Override
- public void onReceived(int srcAddress, byte[] params, boolean hasVendorId) {
- listener.onReceived(srcAddress, params, hasVendorId);
+ public void onReceived(int srcAddress, int destAddress, byte[] params,
+ boolean hasVendorId) {
+ listener.onReceived(srcAddress, destAddress, params, hasVendorId);
+ }
+ @Override
+ public void onControlStateChanged(boolean enabled, int reason) {
+ listener.onControlStateChanged(enabled, reason);
}
};
}
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index 30f3576..ff2ba1e 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -236,6 +236,15 @@ public final class HdmiControlManager {
/** Clear timer error - CEC is disabled. */
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.
private final boolean mHasPlaybackDevice;
// 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.
*
* @param srcAddress source logical address
+ * @param destAddress destination logical address
* @param params vendor-specific parameters
* @param hasVendorId {@code true} if the command is <Vendor Command
* 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);
}
/**
diff --git a/core/java/android/hardware/hdmi/IHdmiVendorCommandListener.aidl b/core/java/android/hardware/hdmi/IHdmiVendorCommandListener.aidl
index 55cc925..a16e878 100644
--- a/core/java/android/hardware/hdmi/IHdmiVendorCommandListener.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiVendorCommandListener.aidl
@@ -23,5 +23,6 @@ package android.hardware.hdmi;
* @hide
*/
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);
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index 836a463..4f8b9fb 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -516,8 +516,8 @@ abstract class HdmiCecLocalDevice {
}
protected boolean handleVendorCommand(HdmiCecMessage message) {
- if (!mService.invokeVendorCommandListeners(mDeviceType, message.getSource(),
- message.getParams(), false)) {
+ if (!mService.invokeVendorCommandListenersOnReceived(mDeviceType, message.getSource(),
+ message.getDestination(), message.getParams(), false)) {
// 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.
mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE);
@@ -529,8 +529,8 @@ abstract class HdmiCecLocalDevice {
byte[] params = message.getParams();
int vendorId = HdmiUtils.threeBytesToInt(params);
if (vendorId == mService.getVendorId()) {
- if (!mService.invokeVendorCommandListeners(mDeviceType, message.getSource(), params,
- true)) {
+ if (!mService.invokeVendorCommandListenersOnReceived(mDeviceType, message.getSource(),
+ message.getDestination(), params, true)) {
mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE);
}
} else if (message.getDestination() != 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 d58d787..8a8011d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -316,20 +316,23 @@ public final class HdmiControlService extends SystemService {
mMessageValidator = new HdmiCecMessageValidator(this);
publishBinderService(Context.HDMI_CONTROL_SERVICE, new BinderService());
- // Register broadcast receiver for power state change.
if (mCecController != null) {
+ // Register broadcast receiver for power state change.
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
getContext().registerReceiver(mHdmiControlBroadcastReceiver, filter);
+
+ // Register ContentObserver to monitor the settings change.
+ registerContentObserver();
}
}
/**
* 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) {
mPowerStatus = HdmiControlManager.POWER_STATUS_ON;
}
@@ -337,7 +340,22 @@ public final class HdmiControlService extends SystemService {
if (isTvDevice()) {
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));
}
- private void unregisterSettingsObserver() {
- getContext().getContentResolver().unregisterContentObserver(mSettingsObserver);
- }
-
private void initializeCec(int initiatedBy) {
mCecController.setOption(OPTION_CEC_SERVICE_CONTROL, ENABLED);
initializeLocalDevices(initiatedBy);
@@ -460,7 +474,7 @@ public final class HdmiControlService extends SystemService {
if (initiatedBy != INITIATED_BY_HOTPLUG) {
// In case of the hotplug we don't call onInitializeCecComplete()
// since we reallocate the logical address only.
- onInitializeCecComplete();
+ onInitializeCecComplete(initiatedBy);
}
notifyAddressAllocated(allocatedDevices, initiatedBy);
}
@@ -1789,6 +1803,8 @@ public final class HdmiControlService extends SystemService {
private void onStandby() {
assertRunOnServiceThread();
mPowerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY;
+ invokeVendorCommandListenersOnControlStateChanged(false,
+ HdmiControlManager.CONTROL_STATE_CHANGED_REASON_STANDBY);
final List<HdmiCecLocalDevice> devices = getAllLocalDevices();
disableDevices(new PendingActionClearedCallback() {
@@ -1827,9 +1843,6 @@ public final class HdmiControlService extends SystemService {
for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {
device.disableDevice(mStandbyMessageReceived, callback);
}
- if (isTvDevice()) {
- unregisterSettingsObserver();
- }
}
mMhlController.clearAllLocalDevices();
@@ -1874,8 +1887,8 @@ public final class HdmiControlService extends SystemService {
}
}
- boolean invokeVendorCommandListeners(int deviceType, int srcAddress, byte[] params,
- boolean hasVendorId) {
+ boolean invokeVendorCommandListenersOnReceived(int deviceType, int srcAddress, int destAddress,
+ byte[] params, boolean hasVendorId) {
synchronized (mLock) {
if (mVendorCommandListenerRecords.isEmpty()) {
return false;
@@ -1885,7 +1898,7 @@ public final class HdmiControlService extends SystemService {
continue;
}
try {
- record.mListener.onReceived(srcAddress, params, hasVendorId);
+ record.mListener.onReceived(srcAddress, destAddress, params, hasVendorId);
} catch (RemoteException 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) {
HdmiMhlVendorCommandListenerRecord record =
new HdmiMhlVendorCommandListenerRecord(listener);
@@ -1943,6 +1972,11 @@ 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);