Merge "CEC: Make HDMI CEC volume control configurable" into rvc-dev

This commit is contained in:
TreeHugger Robot
2020-04-27 12:26:23 +00:00
committed by Android (Google) Code Review
13 changed files with 452 additions and 6 deletions

View File

@@ -649,6 +649,68 @@ public final class HdmiControlManager {
}
}
/**
* Controls whether volume control commands via HDMI CEC are enabled.
*
* <p>When disabled:
* <ul>
* <li>the device will not send any HDMI CEC audio messages
* <li>received HDMI CEC audio messages are responded to with {@code <Feature Abort>}
* </ul>
*
* <p>Effects on different device types:
* <table>
* <tr><th>HDMI CEC device type</th><th>enabled</th><th>disabled</th></tr>
* <tr>
* <td>TV (type: 0)</td>
* <td>Per CEC specification.</td>
* <td>TV changes system volume. TV no longer reacts to incoming volume changes via
* {@code <User Control Pressed>}. TV no longer handles {@code <Report Audio Status>}
* .</td>
* </tr>
* <tr>
* <td>Playback device (type: 4)</td>
* <td>Device sends volume commands to TV/Audio system via {@code <User Control
* Pressed>}</td><td>Device does not send volume commands via {@code <User Control
* Pressed>}.</td>
* </tr>
* <tr>
* <td>Audio device (type: 5)</td>
* <td>Full "System Audio Control" capabilities.</td>
* <td>Audio device no longer reacts to incoming {@code <User Control Pressed>}
* volume commands. Audio device no longer reports volume changes via {@code <Report
* Audio Status>}.</td>
* </tr>
* </table>
*
* <p> Due to the resulting behavior, usage on TV and Audio devices is discouraged.
*
* @param isHdmiCecVolumeControlEnabled target state of HDMI CEC volume control.
* @see Settings.Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED
* @hide
*/
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
public void setHdmiCecVolumeControlEnabled(boolean isHdmiCecVolumeControlEnabled) {
try {
mService.setHdmiCecVolumeControlEnabled(isHdmiCecVolumeControlEnabled);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Returns whether volume changes via HDMI CEC are enabled.
* @hide
*/
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
public boolean isHdmiCecVolumeControlEnabled() {
try {
return mService.isHdmiCecVolumeControlEnabled();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Gets whether the system is in system audio mode.
*

View File

@@ -80,6 +80,8 @@ interface IHdmiControlService {
void sendMhlVendorCommand(int portId, int offset, int length, in byte[] data);
void addHdmiMhlVendorCommandListener(IHdmiMhlVendorCommandListener listener);
void setStandbyMode(boolean isStandbyModeOn);
void setHdmiCecVolumeControlEnabled(boolean isHdmiCecVolumeControlEnabled);
boolean isHdmiCecVolumeControlEnabled();
void reportAudioStatus(int deviceType, int volume, int maxVolume, boolean isMute);
void setSystemAudioModeOnForAudioOnlySource();
}

View File

@@ -9614,6 +9614,43 @@ public final class Settings {
*/
public static final String HDMI_CONTROL_ENABLED = "hdmi_control_enabled";
/**
* Controls whether volume control commands via HDMI CEC are enabled. (0 = false, 1 =
* true).
*
* <p>Effects on different device types:
* <table>
* <tr><th>HDMI CEC device type</th><th>0: disabled</th><th>1: enabled</th></tr>
* <tr>
* <td>TV (type: 0)</td>
* <td>Per CEC specification.</td>
* <td>TV changes system volume. TV no longer reacts to incoming volume changes
* via {@code <User Control Pressed>}. TV no longer handles {@code <Report Audio
* Status>}.</td>
* </tr>
* <tr>
* <td>Playback device (type: 4)</td>
* <td>Device sends volume commands to TV/Audio system via {@code <User Control
* Pressed>}</td>
* <td>Device does not send volume commands via {@code <User Control Pressed>}.</td>
* </tr>
* <tr>
* <td>Audio device (type: 5)</td>
* <td>Full "System Audio Control" capabilities.</td>
* <td>Audio device no longer reacts to incoming {@code <User Control Pressed>}
* volume commands. Audio device no longer reports volume changes via {@code
* <Report Audio Status>}.</td>
* </tr>
* </table>
*
* <p> Due to the resulting behavior, usage on TV and Audio devices is discouraged.
*
* @hide
* @see android.hardware.hdmi.HdmiControlManager#setHdmiCecVolumeControlEnabled(boolean)
*/
public static final String HDMI_CONTROL_VOLUME_CONTROL_ENABLED =
"hdmi_control_volume_control_enabled";
/**
* Whether HDMI System Audio Control feature is enabled. If enabled, TV will try to turn on
* system audio mode if there's a connected CEC-enabled AV Receiver. Then audio stream will

View File

@@ -354,6 +354,15 @@ public class HdmiAudioSystemClientTest {
@Override
public void askRemoteDeviceToBecomeActiveSource(int physicalAddress) {
}
@Override
public void setHdmiCecVolumeControlEnabled(boolean isHdmiCecVolumeControlEnabled) {
}
@Override
public boolean isHdmiCecVolumeControlEnabled() {
return true;
}
}
}

View File

@@ -296,6 +296,7 @@ public class SettingsBackupTest {
Settings.Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED,
Settings.Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED,
Settings.Global.HDMI_CONTROL_ENABLED,
Settings.Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED,
Settings.Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED,
Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED,
Settings.Global.HIDDEN_API_POLICY,

View File

@@ -32,6 +32,7 @@ import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.hdmi.Constants.LocalActivePort;
import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
@@ -144,7 +145,8 @@ abstract class HdmiCecLocalDevice {
// A collection of FeatureAction.
// Note that access to this collection should happen in service thread.
private final ArrayList<HdmiCecFeatureAction> mActions = new ArrayList<>();
@VisibleForTesting
final ArrayList<HdmiCecFeatureAction> mActions = new ArrayList<>();
private final Handler mHandler =
new Handler() {
@@ -544,6 +546,8 @@ abstract class HdmiCecLocalDevice {
} else if (mService.isPowerStandbyOrTransient() && isPowerOnOrToggleCommand(message)) {
mService.wakeUp();
return true;
} else if (!mService.isHdmiCecVolumeControlEnabled() && isVolumeOrMuteCommand(message)) {
return false;
}
final long downTime = SystemClock.uptimeMillis();
@@ -618,6 +622,16 @@ abstract class HdmiCecLocalDevice {
|| params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION);
}
static boolean isVolumeOrMuteCommand(HdmiCecMessage message) {
byte[] params = message.getParams();
return message.getOpcode() == Constants.MESSAGE_USER_CONTROL_PRESSED
&& (params[0] == HdmiCecKeycode.CEC_KEYCODE_VOLUME_DOWN
|| params[0] == HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP
|| params[0] == HdmiCecKeycode.CEC_KEYCODE_MUTE
|| params[0] == HdmiCecKeycode.CEC_KEYCODE_MUTE_FUNCTION
|| params[0] == HdmiCecKeycode.CEC_KEYCODE_RESTORE_VOLUME_FUNCTION);
}
protected boolean handleTextViewOn(HdmiCecMessage message) {
return false;
}
@@ -1038,6 +1052,9 @@ abstract class HdmiCecLocalDevice {
@ServiceThreadOnly
protected void sendVolumeKeyEvent(int keyCode, boolean isPressed) {
assertRunOnServiceThread();
if (!mService.isHdmiCecVolumeControlEnabled()) {
return;
}
if (!HdmiCecKeycode.isVolumeKeycode(keyCode)) {
Slog.w(TAG, "Not a volume key: " + keyCode);
return;

View File

@@ -575,7 +575,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
@ServiceThreadOnly
protected boolean handleGiveAudioStatus(HdmiCecMessage message) {
assertRunOnServiceThread();
if (isSystemAudioControlFeatureEnabled()) {
if (isSystemAudioControlFeatureEnabled() && mService.isHdmiCecVolumeControlEnabled()) {
reportAudioStatus(message.getSource());
} else {
mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED);
@@ -930,6 +930,9 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
void reportAudioStatus(int source) {
assertRunOnServiceThread();
if (!mService.isHdmiCecVolumeControlEnabled()) {
return;
}
int volume = mService.getAudioManager().getStreamVolume(AudioManager.STREAM_MUSIC);
boolean mute = mService.getAudioManager().isStreamMute(AudioManager.STREAM_MUSIC);

View File

@@ -678,6 +678,9 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
@ServiceThreadOnly
protected boolean handleReportAudioStatus(HdmiCecMessage message) {
assertRunOnServiceThread();
if (!mService.isHdmiCecVolumeControlEnabled()) {
return false;
}
boolean mute = HdmiUtils.isAudioStatusMute(message);
int volume = HdmiUtils.getAudioStatusVolume(message);
@@ -987,7 +990,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
}
void setAudioStatus(boolean mute, int volume) {
if (!isSystemAudioActivated()) {
if (!isSystemAudioActivated() || !mService.isHdmiCecVolumeControlEnabled()) {
return;
}
synchronized (mLock) {
@@ -1009,7 +1012,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
// On initialization process, getAvrDeviceInfo() may return null and cause exception
return;
}
if (delta == 0 || !isSystemAudioActivated()) {
if (delta == 0 || !isSystemAudioActivated() || !mService.isHdmiCecVolumeControlEnabled()) {
return;
}
@@ -1038,7 +1041,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
@ServiceThreadOnly
void changeMute(boolean mute) {
assertRunOnServiceThread();
if (getAvrDeviceInfo() == null) {
if (getAvrDeviceInfo() == null || !mService.isHdmiCecVolumeControlEnabled()) {
// On initialization process, getAvrDeviceInfo() may return null and cause exception
return;
}

View File

@@ -177,6 +177,10 @@ public class HdmiControlService extends SystemService {
@GuardedBy("mLock")
protected final ActiveSource mActiveSource = new ActiveSource();
// Whether HDMI CEC volume control is enabled or not.
@GuardedBy("mLock")
private boolean mHdmiCecVolumeControlEnabled;
// Whether System Audio Mode is activated or not.
@GuardedBy("mLock")
private boolean mSystemAudioActivated = false;
@@ -497,6 +501,8 @@ public class HdmiControlService extends SystemService {
mPowerStatus = getInitialPowerStatus();
mProhibitMode = false;
mHdmiControlEnabled = readBooleanSetting(Global.HDMI_CONTROL_ENABLED, true);
mHdmiCecVolumeControlEnabled = readBooleanSetting(
Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED, true);
mMhlInputChangeEnabled = readBooleanSetting(Global.MHL_INPUT_SWITCHING_ENABLED, true);
if (mCecController == null) {
@@ -646,6 +652,7 @@ public class HdmiControlService extends SystemService {
ContentResolver resolver = getContext().getContentResolver();
String[] settings = new String[] {
Global.HDMI_CONTROL_ENABLED,
Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED,
Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED,
Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED,
Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED,
@@ -674,6 +681,9 @@ public class HdmiControlService extends SystemService {
case Global.HDMI_CONTROL_ENABLED:
setControlEnabled(enabled);
break;
case Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED:
setHdmiCecVolumeControlEnabled(enabled);
break;
case Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED:
if (isTvDeviceEnabled()) {
tv().setAutoWakeup(enabled);
@@ -1273,7 +1283,9 @@ public class HdmiControlService extends SystemService {
}
void setAudioStatus(boolean mute, int volume) {
if (!isTvDeviceEnabled() || !tv().isSystemAudioActivated()) {
if (!isTvDeviceEnabled()
|| !tv().isSystemAudioActivated()
|| !isHdmiCecVolumeControlEnabled()) {
return;
}
AudioManager audioManager = getAudioManager();
@@ -2186,6 +2198,24 @@ public class HdmiControlService extends SystemService {
});
}
@Override
public boolean isHdmiCecVolumeControlEnabled() {
enforceAccessPermission();
return HdmiControlService.this.isHdmiCecVolumeControlEnabled();
}
@Override
public void setHdmiCecVolumeControlEnabled(final boolean isHdmiCecVolumeControlEnabled) {
enforceAccessPermission();
runOnServiceThread(new Runnable() {
@Override
public void run() {
HdmiControlService.this.setHdmiCecVolumeControlEnabled(
isHdmiCecVolumeControlEnabled);
}
});
}
@Override
public void reportAudioStatus(final int deviceType, final int volume, final int maxVolume,
final boolean isMute) {
@@ -2250,6 +2280,7 @@ public class HdmiControlService extends SystemService {
pw.println("mHdmiControlEnabled: " + mHdmiControlEnabled);
pw.println("mMhlInputChangeEnabled: " + mMhlInputChangeEnabled);
pw.println("mSystemAudioActivated: " + isSystemAudioActivated());
pw.println("mHdmiCecVolumeControlEnabled " + mHdmiCecVolumeControlEnabled);
pw.decreaseIndent();
pw.println("mMhlController: ");
@@ -2982,6 +3013,29 @@ public class HdmiControlService extends SystemService {
}
}
void setHdmiCecVolumeControlEnabled(boolean isHdmiCecVolumeControlEnabled) {
assertRunOnServiceThread();
synchronized (mLock) {
mHdmiCecVolumeControlEnabled = isHdmiCecVolumeControlEnabled;
boolean storedValue = readBooleanSetting(Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED,
true);
if (storedValue != isHdmiCecVolumeControlEnabled) {
HdmiLogger.debug("Changing HDMI CEC volume control feature state: %s",
isHdmiCecVolumeControlEnabled);
writeBooleanSetting(Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED,
isHdmiCecVolumeControlEnabled);
}
}
}
boolean isHdmiCecVolumeControlEnabled() {
assertRunOnServiceThread();
synchronized (mLock) {
return mHdmiCecVolumeControlEnabled;
}
}
boolean isProhibitMode() {
synchronized (mLock) {
return mProhibitMode;
@@ -3022,8 +3076,12 @@ public class HdmiControlService extends SystemService {
if (enabled) {
enableHdmiControlService();
setHdmiCecVolumeControlEnabled(
readBooleanSetting(Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED, true));
return;
}
setHdmiCecVolumeControlEnabled(false);
// Call the vendor handler before the service is disabled.
invokeVendorCommandListenersOnControlStateChanged(false,
HdmiControlManager.CONTROL_STATE_CHANGED_REASON_SETTING);

View File

@@ -24,6 +24,7 @@ import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_1;
import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_2;
import static com.android.server.hdmi.Constants.ADDR_TUNER_1;
import static com.android.server.hdmi.Constants.ADDR_TV;
import static com.android.server.hdmi.Constants.MESSAGE_GIVE_AUDIO_STATUS;
import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
import static com.android.server.hdmi.HdmiControlService.STANDBY_SCREEN_OFF;
@@ -47,6 +48,7 @@ import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.util.ArrayList;
@SmallTest
@RunWith(JUnit4.class)
/** Tests for {@link HdmiCecLocalDeviceAudioSystem} class. */
@@ -167,6 +169,8 @@ public class HdmiCecLocalDeviceAudioSystemTest {
}
};
mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
mMyLooper = mTestLooper.getLooper();
mHdmiCecLocalDeviceAudioSystem = new HdmiCecLocalDeviceAudioSystem(mHdmiControlService);
mHdmiCecLocalDevicePlayback = new HdmiCecLocalDevicePlayback(mHdmiControlService) {
@@ -717,4 +721,112 @@ public class HdmiCecLocalDeviceAudioSystemTest {
mHdmiCecLocalDeviceAudioSystem.onHotplug(0, false);
assertThat(mWokenUp).isFalse();
}
@Test
public void giveAudioStatus_volumeEnabled() {
mMusicVolume = 50;
mMusicMaxVolume = 100;
mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
mHdmiCecLocalDeviceAudioSystem.setSystemAudioControlFeatureEnabled(true);
int volume = mHdmiControlService.getAudioManager()
.getStreamVolume(AudioManager.STREAM_MUSIC);
boolean mute = mHdmiControlService.getAudioManager()
.isStreamMute(AudioManager.STREAM_MUSIC);
int maxVolume = mHdmiControlService.getAudioManager()
.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
int scaledVolume = VolumeControlAction.scaleToCecVolume(volume, maxVolume);
HdmiCecMessage expected = HdmiCecMessageBuilder.buildReportAudioStatus(ADDR_AUDIO_SYSTEM,
ADDR_TV, scaledVolume, mute);
HdmiCecMessage featureAbort = HdmiCecMessageBuilder.buildFeatureAbortCommand(
ADDR_AUDIO_SYSTEM, ADDR_TV, MESSAGE_GIVE_AUDIO_STATUS, Constants.ABORT_REFUSED);
HdmiCecMessage giveAudioStatus = HdmiCecMessageBuilder.buildGiveAudioStatus(ADDR_TV,
ADDR_AUDIO_SYSTEM);
mNativeWrapper.clearResultMessages();
boolean handled = mHdmiCecLocalDeviceAudioSystem.handleGiveAudioStatus(giveAudioStatus);
mTestLooper.dispatchAll();
assertThat(mNativeWrapper.getResultMessages()).contains(expected);
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(featureAbort);
assertThat(handled).isTrue();
}
@Test
public void giveAudioStatus_volumeDisabled() {
mMusicVolume = 50;
mMusicMaxVolume = 100;
mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
mHdmiCecLocalDeviceAudioSystem.setSystemAudioControlFeatureEnabled(true);
int volume = mHdmiControlService.getAudioManager()
.getStreamVolume(AudioManager.STREAM_MUSIC);
boolean mute = mHdmiControlService.getAudioManager()
.isStreamMute(AudioManager.STREAM_MUSIC);
int maxVolume = mHdmiControlService.getAudioManager()
.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
int scaledVolume = VolumeControlAction.scaleToCecVolume(volume, maxVolume);
HdmiCecMessage unexpected = HdmiCecMessageBuilder.buildReportAudioStatus(ADDR_AUDIO_SYSTEM,
ADDR_TV, scaledVolume, mute);
HdmiCecMessage featureAbort = HdmiCecMessageBuilder.buildFeatureAbortCommand(
ADDR_AUDIO_SYSTEM, ADDR_TV, MESSAGE_GIVE_AUDIO_STATUS, Constants.ABORT_REFUSED);
HdmiCecMessage giveAudioStatus = HdmiCecMessageBuilder.buildGiveAudioStatus(ADDR_TV,
ADDR_AUDIO_SYSTEM);
mNativeWrapper.clearResultMessages();
boolean handled = mHdmiCecLocalDeviceAudioSystem.handleGiveAudioStatus(giveAudioStatus);
mTestLooper.dispatchAll();
assertThat(mNativeWrapper.getResultMessages()).contains(featureAbort);
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(unexpected);
assertThat(handled).isTrue();
}
@Test
public void reportAudioStatus_volumeEnabled() {
mMusicVolume = 50;
mMusicMaxVolume = 100;
mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
mHdmiCecLocalDeviceAudioSystem.setSystemAudioControlFeatureEnabled(true);
int volume = mHdmiControlService.getAudioManager()
.getStreamVolume(AudioManager.STREAM_MUSIC);
boolean mute = mHdmiControlService.getAudioManager()
.isStreamMute(AudioManager.STREAM_MUSIC);
int maxVolume = mHdmiControlService.getAudioManager()
.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
int scaledVolume = VolumeControlAction.scaleToCecVolume(volume, maxVolume);
HdmiCecMessage expected = HdmiCecMessageBuilder.buildReportAudioStatus(ADDR_AUDIO_SYSTEM,
ADDR_TV, scaledVolume, mute);
mNativeWrapper.clearResultMessages();
mHdmiCecLocalDeviceAudioSystem.reportAudioStatus(ADDR_TV);
mTestLooper.dispatchAll();
assertThat(mNativeWrapper.getResultMessages()).contains(expected);
}
@Test
public void reportAudioStatus_volumeDisabled() {
mMusicVolume = 50;
mMusicMaxVolume = 100;
mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
mHdmiCecLocalDeviceAudioSystem.setSystemAudioControlFeatureEnabled(true);
int volume = mHdmiControlService.getAudioManager()
.getStreamVolume(AudioManager.STREAM_MUSIC);
boolean mute = mHdmiControlService.getAudioManager()
.isStreamMute(AudioManager.STREAM_MUSIC);
int maxVolume = mHdmiControlService.getAudioManager()
.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
int scaledVolume = VolumeControlAction.scaleToCecVolume(volume, maxVolume);
HdmiCecMessage unexpected = HdmiCecMessageBuilder.buildReportAudioStatus(ADDR_AUDIO_SYSTEM,
ADDR_TV, scaledVolume, mute);
mNativeWrapper.clearResultMessages();
mHdmiCecLocalDeviceAudioSystem.reportAudioStatus(ADDR_TV);
mTestLooper.dispatchAll();
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(unexpected);
}
}

View File

@@ -22,6 +22,7 @@ import static com.google.common.truth.Truth.assertThat;
import android.os.Looper;
import android.os.test.TestLooper;
import android.view.KeyEvent;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -153,4 +154,75 @@ public class HdmiCecLocalDevicePlaybackTest {
mHdmiCecLocalDevicePlayback.onHotplug(0, false);
assertThat(mWokenUp).isFalse();
}
@Test
@Ignore("b/151147315")
public void sendVolumeKeyEvent_up_volumeEnabled() {
mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, true);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, false);
assertThat(hasSendKeyAction()).isTrue();
}
@Test
@Ignore("b/151147315")
public void sendVolumeKeyEvent_down_volumeEnabled() {
mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_DOWN, true);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_DOWN, false);
assertThat(hasSendKeyAction()).isTrue();
}
@Test
@Ignore("b/151147315")
public void sendVolumeKeyEvent_mute_volumeEnabled() {
mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_MUTE, true);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_MUTE, false);
assertThat(hasSendKeyAction()).isTrue();
}
@Test
@Ignore("b/151147315")
public void sendVolumeKeyEvent_up_volumeDisabled() {
mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, true);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, false);
assertThat(hasSendKeyAction()).isFalse();
}
@Test
@Ignore("b/151147315")
public void sendVolumeKeyEvent_down_volumeDisabled() {
mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_DOWN, true);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_DOWN, false);
assertThat(hasSendKeyAction()).isFalse();
}
@Test
@Ignore("b/151147315")
public void sendVolumeKeyEvent_mute_volumeDisabled() {
mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_MUTE, true);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_MUTE, false);
assertThat(hasSendKeyAction()).isFalse();
}
private boolean hasSendKeyAction() {
boolean match = false;
for (HdmiCecFeatureAction action : mHdmiCecLocalDevicePlayback.mActions) {
if (action instanceof SendKeyAction) {
match = true;
break;
}
}
return match;
}
}

