Merge "Add new HDMI CEC messages"
This commit is contained in:
@@ -88,79 +88,84 @@ final class Constants {
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({
|
||||
MESSAGE_FEATURE_ABORT,
|
||||
MESSAGE_IMAGE_VIEW_ON,
|
||||
MESSAGE_TUNER_STEP_INCREMENT,
|
||||
MESSAGE_TUNER_STEP_DECREMENT,
|
||||
MESSAGE_TUNER_DEVICE_STATUS,
|
||||
MESSAGE_GIVE_TUNER_DEVICE_STATUS,
|
||||
MESSAGE_RECORD_ON,
|
||||
MESSAGE_RECORD_STATUS,
|
||||
MESSAGE_RECORD_OFF,
|
||||
MESSAGE_TEXT_VIEW_ON,
|
||||
MESSAGE_RECORD_TV_SCREEN,
|
||||
MESSAGE_GIVE_DECK_STATUS,
|
||||
MESSAGE_DECK_STATUS,
|
||||
MESSAGE_SET_MENU_LANGUAGE,
|
||||
MESSAGE_CLEAR_ANALOG_TIMER,
|
||||
MESSAGE_SET_ANALOG_TIMER,
|
||||
MESSAGE_TIMER_STATUS,
|
||||
MESSAGE_STANDBY,
|
||||
MESSAGE_PLAY,
|
||||
MESSAGE_DECK_CONTROL,
|
||||
MESSAGE_TIMER_CLEARED_STATUS,
|
||||
MESSAGE_USER_CONTROL_PRESSED,
|
||||
MESSAGE_USER_CONTROL_RELEASED,
|
||||
MESSAGE_GIVE_OSD_NAME,
|
||||
MESSAGE_SET_OSD_NAME,
|
||||
MESSAGE_SET_OSD_STRING,
|
||||
MESSAGE_SET_TIMER_PROGRAM_TITLE,
|
||||
MESSAGE_SYSTEM_AUDIO_MODE_REQUEST,
|
||||
MESSAGE_GIVE_AUDIO_STATUS,
|
||||
MESSAGE_SET_SYSTEM_AUDIO_MODE,
|
||||
MESSAGE_REPORT_AUDIO_STATUS,
|
||||
MESSAGE_GIVE_SYSTEM_AUDIO_MODE_STATUS,
|
||||
MESSAGE_SYSTEM_AUDIO_MODE_STATUS,
|
||||
MESSAGE_ROUTING_CHANGE,
|
||||
MESSAGE_ROUTING_INFORMATION,
|
||||
MESSAGE_ACTIVE_SOURCE,
|
||||
MESSAGE_GIVE_PHYSICAL_ADDRESS,
|
||||
MESSAGE_REPORT_PHYSICAL_ADDRESS,
|
||||
MESSAGE_REQUEST_ACTIVE_SOURCE,
|
||||
MESSAGE_SET_STREAM_PATH,
|
||||
MESSAGE_DEVICE_VENDOR_ID,
|
||||
MESSAGE_VENDOR_COMMAND,
|
||||
MESSAGE_VENDOR_REMOTE_BUTTON_DOWN,
|
||||
MESSAGE_VENDOR_REMOTE_BUTTON_UP,
|
||||
MESSAGE_GIVE_DEVICE_VENDOR_ID,
|
||||
MESSAGE_MENU_REQUEST,
|
||||
MESSAGE_MENU_STATUS,
|
||||
MESSAGE_GIVE_DEVICE_POWER_STATUS,
|
||||
MESSAGE_REPORT_POWER_STATUS,
|
||||
MESSAGE_GET_MENU_LANGUAGE,
|
||||
MESSAGE_SELECT_ANALOG_SERVICE,
|
||||
MESSAGE_SELECT_DIGITAL_SERVICE,
|
||||
MESSAGE_SET_DIGITAL_TIMER,
|
||||
MESSAGE_CLEAR_DIGITAL_TIMER,
|
||||
MESSAGE_SET_AUDIO_RATE,
|
||||
MESSAGE_INACTIVE_SOURCE,
|
||||
MESSAGE_CEC_VERSION,
|
||||
MESSAGE_GET_CEC_VERSION,
|
||||
MESSAGE_VENDOR_COMMAND_WITH_ID,
|
||||
MESSAGE_CLEAR_EXTERNAL_TIMER,
|
||||
MESSAGE_SET_EXTERNAL_TIMER,
|
||||
MESSAGE_REPORT_SHORT_AUDIO_DESCRIPTOR,
|
||||
MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR,
|
||||
MESSAGE_INITIATE_ARC,
|
||||
MESSAGE_REPORT_ARC_INITIATED,
|
||||
MESSAGE_REPORT_ARC_TERMINATED,
|
||||
MESSAGE_REQUEST_ARC_INITIATION,
|
||||
MESSAGE_REQUEST_ARC_TERMINATION,
|
||||
MESSAGE_TERMINATE_ARC,
|
||||
MESSAGE_CDC_MESSAGE,
|
||||
MESSAGE_ABORT,
|
||||
MESSAGE_FEATURE_ABORT,
|
||||
MESSAGE_IMAGE_VIEW_ON,
|
||||
MESSAGE_TUNER_STEP_INCREMENT,
|
||||
MESSAGE_TUNER_STEP_DECREMENT,
|
||||
MESSAGE_TUNER_DEVICE_STATUS,
|
||||
MESSAGE_GIVE_TUNER_DEVICE_STATUS,
|
||||
MESSAGE_RECORD_ON,
|
||||
MESSAGE_RECORD_STATUS,
|
||||
MESSAGE_RECORD_OFF,
|
||||
MESSAGE_TEXT_VIEW_ON,
|
||||
MESSAGE_RECORD_TV_SCREEN,
|
||||
MESSAGE_GIVE_DECK_STATUS,
|
||||
MESSAGE_DECK_STATUS,
|
||||
MESSAGE_SET_MENU_LANGUAGE,
|
||||
MESSAGE_CLEAR_ANALOG_TIMER,
|
||||
MESSAGE_SET_ANALOG_TIMER,
|
||||
MESSAGE_TIMER_STATUS,
|
||||
MESSAGE_STANDBY,
|
||||
MESSAGE_PLAY,
|
||||
MESSAGE_DECK_CONTROL,
|
||||
MESSAGE_TIMER_CLEARED_STATUS,
|
||||
MESSAGE_USER_CONTROL_PRESSED,
|
||||
MESSAGE_USER_CONTROL_RELEASED,
|
||||
MESSAGE_GIVE_OSD_NAME,
|
||||
MESSAGE_SET_OSD_NAME,
|
||||
MESSAGE_SET_OSD_STRING,
|
||||
MESSAGE_SET_TIMER_PROGRAM_TITLE,
|
||||
MESSAGE_SYSTEM_AUDIO_MODE_REQUEST,
|
||||
MESSAGE_GIVE_AUDIO_STATUS,
|
||||
MESSAGE_SET_SYSTEM_AUDIO_MODE,
|
||||
MESSAGE_REPORT_AUDIO_STATUS,
|
||||
MESSAGE_GIVE_SYSTEM_AUDIO_MODE_STATUS,
|
||||
MESSAGE_SYSTEM_AUDIO_MODE_STATUS,
|
||||
MESSAGE_ROUTING_CHANGE,
|
||||
MESSAGE_ROUTING_INFORMATION,
|
||||
MESSAGE_ACTIVE_SOURCE,
|
||||
MESSAGE_GIVE_PHYSICAL_ADDRESS,
|
||||
MESSAGE_REPORT_PHYSICAL_ADDRESS,
|
||||
MESSAGE_REQUEST_ACTIVE_SOURCE,
|
||||
MESSAGE_SET_STREAM_PATH,
|
||||
MESSAGE_DEVICE_VENDOR_ID,
|
||||
MESSAGE_VENDOR_COMMAND,
|
||||
MESSAGE_VENDOR_REMOTE_BUTTON_DOWN,
|
||||
MESSAGE_VENDOR_REMOTE_BUTTON_UP,
|
||||
MESSAGE_GIVE_DEVICE_VENDOR_ID,
|
||||
MESSAGE_MENU_REQUEST,
|
||||
MESSAGE_MENU_STATUS,
|
||||
MESSAGE_GIVE_DEVICE_POWER_STATUS,
|
||||
MESSAGE_REPORT_POWER_STATUS,
|
||||
MESSAGE_GET_MENU_LANGUAGE,
|
||||
MESSAGE_SELECT_ANALOG_SERVICE,
|
||||
MESSAGE_SELECT_DIGITAL_SERVICE,
|
||||
MESSAGE_SET_DIGITAL_TIMER,
|
||||
MESSAGE_CLEAR_DIGITAL_TIMER,
|
||||
MESSAGE_SET_AUDIO_RATE,
|
||||
MESSAGE_INACTIVE_SOURCE,
|
||||
MESSAGE_CEC_VERSION,
|
||||
MESSAGE_GET_CEC_VERSION,
|
||||
MESSAGE_VENDOR_COMMAND_WITH_ID,
|
||||
MESSAGE_CLEAR_EXTERNAL_TIMER,
|
||||
MESSAGE_SET_EXTERNAL_TIMER,
|
||||
MESSAGE_REPORT_SHORT_AUDIO_DESCRIPTOR,
|
||||
MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR,
|
||||
MESSAGE_GIVE_FEATURES,
|
||||
MESSAGE_REPORT_FEATURES,
|
||||
MESSAGE_REQUEST_CURRENT_LATENCY,
|
||||
MESSAGE_REPORT_CURRENT_LATENCY,
|
||||
MESSAGE_INITIATE_ARC,
|
||||
MESSAGE_REPORT_ARC_INITIATED,
|
||||
MESSAGE_REPORT_ARC_TERMINATED,
|
||||
MESSAGE_REQUEST_ARC_INITIATION,
|
||||
MESSAGE_REQUEST_ARC_TERMINATION,
|
||||
MESSAGE_TERMINATE_ARC,
|
||||
MESSAGE_CDC_MESSAGE,
|
||||
MESSAGE_ABORT,
|
||||
})
|
||||
public @interface FeatureOpcode {}
|
||||
public @interface FeatureOpcode {
|
||||
}
|
||||
|
||||
static final int MESSAGE_FEATURE_ABORT = 0x00;
|
||||
static final int MESSAGE_IMAGE_VIEW_ON = 0x04;
|
||||
@@ -225,6 +230,10 @@ final class Constants {
|
||||
static final int MESSAGE_SET_EXTERNAL_TIMER = 0xA2;
|
||||
static final int MESSAGE_REPORT_SHORT_AUDIO_DESCRIPTOR = 0xA3;
|
||||
static final int MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR = 0xA4;
|
||||
static final int MESSAGE_GIVE_FEATURES = 0xA5;
|
||||
static final int MESSAGE_REPORT_FEATURES = 0xA6;
|
||||
static final int MESSAGE_REQUEST_CURRENT_LATENCY = 0xA7;
|
||||
static final int MESSAGE_REPORT_CURRENT_LATENCY = 0xA8;
|
||||
static final int MESSAGE_INITIATE_ARC = 0xC0;
|
||||
static final int MESSAGE_REPORT_ARC_INITIATED = 0xC1;
|
||||
static final int MESSAGE_REPORT_ARC_TERMINATED = 0xC2;
|
||||
@@ -501,6 +510,35 @@ final class Constants {
|
||||
static final int VERSION_1_4 = 0x05;
|
||||
static final int VERSION_2_0 = 0x06;
|
||||
|
||||
static final int ALL_DEVICE_TYPES_TV = 7;
|
||||
static final int ALL_DEVICE_TYPES_RECORDER = 6;
|
||||
static final int ALL_DEVICE_TYPES_TUNER = 5;
|
||||
static final int ALL_DEVICE_TYPES_PLAYBACK = 4;
|
||||
static final int ALL_DEVICE_TYPES_AUDIO_SYSTEM = 3;
|
||||
static final int ALL_DEVICE_TYPES_SWITCH = 2;
|
||||
|
||||
static final int DEVICE_FEATURE_TV_SUPPORTS_RECORD_TV_SCREEN = 6;
|
||||
static final int DEVICE_FEATURE_TV_SUPPORTS_SET_OSD_STRING = 5;
|
||||
static final int DEVICE_FEATURE_SUPPORTS_DECK_CONTROL = 4;
|
||||
static final int DEVICE_FEATURE_SUPPORTS_SET_AUDIO_RATE = 3;
|
||||
static final int DEVICE_FEATURE_SINK_SUPPORTS_ARC_TX = 2;
|
||||
static final int DEVICE_FEATURE_SOURCE_SUPPORTS_ARC_RX = 1;
|
||||
|
||||
static final int RC_PROFILE_TV = 0;
|
||||
static final int RC_PROFILE_SOURCE = 1;
|
||||
|
||||
static final int RC_PROFILE_TV_NONE = 0x0;
|
||||
static final int RC_PROFILE_TV_ONE = 0x2;
|
||||
static final int RC_PROFILE_TV_TWO = 0x6;
|
||||
static final int RC_PROFILE_TV_THREE = 0xA;
|
||||
static final int RC_PROFILE_TV_FOUR = 0xE;
|
||||
|
||||
static final int RC_PROFILE_SOURCE_HANDLES_ROOT_MENU = 4;
|
||||
static final int RC_PROFILE_SOURCE_HANDLES_SETUP_MENU = 3;
|
||||
static final int RC_PROFILE_SOURCE_HANDLES_CONTENTS_MENU = 2;
|
||||
static final int RC_PROFILE_SOURCE_HANDLES_TOP_MENU = 1;
|
||||
static final int RC_PROFILE_SOURCE_HANDLES_MEDIA_CONTEXT_SENSITIVE_MENU = 0;
|
||||
|
||||
private Constants() {
|
||||
/* cannot be instantiated */
|
||||
}
|
||||
|
||||
@@ -351,6 +351,8 @@ abstract class HdmiCecLocalDevice {
|
||||
return handleRequestShortAudioDescriptor(message);
|
||||
case Constants.MESSAGE_REPORT_SHORT_AUDIO_DESCRIPTOR:
|
||||
return handleReportShortAudioDescriptor(message);
|
||||
case Constants.MESSAGE_GIVE_FEATURES:
|
||||
return handleGiveFeatures(message);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -551,6 +553,33 @@ abstract class HdmiCecLocalDevice {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected abstract int getRcProfile();
|
||||
|
||||
protected abstract List<Integer> getRcFeatures();
|
||||
|
||||
protected abstract List<Integer> getDeviceFeatures();
|
||||
|
||||
protected boolean handleGiveFeatures(HdmiCecMessage message) {
|
||||
if (mService.getCecVersion() < Constants.VERSION_2_0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Integer> localDeviceTypes = new ArrayList<>();
|
||||
for (HdmiCecLocalDevice localDevice : mService.getAllLocalDevices()) {
|
||||
localDeviceTypes.add(localDevice.mDeviceType);
|
||||
}
|
||||
|
||||
|
||||
int rcProfile = getRcProfile();
|
||||
List<Integer> rcFeatures = getRcFeatures();
|
||||
List<Integer> deviceFeatures = getDeviceFeatures();
|
||||
|
||||
mService.sendCecCommand(
|
||||
HdmiCecMessageBuilder.buildReportFeatures(mAddress, mService.getCecVersion(),
|
||||
localDeviceTypes, rcProfile, rcFeatures, deviceFeatures));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
protected boolean handleStandby(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
|
||||
@@ -47,6 +47,8 @@ import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
|
||||
import com.android.server.hdmi.HdmiUtils.CodecSad;
|
||||
import com.android.server.hdmi.HdmiUtils.DeviceConfig;
|
||||
|
||||
import com.google.android.collect.Lists;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.File;
|
||||
@@ -175,6 +177,11 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
|
||||
return info != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Integer> getDeviceFeatures() {
|
||||
return Lists.newArrayList(Constants.DEVICE_FEATURE_SOURCE_SUPPORTS_ARC_RX);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ServiceThreadOnly
|
||||
void onHotplug(int portId, boolean connected) {
|
||||
|
||||
@@ -28,6 +28,8 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.hdmi.Constants.LocalActivePort;
|
||||
import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
|
||||
|
||||
import com.google.android.collect.Lists;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -233,6 +235,24 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getRcProfile() {
|
||||
return Constants.RC_PROFILE_SOURCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Integer> getRcFeatures() {
|
||||
return Lists.newArrayList(Constants.RC_PROFILE_SOURCE_HANDLES_CONTENTS_MENU,
|
||||
Constants.RC_PROFILE_SOURCE_HANDLES_ROOT_MENU,
|
||||
Constants.RC_PROFILE_SOURCE_HANDLES_SETUP_MENU,
|
||||
Constants.RC_PROFILE_SOURCE_HANDLES_TOP_MENU);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Integer> getDeviceFeatures() {
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
|
||||
// Active source claiming needs to be handled in Service
|
||||
// since service can decide who will be the active source when the device supports
|
||||
// multiple device types in this method.
|
||||
|
||||
@@ -51,6 +51,8 @@ import com.android.server.hdmi.DeviceDiscoveryAction.DeviceDiscoveryCallback;
|
||||
import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
|
||||
import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
|
||||
|
||||
import com.google.android.collect.Lists;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -1478,6 +1480,22 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getRcProfile() {
|
||||
return Constants.RC_PROFILE_TV;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Integer> getRcFeatures() {
|
||||
return Lists.newArrayList(Constants.RC_PROFILE_TV_NONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Integer> getDeviceFeatures() {
|
||||
return Lists.newArrayList(Constants.DEVICE_FEATURE_SINK_SUPPORTS_ARC_TX,
|
||||
Constants.DEVICE_FEATURE_TV_SUPPORTS_RECORD_TV_SCREEN);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void sendStandby(int deviceId) {
|
||||
HdmiDeviceInfo targetDevice = mService.getHdmiCecNetwork().getDeviceInfo(deviceId);
|
||||
|
||||
@@ -18,6 +18,8 @@ package com.android.server.hdmi;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
|
||||
import com.android.server.hdmi.Constants.FeatureOpcode;
|
||||
|
||||
import libcore.util.EmptyArray;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -126,7 +128,7 @@ public final class HdmiCecMessage {
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
private static String opcodeToString(int opcode) {
|
||||
private static String opcodeToString(@FeatureOpcode int opcode) {
|
||||
switch (opcode) {
|
||||
case Constants.MESSAGE_FEATURE_ABORT:
|
||||
return "Feature Abort";
|
||||
@@ -264,6 +266,14 @@ public final class HdmiCecMessage {
|
||||
return "Request ARC Initiation";
|
||||
case Constants.MESSAGE_REQUEST_ARC_TERMINATION:
|
||||
return "Request ARC Termination";
|
||||
case Constants.MESSAGE_GIVE_FEATURES:
|
||||
return "Give Features";
|
||||
case Constants.MESSAGE_REPORT_FEATURES:
|
||||
return "Report Features";
|
||||
case Constants.MESSAGE_REQUEST_CURRENT_LATENCY:
|
||||
return "Request Current Latency";
|
||||
case Constants.MESSAGE_REPORT_CURRENT_LATENCY:
|
||||
return "Report Current Latency";
|
||||
case Constants.MESSAGE_TERMINATE_ARC:
|
||||
return "Terminate ARC";
|
||||
case Constants.MESSAGE_CDC_MESSAGE:
|
||||
|
||||
@@ -16,10 +16,14 @@
|
||||
|
||||
package com.android.server.hdmi;
|
||||
|
||||
import android.hardware.hdmi.HdmiDeviceInfo;
|
||||
|
||||
import com.android.server.hdmi.Constants.AudioCodec;
|
||||
import com.android.server.hdmi.Constants.CecVersion;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A helper class to build {@link HdmiCecMessage} from various cec commands.
|
||||
@@ -688,6 +692,40 @@ public class HdmiCecMessageBuilder {
|
||||
return buildCommand(src, dest, Constants.MESSAGE_CLEAR_EXTERNAL_TIMER, params);
|
||||
}
|
||||
|
||||
static HdmiCecMessage buildGiveFeatures(int src, int dest) {
|
||||
return buildCommand(src, dest, Constants.MESSAGE_GIVE_FEATURES);
|
||||
}
|
||||
|
||||
static HdmiCecMessage buildReportFeatures(int src, @CecVersion int cecVersion,
|
||||
List<Integer> allDeviceTypes, int rcProfile, List<Integer> rcFeatures,
|
||||
List<Integer> deviceFeatures) {
|
||||
byte cecVersionByte = (byte) (cecVersion & 0xFF);
|
||||
byte deviceTypes = 0;
|
||||
for (Integer deviceType : allDeviceTypes) {
|
||||
deviceTypes |= 1 << hdmiDeviceInfoDeviceTypeToShiftValue(deviceType);
|
||||
}
|
||||
|
||||
byte rcProfileByte = 0;
|
||||
rcProfileByte |= rcProfile << 6;
|
||||
if (rcProfile == Constants.RC_PROFILE_SOURCE) {
|
||||
for (Integer rcFeature : rcFeatures) {
|
||||
rcProfileByte |= 1 << rcFeature;
|
||||
}
|
||||
} else {
|
||||
byte rcProfileTv = (byte) (rcFeatures.get(0) & 0xFFFF);
|
||||
rcProfileByte |= rcProfileTv;
|
||||
}
|
||||
|
||||
byte deviceFeaturesByte = 0;
|
||||
for (Integer deviceFeature : deviceFeatures) {
|
||||
deviceFeaturesByte |= 1 << deviceFeature;
|
||||
}
|
||||
|
||||
byte[] params = {cecVersionByte, deviceTypes, rcProfileByte, deviceFeaturesByte};
|
||||
return buildCommand(src, Constants.ADDR_BROADCAST, Constants.MESSAGE_REPORT_FEATURES,
|
||||
params);
|
||||
}
|
||||
|
||||
/***** Please ADD new buildXXX() methods above. ******/
|
||||
|
||||
/**
|
||||
@@ -738,4 +776,23 @@ public class HdmiCecMessageBuilder {
|
||||
(byte) (physicalAddress & 0xFF)
|
||||
};
|
||||
}
|
||||
|
||||
private static int hdmiDeviceInfoDeviceTypeToShiftValue(int deviceType) {
|
||||
switch (deviceType) {
|
||||
case HdmiDeviceInfo.DEVICE_TV:
|
||||
return Constants.ALL_DEVICE_TYPES_TV;
|
||||
case HdmiDeviceInfo.DEVICE_RECORDER:
|
||||
return Constants.ALL_DEVICE_TYPES_RECORDER;
|
||||
case HdmiDeviceInfo.DEVICE_TUNER:
|
||||
return Constants.ALL_DEVICE_TYPES_TUNER;
|
||||
case HdmiDeviceInfo.DEVICE_PLAYBACK:
|
||||
return Constants.ALL_DEVICE_TYPES_PLAYBACK;
|
||||
case HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM:
|
||||
return Constants.ALL_DEVICE_TYPES_AUDIO_SYSTEM;
|
||||
case HdmiDeviceInfo.DEVICE_PURE_CEC_SWITCH:
|
||||
return Constants.ALL_DEVICE_TYPES_SWITCH;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unhandled device type: " + deviceType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,6 +211,17 @@ public class HdmiCecMessageValidator {
|
||||
new OneByteRangeValidator(0x00, 0x06),
|
||||
DEST_DIRECT);
|
||||
|
||||
// Messages for Feature Discovery.
|
||||
addValidationInfo(Constants.MESSAGE_GIVE_FEATURES, noneValidator, DEST_DIRECT);
|
||||
addValidationInfo(Constants.MESSAGE_REPORT_FEATURES, new VariableLengthValidator(4, 14),
|
||||
DEST_BROADCAST);
|
||||
|
||||
// Messages for Dynamic Auto Lipsync
|
||||
addValidationInfo(Constants.MESSAGE_REQUEST_CURRENT_LATENCY, physicalAddressValidator,
|
||||
DEST_BROADCAST);
|
||||
addValidationInfo(Constants.MESSAGE_REPORT_CURRENT_LATENCY,
|
||||
new VariableLengthValidator(4, 14), DEST_BROADCAST);
|
||||
|
||||
// All Messages for the ARC have no parameters.
|
||||
|
||||
// Messages for the Capability Discovery and Control.
|
||||
|
||||
@@ -42,6 +42,8 @@ import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@SmallTest
|
||||
@Presubmit
|
||||
@@ -80,6 +82,21 @@ public class HdmiCecLocalDeviceTest {
|
||||
|
||||
@Override
|
||||
protected void setPreferredAddress(int addr) {}
|
||||
|
||||
@Override
|
||||
protected int getRcProfile() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Integer> getRcFeatures() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Integer> getDeviceFeatures() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
private MyHdmiCecLocalDevice mHdmiLocalDevice;
|
||||
|
||||
@@ -26,10 +26,14 @@ import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.google.android.collect.Lists;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@SmallTest
|
||||
@Presubmit
|
||||
@RunWith(JUnit4.class)
|
||||
@@ -88,6 +92,98 @@ public class HdmiCecMessageBuilderTest {
|
||||
buildMessage("40:47:61:62:63:64:65:66:67:68:69:6A:6B:6C:6D:6E"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildGiveFeatures() {
|
||||
HdmiCecMessage message = HdmiCecMessageBuilder.buildGiveFeatures(ADDR_PLAYBACK_1, ADDR_TV);
|
||||
|
||||
assertThat(message).isEqualTo(buildMessage("40:A5"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildReportFeatures_basicTv_1_4() {
|
||||
HdmiCecMessage message = HdmiCecMessageBuilder.buildReportFeatures(ADDR_TV,
|
||||
Constants.VERSION_1_4,
|
||||
Lists.newArrayList(HdmiDeviceInfo.DEVICE_TV), Constants.RC_PROFILE_TV,
|
||||
Lists.newArrayList(Constants.RC_PROFILE_TV_NONE), Collections.emptyList());
|
||||
|
||||
assertThat(message).isEqualTo(buildMessage("0F:A6:05:80:00:00"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildReportFeatures_basicPlayback_1_4() {
|
||||
HdmiCecMessage message = HdmiCecMessageBuilder.buildReportFeatures(ADDR_PLAYBACK_1,
|
||||
Constants.VERSION_1_4,
|
||||
Lists.newArrayList(HdmiDeviceInfo.DEVICE_PLAYBACK), Constants.RC_PROFILE_TV,
|
||||
Lists.newArrayList(Constants.RC_PROFILE_TV_NONE), Collections.emptyList());
|
||||
|
||||
assertThat(message).isEqualTo(buildMessage("4F:A6:05:10:00:00"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildReportFeatures_basicPlaybackAudioSystem_1_4() {
|
||||
HdmiCecMessage message = HdmiCecMessageBuilder.buildReportFeatures(ADDR_PLAYBACK_1,
|
||||
Constants.VERSION_1_4,
|
||||
Lists.newArrayList(HdmiDeviceInfo.DEVICE_PLAYBACK,
|
||||
HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM), Constants.RC_PROFILE_TV,
|
||||
Lists.newArrayList(Constants.RC_PROFILE_TV_NONE), Collections.emptyList());
|
||||
|
||||
assertThat(message).isEqualTo(buildMessage("4F:A6:05:18:00:00"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildReportFeatures_basicTv_2_0() {
|
||||
HdmiCecMessage message = HdmiCecMessageBuilder.buildReportFeatures(ADDR_TV,
|
||||
Constants.VERSION_2_0,
|
||||
Lists.newArrayList(HdmiDeviceInfo.DEVICE_TV), Constants.RC_PROFILE_TV,
|
||||
Lists.newArrayList(Constants.RC_PROFILE_TV_NONE), Collections.emptyList());
|
||||
|
||||
assertThat(message).isEqualTo(buildMessage("0F:A6:06:80:00:00"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildReportFeatures_remoteControlTv_2_0() {
|
||||
HdmiCecMessage message = HdmiCecMessageBuilder.buildReportFeatures(ADDR_TV,
|
||||
Constants.VERSION_2_0,
|
||||
Lists.newArrayList(HdmiDeviceInfo.DEVICE_TV), Constants.RC_PROFILE_TV,
|
||||
Lists.newArrayList(Constants.RC_PROFILE_TV_ONE), Collections.emptyList());
|
||||
|
||||
assertThat(message).isEqualTo(buildMessage("0F:A6:06:80:02:00"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildReportFeatures_remoteControlPlayback_2_0() {
|
||||
HdmiCecMessage message = HdmiCecMessageBuilder.buildReportFeatures(ADDR_TV,
|
||||
Constants.VERSION_2_0,
|
||||
Lists.newArrayList(HdmiDeviceInfo.DEVICE_PLAYBACK), Constants.RC_PROFILE_SOURCE,
|
||||
Lists.newArrayList(Constants.RC_PROFILE_SOURCE_HANDLES_TOP_MENU,
|
||||
Constants.RC_PROFILE_SOURCE_HANDLES_SETUP_MENU), Collections.emptyList());
|
||||
|
||||
assertThat(message).isEqualTo(buildMessage("0F:A6:06:10:4A:00"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildReportFeatures_deviceFeaturesTv_2_0() {
|
||||
HdmiCecMessage message = HdmiCecMessageBuilder.buildReportFeatures(ADDR_TV,
|
||||
Constants.VERSION_2_0,
|
||||
Lists.newArrayList(HdmiDeviceInfo.DEVICE_TV), Constants.RC_PROFILE_TV,
|
||||
Lists.newArrayList(Constants.RC_PROFILE_TV_NONE),
|
||||
Lists.newArrayList(Constants.DEVICE_FEATURE_TV_SUPPORTS_RECORD_TV_SCREEN));
|
||||
|
||||
assertThat(message).isEqualTo(buildMessage("0F:A6:06:80:00:40"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildReportFeatures_deviceFeaturesPlayback_2_0() {
|
||||
HdmiCecMessage message = HdmiCecMessageBuilder.buildReportFeatures(ADDR_TV,
|
||||
Constants.VERSION_2_0,
|
||||
Lists.newArrayList(HdmiDeviceInfo.DEVICE_PLAYBACK), Constants.RC_PROFILE_SOURCE,
|
||||
Lists.newArrayList(Constants.RC_PROFILE_SOURCE_HANDLES_TOP_MENU,
|
||||
Constants.RC_PROFILE_SOURCE_HANDLES_SETUP_MENU),
|
||||
Lists.newArrayList(Constants.DEVICE_FEATURE_SUPPORTS_DECK_CONTROL));
|
||||
|
||||
assertThat(message).isEqualTo(buildMessage("0F:A6:06:10:4A:10"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a CEC message from a hex byte string with bytes separated by {@code :}.
|
||||
*
|
||||
@@ -100,7 +196,7 @@ public class HdmiCecMessageBuilderTest {
|
||||
int opcode = Integer.parseInt(parts[1], 16);
|
||||
byte[] params = new byte[parts.length - 2];
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
params[i] = Byte.parseByte(parts[i + 2], 16);
|
||||
params[i] = (byte) Integer.parseInt(parts[i + 2], 16);
|
||||
}
|
||||
return new HdmiCecMessage(src, dest, opcode, params);
|
||||
}
|
||||
|
||||
@@ -353,6 +353,24 @@ public class HdmiCecMessageValidatorTest {
|
||||
assertMessageValidity("40:35:EE:52:4A").isEqualTo(ERROR_PARAMETER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isValid_giveFeatures() {
|
||||
assertMessageValidity("40:A5").isEqualTo(OK);
|
||||
|
||||
assertMessageValidity("4F:A5").isEqualTo(ERROR_DESTINATION);
|
||||
assertMessageValidity("F0:A5").isEqualTo(ERROR_SOURCE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isValid_reportFeatures() {
|
||||
assertMessageValidity("0F:A6:05:80:00:00").isEqualTo(OK);
|
||||
|
||||
assertMessageValidity("04:A6:05:80:00:00").isEqualTo(ERROR_DESTINATION);
|
||||
assertMessageValidity("FF:A6:05:80:00:00").isEqualTo(ERROR_SOURCE);
|
||||
|
||||
assertMessageValidity("0F:A6").isEqualTo(ERROR_PARAMETER_SHORT);
|
||||
}
|
||||
|
||||
private IntegerSubject assertMessageValidity(String message) {
|
||||
return assertThat(mHdmiCecMessageValidator.isValid(buildMessage(message)));
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Tests for {@link HdmiControlServiceBinderAPITest} class.
|
||||
@@ -99,6 +101,21 @@ public class HdmiControlServiceBinderAPITest {
|
||||
protected void setCanGoToStandby(boolean canGoToStandby) {
|
||||
mCanGoToStandby = canGoToStandby;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getRcProfile() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Integer> getRcFeatures() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Integer> getDeviceFeatures() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
private static final String TAG = "HdmiControlServiceBinderAPITest";
|
||||
|
||||
@@ -54,6 +54,7 @@ import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Tests for {@link HdmiControlService} class.
|
||||
@@ -421,6 +422,42 @@ public class HdmiControlServiceTest {
|
||||
assertThat(mHdmiControlService.getCecVersion()).isEqualTo(Constants.VERSION_2_0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleGiveFeatures_cec14_featureAbort() {
|
||||
Settings.Global.putInt(mContextSpy.getContentResolver(), Settings.Global.HDMI_CEC_VERSION,
|
||||
Constants.VERSION_1_4);
|
||||
mHdmiControlService.setControlEnabled(true);
|
||||
mTestLooper.dispatchAll();
|
||||
|
||||
mNativeWrapper.onCecMessage(HdmiCecMessageBuilder.buildGiveFeatures(Constants.ADDR_TV,
|
||||
Constants.ADDR_PLAYBACK_1));
|
||||
mTestLooper.dispatchAll();
|
||||
|
||||
HdmiCecMessage featureAbort = HdmiCecMessageBuilder.buildFeatureAbortCommand(
|
||||
Constants.ADDR_PLAYBACK_1, Constants.ADDR_TV, Constants.MESSAGE_GIVE_FEATURES,
|
||||
Constants.ABORT_UNRECOGNIZED_OPCODE);
|
||||
assertThat(mNativeWrapper.getResultMessages()).contains(featureAbort);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleGiveFeatures_cec20_reportsFeatures() {
|
||||
Settings.Global.putInt(mContextSpy.getContentResolver(), Settings.Global.HDMI_CEC_VERSION,
|
||||
Constants.VERSION_2_0);
|
||||
mHdmiControlService.setControlEnabled(true);
|
||||
mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
|
||||
mTestLooper.dispatchAll();
|
||||
|
||||
mNativeWrapper.onCecMessage(HdmiCecMessageBuilder.buildGiveFeatures(Constants.ADDR_TV,
|
||||
Constants.ADDR_PLAYBACK_1));
|
||||
mTestLooper.dispatchAll();
|
||||
|
||||
HdmiCecMessage reportFeatures = HdmiCecMessageBuilder.buildReportFeatures(
|
||||
Constants.ADDR_PLAYBACK_1, Constants.VERSION_2_0,
|
||||
Arrays.asList(DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM),
|
||||
mMyPlaybackDevice.getRcProfile(), mMyPlaybackDevice.getRcFeatures(),
|
||||
mMyPlaybackDevice.getDeviceFeatures());
|
||||
assertThat(mNativeWrapper.getResultMessages()).contains(reportFeatures);
|
||||
}
|
||||
|
||||
private static class VolumeControlFeatureCallback extends
|
||||
IHdmiCecVolumeControlFeatureListener.Stub {
|
||||
|
||||
Reference in New Issue
Block a user