Merge "CEC: Change vendor command handling" am: 134f59f851 am: e90b5a3efc
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1807376 Change-Id: Ib9aa66ef9089f5b628745b9e5931ba69c9e15448
This commit is contained in:
@@ -2954,6 +2954,7 @@ package android.hardware.hdmi {
|
||||
method public void sendKeyEvent(int, boolean);
|
||||
method public void sendVendorCommand(int, byte[], boolean);
|
||||
method public void setVendorCommandListener(@NonNull android.hardware.hdmi.HdmiControlManager.VendorCommandListener);
|
||||
method public void setVendorCommandListener(@NonNull android.hardware.hdmi.HdmiControlManager.VendorCommandListener, int);
|
||||
}
|
||||
|
||||
public final class HdmiControlManager {
|
||||
|
||||
@@ -17,6 +17,8 @@ import android.util.Log;
|
||||
public abstract class HdmiClient {
|
||||
private static final String TAG = "HdmiClient";
|
||||
|
||||
private static final int UNKNOWN_VENDOR_ID = 0xFFFFFF;
|
||||
|
||||
/* package */ final IHdmiControlService mService;
|
||||
|
||||
private IHdmiVendorCommandListener mIHdmiVendorCommandListener;
|
||||
@@ -94,11 +96,25 @@ public abstract class HdmiClient {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a listener used to receive incoming vendor-specific command.
|
||||
* Sets a listener used to receive incoming vendor-specific command. This listener will only
|
||||
* receive {@code <Vendor Command>} but will not receive any {@code <Vendor Command with ID>}
|
||||
* messages.
|
||||
*
|
||||
* @param listener listener object
|
||||
*/
|
||||
public void setVendorCommandListener(@NonNull VendorCommandListener listener) {
|
||||
// Set the vendor ID to INVALID_VENDOR_ID.
|
||||
setVendorCommandListener(listener, UNKNOWN_VENDOR_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a listener used to receive incoming vendor-specific command.
|
||||
*
|
||||
* @param listener listener object
|
||||
* @param vendorId The listener is interested in {@code <Vendor Command with ID>} received with
|
||||
* this vendorId and all {@code <Vendor Command>} messages.
|
||||
*/
|
||||
public void setVendorCommandListener(@NonNull VendorCommandListener listener, int vendorId) {
|
||||
if (listener == null) {
|
||||
throw new IllegalArgumentException("listener cannot be null");
|
||||
}
|
||||
@@ -107,7 +123,7 @@ public abstract class HdmiClient {
|
||||
}
|
||||
try {
|
||||
IHdmiVendorCommandListener wrappedListener = getListenerWrapper(listener);
|
||||
mService.addVendorCommandListener(wrappedListener, getDeviceType());
|
||||
mService.addVendorCommandListener(wrappedListener, vendorId);
|
||||
mIHdmiVendorCommandListener = wrappedListener;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "failed to set vendor command listener: ", e);
|
||||
|
||||
@@ -221,8 +221,8 @@ public final class HdmiControlServiceWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType) {
|
||||
HdmiControlServiceWrapper.this.addVendorCommandListener(listener, deviceType);
|
||||
public void addVendorCommandListener(IHdmiVendorCommandListener listener, int vendorId) {
|
||||
HdmiControlServiceWrapper.this.addVendorCommandListener(listener, vendorId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -471,7 +471,7 @@ public final class HdmiControlServiceWrapper {
|
||||
boolean hasVendorId) {}
|
||||
|
||||
/** @hide */
|
||||
public void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType) {}
|
||||
public void addVendorCommandListener(IHdmiVendorCommandListener listener, int vendorId) {}
|
||||
|
||||
/** @hide */
|
||||
public void sendStandby(int deviceType, int deviceId) {}
|
||||
|
||||
@@ -76,7 +76,7 @@ interface IHdmiControlService {
|
||||
void askRemoteDeviceToBecomeActiveSource(int physicalAddress);
|
||||
void sendVendorCommand(int deviceType, int targetAddress, in byte[] params,
|
||||
boolean hasVendorId);
|
||||
void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType);
|
||||
void addVendorCommandListener(IHdmiVendorCommandListener listener, int vendorId);
|
||||
void sendStandby(int deviceType, int deviceId);
|
||||
void setHdmiRecordListener(IHdmiRecordListener callback);
|
||||
void startOneTouchRecord(int recorderAddress, in byte[] recordSource);
|
||||
|
||||
@@ -288,9 +288,8 @@ public class HdmiAudioSystemClientTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVendorCommandListener(final IHdmiVendorCommandListener listener,
|
||||
final int deviceType) {
|
||||
}
|
||||
public void addVendorCommandListener(
|
||||
final IHdmiVendorCommandListener listener, final int vendorId) {}
|
||||
|
||||
@Override
|
||||
public void sendVendorCommand(final int deviceType, final int targetAddress,
|
||||
|
||||
@@ -829,17 +829,12 @@ abstract class HdmiCecLocalDevice {
|
||||
protected int handleVendorCommandWithId(HdmiCecMessage message) {
|
||||
byte[] params = message.getParams();
|
||||
int vendorId = HdmiUtils.threeBytesToInt(params);
|
||||
if (vendorId == mService.getVendorId()) {
|
||||
if (!mService.invokeVendorCommandListenersOnReceived(
|
||||
mDeviceType, message.getSource(), message.getDestination(), params, true)) {
|
||||
return Constants.ABORT_REFUSED;
|
||||
}
|
||||
} else if (message.getDestination() != Constants.ADDR_BROADCAST
|
||||
&& message.getSource() != Constants.ADDR_UNREGISTERED) {
|
||||
Slog.v(TAG, "Wrong direct vendor command. Replying with <Feature Abort>");
|
||||
return Constants.ABORT_UNRECOGNIZED_OPCODE;
|
||||
} else {
|
||||
if (message.getDestination() == Constants.ADDR_BROADCAST
|
||||
|| message.getSource() == Constants.ADDR_UNREGISTERED) {
|
||||
Slog.v(TAG, "Wrong broadcast vendor command. Ignoring");
|
||||
} else if (!mService.invokeVendorCommandListenersOnReceived(
|
||||
mDeviceType, message.getSource(), message.getDestination(), params, true)) {
|
||||
return Constants.ABORT_REFUSED;
|
||||
}
|
||||
return Constants.HANDLED;
|
||||
}
|
||||
|
||||
@@ -1582,11 +1582,11 @@ public class HdmiControlService extends SystemService {
|
||||
|
||||
class VendorCommandListenerRecord implements IBinder.DeathRecipient {
|
||||
private final IHdmiVendorCommandListener mListener;
|
||||
private final int mDeviceType;
|
||||
private final int mVendorId;
|
||||
|
||||
public VendorCommandListenerRecord(IHdmiVendorCommandListener listener, int deviceType) {
|
||||
VendorCommandListenerRecord(IHdmiVendorCommandListener listener, int vendorId) {
|
||||
mListener = listener;
|
||||
mDeviceType = deviceType;
|
||||
mVendorId = vendorId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2077,10 +2077,10 @@ public class HdmiControlService extends SystemService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVendorCommandListener(final IHdmiVendorCommandListener listener,
|
||||
final int deviceType) {
|
||||
public void addVendorCommandListener(
|
||||
final IHdmiVendorCommandListener listener, final int vendorId) {
|
||||
initBinderCall();
|
||||
HdmiControlService.this.addVendorCommandListener(listener, deviceType);
|
||||
HdmiControlService.this.addVendorCommandListener(listener, vendorId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -3219,8 +3219,9 @@ public class HdmiControlService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
private void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType) {
|
||||
VendorCommandListenerRecord record = new VendorCommandListenerRecord(listener, deviceType);
|
||||
@VisibleForTesting
|
||||
void addVendorCommandListener(IHdmiVendorCommandListener listener, int vendorId) {
|
||||
VendorCommandListenerRecord record = new VendorCommandListenerRecord(listener, vendorId);
|
||||
try {
|
||||
listener.asBinder().linkToDeath(record, 0);
|
||||
} catch (RemoteException e) {
|
||||
@@ -3239,8 +3240,14 @@ public class HdmiControlService extends SystemService {
|
||||
return false;
|
||||
}
|
||||
for (VendorCommandListenerRecord record : mVendorCommandListenerRecords) {
|
||||
if (record.mDeviceType != deviceType) {
|
||||
continue;
|
||||
if (hasVendorId) {
|
||||
int vendorId =
|
||||
((params[0] & 0xFF) << 16)
|
||||
+ ((params[1] & 0xFF) << 8)
|
||||
+ (params[2] & 0xFF);
|
||||
if (record.mVendorId != vendorId) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
try {
|
||||
record.mListener.onReceived(srcAddress, destAddress, params, hasVendorId);
|
||||
|
||||
@@ -43,6 +43,7 @@ import android.hardware.hdmi.HdmiControlManager;
|
||||
import android.hardware.hdmi.HdmiPortInfo;
|
||||
import android.hardware.hdmi.IHdmiCecVolumeControlFeatureListener;
|
||||
import android.hardware.hdmi.IHdmiControlStatusChangeListener;
|
||||
import android.hardware.hdmi.IHdmiVendorCommandListener;
|
||||
import android.os.Binder;
|
||||
import android.os.IPowerManager;
|
||||
import android.os.IThermalService;
|
||||
@@ -885,6 +886,114 @@ public class HdmiControlServiceTest {
|
||||
.isEqualTo(Constants.ABORT_REFUSED);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addVendorCommandListener_receiveCallback_VendorCmdNoIdTest() {
|
||||
int destAddress = mHdmiControlServiceSpy.playback().getDeviceInfo().getLogicalAddress();
|
||||
int sourceAddress = Constants.ADDR_TV;
|
||||
byte[] params = {0x00, 0x01, 0x02, 0x03};
|
||||
int vendorId = 0x123456;
|
||||
|
||||
VendorCommandListener vendorCmdListener =
|
||||
new VendorCommandListener(sourceAddress, destAddress, params, vendorId);
|
||||
mHdmiControlServiceSpy.addVendorCommandListener(vendorCmdListener, vendorId);
|
||||
mTestLooper.dispatchAll();
|
||||
|
||||
HdmiCecMessage vendorCommandNoId =
|
||||
HdmiCecMessageBuilder.buildVendorCommand(sourceAddress, destAddress, params);
|
||||
mNativeWrapper.onCecMessage(vendorCommandNoId);
|
||||
mTestLooper.dispatchAll();
|
||||
assertThat(vendorCmdListener.mVendorCommandCallbackReceived).isTrue();
|
||||
assertThat(vendorCmdListener.mParamsCorrect).isTrue();
|
||||
assertThat(vendorCmdListener.mHasVendorId).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addVendorCommandListener_receiveCallback_VendorCmdWithIdTest() {
|
||||
int destAddress = mHdmiControlServiceSpy.playback().getDeviceInfo().getLogicalAddress();
|
||||
int sourceAddress = Constants.ADDR_TV;
|
||||
byte[] params = {0x00, 0x01, 0x02, 0x03};
|
||||
int vendorId = 0x123456;
|
||||
|
||||
VendorCommandListener vendorCmdListener =
|
||||
new VendorCommandListener(sourceAddress, destAddress, params, vendorId);
|
||||
mHdmiControlServiceSpy.addVendorCommandListener(vendorCmdListener, vendorId);
|
||||
mTestLooper.dispatchAll();
|
||||
|
||||
HdmiCecMessage vendorCommandWithId =
|
||||
HdmiCecMessageBuilder.buildVendorCommandWithId(
|
||||
sourceAddress, destAddress, vendorId, params);
|
||||
mNativeWrapper.onCecMessage(vendorCommandWithId);
|
||||
mTestLooper.dispatchAll();
|
||||
assertThat(vendorCmdListener.mVendorCommandCallbackReceived).isTrue();
|
||||
assertThat(vendorCmdListener.mParamsCorrect).isTrue();
|
||||
assertThat(vendorCmdListener.mHasVendorId).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addVendorCommandListener_noCallback_VendorCmdDiffIdTest() {
|
||||
int destAddress = mHdmiControlServiceSpy.playback().getDeviceInfo().getLogicalAddress();
|
||||
int sourceAddress = Constants.ADDR_TV;
|
||||
byte[] params = {0x00, 0x01, 0x02, 0x03};
|
||||
int vendorId = 0x123456;
|
||||
int diffVendorId = 0x345678;
|
||||
|
||||
VendorCommandListener vendorCmdListener =
|
||||
new VendorCommandListener(sourceAddress, destAddress, params, vendorId);
|
||||
mHdmiControlServiceSpy.addVendorCommandListener(vendorCmdListener, vendorId);
|
||||
mTestLooper.dispatchAll();
|
||||
|
||||
HdmiCecMessage vendorCommandWithDiffId =
|
||||
HdmiCecMessageBuilder.buildVendorCommandWithId(
|
||||
sourceAddress, destAddress, diffVendorId, params);
|
||||
mNativeWrapper.onCecMessage(vendorCommandWithDiffId);
|
||||
mTestLooper.dispatchAll();
|
||||
assertThat(vendorCmdListener.mVendorCommandCallbackReceived).isFalse();
|
||||
}
|
||||
|
||||
private static class VendorCommandListener extends IHdmiVendorCommandListener.Stub {
|
||||
boolean mVendorCommandCallbackReceived = false;
|
||||
boolean mParamsCorrect = false;
|
||||
boolean mHasVendorId = false;
|
||||
|
||||
int mSourceAddress;
|
||||
int mDestAddress;
|
||||
byte[] mParams;
|
||||
int mVendorId;
|
||||
|
||||
VendorCommandListener(int sourceAddress, int destAddress, byte[] params, int vendorId) {
|
||||
this.mSourceAddress = sourceAddress;
|
||||
this.mDestAddress = destAddress;
|
||||
this.mParams = params.clone();
|
||||
this.mVendorId = vendorId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceived(
|
||||
int sourceAddress, int destAddress, byte[] params, boolean hasVendorId) {
|
||||
mVendorCommandCallbackReceived = true;
|
||||
if (mSourceAddress == sourceAddress && mDestAddress == destAddress) {
|
||||
byte[] expectedParams;
|
||||
if (hasVendorId) {
|
||||
// If the command has vendor ID, we have to add it to mParams.
|
||||
expectedParams = new byte[params.length];
|
||||
expectedParams[0] = (byte) ((mVendorId >> 16) & 0xFF);
|
||||
expectedParams[1] = (byte) ((mVendorId >> 8) & 0xFF);
|
||||
expectedParams[2] = (byte) (mVendorId & 0xFF);
|
||||
System.arraycopy(mParams, 0, expectedParams, 3, mParams.length);
|
||||
} else {
|
||||
expectedParams = params.clone();
|
||||
}
|
||||
if (Arrays.equals(expectedParams, params)) {
|
||||
mParamsCorrect = true;
|
||||
}
|
||||
}
|
||||
mHasVendorId = hasVendorId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onControlStateChanged(boolean enabled, int reason) {}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dispatchMessageToLocalDevice_broadcastMessage_returnsHandled() {
|
||||
HdmiCecMessage message = HdmiCecMessageBuilder.buildStandby(
|
||||
|
||||
Reference in New Issue
Block a user