View File

@@ -19,6 +19,7 @@ import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_TV;
import static com.android.server.hdmi.Constants.ADDR_AUDIO_SYSTEM;
import static com.android.server.hdmi.Constants.ADDR_BROADCAST;
import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_1;
import static com.android.server.hdmi.Constants.ADDR_TV;
import static com.android.server.hdmi.Constants.ADDR_UNREGISTERED;
import static com.android.server.hdmi.Constants.MESSAGE_DEVICE_VENDOR_ID;
@@ -185,4 +186,64 @@ public class HdmiCecLocalDeviceTest {
HdmiCecMessageBuilder.buildStandby(ADDR_TV, ADDR_AUDIO_SYSTEM));
assertTrue(mStandbyMessageReceived);
}
@Test
public void handleUserControlPressed_volumeUp() {
mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
boolean result = mHdmiLocalDevice.handleUserControlPressed(
HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP));
assertTrue(result);
}
@Test
public void handleUserControlPressed_volumeDown() {
mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
boolean result = mHdmiLocalDevice.handleUserControlPressed(
HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
HdmiCecKeycode.CEC_KEYCODE_VOLUME_DOWN));
assertTrue(result);
}
@Test
public void handleUserControlPressed_volumeMute() {
mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
boolean result = mHdmiLocalDevice.handleUserControlPressed(
HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
HdmiCecKeycode.CEC_KEYCODE_MUTE));
assertTrue(result);
}
@Test
public void handleUserControlPressed_volumeUp_disabled() {
mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
boolean result = mHdmiLocalDevice.handleUserControlPressed(
HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP));
assertFalse(result);
}
@Test
public void handleUserControlPressed_volumeDown_disabled() {
mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
boolean result = mHdmiLocalDevice.handleUserControlPressed(
HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
HdmiCecKeycode.CEC_KEYCODE_VOLUME_DOWN));
assertFalse(result);
}
@Test
public void handleUserControlPressed_volumeMute_disabled() {
mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
boolean result = mHdmiLocalDevice.handleUserControlPressed(
HdmiCecMessageBuilder.buildUserControlPressed(ADDR_PLAYBACK_1, ADDR_TV,
HdmiCecKeycode.CEC_KEYCODE_MUTE));
assertFalse(result);
}
}

View File

@@ -252,4 +252,13 @@ public class HdmiControlServiceTest {
assertThat(mHdmiControlService.getPowerStatus()).isEqualTo(
HdmiControlManager.POWER_STATUS_STANDBY);
}
@Test
public void setAndGetCecVolumeControlEnabled_isApi() {
mHdmiControlService.setHdmiCecVolumeControlEnabled(false);
assertThat(mHdmiControlService.isHdmiCecVolumeControlEnabled()).isFalse();
mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
assertThat(mHdmiControlService.isHdmiCecVolumeControlEnabled()).isTrue();
}
}