Merge changes I5ac00d59,I41a59081,I63c7cf35
* changes: [CEC Configuration] Fix race condition with listeners [2.0] Disable sending <User Control Pressed> in attempts to change the active source to a 2.0 device [CEC Configuration] Add 'tv_wake_on_one_touch_play' option
This commit is contained in:
@@ -480,6 +480,28 @@ public final class HdmiControlManager {
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface VolumeControl {}
|
||||
|
||||
// -- Whether TV Wake on One Touch Play is enabled or disabled.
|
||||
/**
|
||||
* TV Wake on One Touch Play enabled.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int TV_WAKE_ON_ONE_TOUCH_PLAY_ENABLED = 1;
|
||||
/**
|
||||
* TV Wake on One Touch Play disabled.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int TV_WAKE_ON_ONE_TOUCH_PLAY_DISABLED = 0;
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@IntDef(prefix = { "TV_WAKE_ON_ONE_TOUCH_PLAY_" }, value = {
|
||||
TV_WAKE_ON_ONE_TOUCH_PLAY_ENABLED,
|
||||
TV_WAKE_ON_ONE_TOUCH_PLAY_DISABLED
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface TvWakeOnOneTouchPlay {}
|
||||
|
||||
// -- Settings available in the CEC Configuration.
|
||||
/**
|
||||
@@ -519,7 +541,6 @@ public final class HdmiControlManager {
|
||||
@SystemApi
|
||||
public static final String CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING =
|
||||
"system_audio_mode_muting";
|
||||
|
||||
/**
|
||||
* Controls whether volume control commands via HDMI CEC are enabled.
|
||||
*
|
||||
@@ -555,7 +576,14 @@ public final class HdmiControlManager {
|
||||
*/
|
||||
public static final String CEC_SETTING_NAME_VOLUME_CONTROL_MODE =
|
||||
"volume_control_enabled";
|
||||
|
||||
/**
|
||||
* Name of a setting deciding whether the TV will automatically turn on upon reception
|
||||
* of the CEC command <Text View On> or <Image View On>.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY =
|
||||
"tv_wake_on_one_touch_play";
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@@ -566,6 +594,7 @@ public final class HdmiControlManager {
|
||||
CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST,
|
||||
CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING,
|
||||
CEC_SETTING_NAME_VOLUME_CONTROL_MODE,
|
||||
CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY,
|
||||
})
|
||||
public @interface CecSettingName {}
|
||||
|
||||
@@ -1869,4 +1898,48 @@ public final class HdmiControlManager {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current status of TV Wake on One Touch Play.
|
||||
*
|
||||
* <p>Sets whether the TV should wake up upon reception of <Text View On>
|
||||
* or <Image View On>.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
|
||||
public void setTvWakeOnOneTouchPlay(@NonNull @TvWakeOnOneTouchPlay int value) {
|
||||
if (mService == null) {
|
||||
Log.e(TAG, "HdmiControlService is not available");
|
||||
throw new RuntimeException("HdmiControlService is not available");
|
||||
}
|
||||
try {
|
||||
mService.setCecSettingIntValue(CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY, value);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current status of TV Wake on One Touch Play.
|
||||
*
|
||||
* <p>Reflects whether the TV should wake up upon reception of <Text View On>
|
||||
* or <Image View On>.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
@TvWakeOnOneTouchPlay
|
||||
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
|
||||
public int getTvWakeOnOneTouchPlay() {
|
||||
if (mService == null) {
|
||||
Log.e(TAG, "HdmiControlService is not available");
|
||||
throw new RuntimeException("HdmiControlService is not available");
|
||||
}
|
||||
try {
|
||||
return mService.getCecSettingIntValue(CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ import android.hardware.hdmi.IHdmiControlCallback;
|
||||
import android.hardware.tv.cec.V1_0.SendMessageResult;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
|
||||
|
||||
/**
|
||||
@@ -47,7 +49,8 @@ final class DeviceSelectAction extends HdmiCecFeatureAction {
|
||||
|
||||
// State in which we wait for <Report Power Status> to come in response to the command
|
||||
// <Give Device Power Status> we have sent.
|
||||
private static final int STATE_WAIT_FOR_REPORT_POWER_STATUS = 1;
|
||||
@VisibleForTesting
|
||||
static final int STATE_WAIT_FOR_REPORT_POWER_STATUS = 1;
|
||||
|
||||
// State in which we wait for the device power status to switch to 'Standby'.
|
||||
// We wait till the status becomes 'Standby' before we send <Set Stream Path>
|
||||
@@ -56,11 +59,13 @@ final class DeviceSelectAction extends HdmiCecFeatureAction {
|
||||
|
||||
// State in which we wait for the device power status to switch to 'on'. We wait
|
||||
// maximum 100 seconds (20 * 5) before we give up and just send <Set Stream Path>.
|
||||
private static final int STATE_WAIT_FOR_DEVICE_POWER_ON = 3;
|
||||
@VisibleForTesting
|
||||
static final int STATE_WAIT_FOR_DEVICE_POWER_ON = 3;
|
||||
|
||||
private final HdmiDeviceInfo mTarget;
|
||||
private final IHdmiControlCallback mCallback;
|
||||
private final HdmiCecMessage mGivePowerStatus;
|
||||
private final boolean mIsCec20;
|
||||
|
||||
private int mPowerStatusCounter = 0;
|
||||
|
||||
@@ -71,13 +76,22 @@ final class DeviceSelectAction extends HdmiCecFeatureAction {
|
||||
* @param target target logical device that will be a new active source
|
||||
* @param callback callback object
|
||||
*/
|
||||
public DeviceSelectAction(HdmiCecLocalDeviceTv source,
|
||||
HdmiDeviceInfo target, IHdmiControlCallback callback) {
|
||||
DeviceSelectAction(HdmiCecLocalDeviceTv source, HdmiDeviceInfo target,
|
||||
IHdmiControlCallback callback) {
|
||||
this(source, target, callback,
|
||||
source.getDeviceInfo().getCecVersion() >= HdmiControlManager.HDMI_CEC_VERSION_2_0
|
||||
&& target.getCecVersion() >= HdmiControlManager.HDMI_CEC_VERSION_2_0);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
DeviceSelectAction(HdmiCecLocalDeviceTv source, HdmiDeviceInfo target,
|
||||
IHdmiControlCallback callback, boolean isCec20) {
|
||||
super(source);
|
||||
mCallback = callback;
|
||||
mTarget = target;
|
||||
mGivePowerStatus = HdmiCecMessageBuilder.buildGiveDevicePowerStatus(
|
||||
getSourceAddress(), getTargetAddress());
|
||||
mIsCec20 = isCec20;
|
||||
}
|
||||
|
||||
int getTargetAddress() {
|
||||
@@ -86,8 +100,18 @@ final class DeviceSelectAction extends HdmiCecFeatureAction {
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
// Seq #9
|
||||
queryDevicePowerStatus();
|
||||
if (mIsCec20) {
|
||||
sendSetStreamPath();
|
||||
}
|
||||
if (!mIsCec20 || mTarget.getDevicePowerStatus()
|
||||
== HdmiControlManager.POWER_STATUS_UNKNOWN) {
|
||||
queryDevicePowerStatus();
|
||||
} else if (mTarget.getDevicePowerStatus() == HdmiControlManager.POWER_STATUS_ON) {
|
||||
invokeCallbackAndFinish(HdmiControlManager.RESULT_SUCCESS);
|
||||
return true;
|
||||
}
|
||||
mState = STATE_WAIT_FOR_REPORT_POWER_STATUS;
|
||||
addTimer(mState, HdmiConfig.TIMEOUT_MS);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -96,14 +120,10 @@ final class DeviceSelectAction extends HdmiCecFeatureAction {
|
||||
@Override
|
||||
public void onSendCompleted(int error) {
|
||||
if (error != SendMessageResult.SUCCESS) {
|
||||
invokeCallback(HdmiControlManager.RESULT_COMMUNICATION_FAILED);
|
||||
finish();
|
||||
return;
|
||||
invokeCallbackAndFinish(HdmiControlManager.RESULT_COMMUNICATION_FAILED);
|
||||
}
|
||||
}
|
||||
});
|
||||
mState = STATE_WAIT_FOR_REPORT_POWER_STATUS;
|
||||
addTimer(mState, HdmiConfig.TIMEOUT_MS);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -113,7 +133,6 @@ final class DeviceSelectAction extends HdmiCecFeatureAction {
|
||||
}
|
||||
int opcode = cmd.getOpcode();
|
||||
byte[] params = cmd.getParams();
|
||||
|
||||
switch (mState) {
|
||||
case STATE_WAIT_FOR_REPORT_POWER_STATUS:
|
||||
if (opcode == Constants.MESSAGE_REPORT_POWER_STATUS) {
|
||||
@@ -129,21 +148,23 @@ final class DeviceSelectAction extends HdmiCecFeatureAction {
|
||||
private boolean handleReportPowerStatus(int powerStatus) {
|
||||
switch (powerStatus) {
|
||||
case HdmiControlManager.POWER_STATUS_ON:
|
||||
sendSetStreamPath();
|
||||
selectDevice();
|
||||
return true;
|
||||
case HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY:
|
||||
if (mPowerStatusCounter < 4) {
|
||||
mState = STATE_WAIT_FOR_DEVICE_TO_TRANSIT_TO_STANDBY;
|
||||
addTimer(mState, TIMEOUT_TRANSIT_TO_STANDBY_MS);
|
||||
} else {
|
||||
sendSetStreamPath();
|
||||
selectDevice();
|
||||
}
|
||||
return true;
|
||||
case HdmiControlManager.POWER_STATUS_STANDBY:
|
||||
if (mPowerStatusCounter == 0) {
|
||||
turnOnDevice();
|
||||
mState = STATE_WAIT_FOR_DEVICE_POWER_ON;
|
||||
addTimer(mState, TIMEOUT_POWER_ON_MS);
|
||||
} else {
|
||||
sendSetStreamPath();
|
||||
selectDevice();
|
||||
}
|
||||
return true;
|
||||
case HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON:
|
||||
@@ -151,33 +172,13 @@ final class DeviceSelectAction extends HdmiCecFeatureAction {
|
||||
mState = STATE_WAIT_FOR_DEVICE_POWER_ON;
|
||||
addTimer(mState, TIMEOUT_POWER_ON_MS);
|
||||
} else {
|
||||
sendSetStreamPath();
|
||||
selectDevice();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void turnOnDevice() {
|
||||
sendUserControlPressedAndReleased(mTarget.getLogicalAddress(),
|
||||
HdmiCecKeycode.CEC_KEYCODE_POWER);
|
||||
sendUserControlPressedAndReleased(mTarget.getLogicalAddress(),
|
||||
HdmiCecKeycode.CEC_KEYCODE_POWER_ON_FUNCTION);
|
||||
mState = STATE_WAIT_FOR_DEVICE_POWER_ON;
|
||||
addTimer(mState, TIMEOUT_POWER_ON_MS);
|
||||
}
|
||||
|
||||
private void sendSetStreamPath() {
|
||||
// Turn the active source invalidated, which remains so till <Active Source> comes from
|
||||
// the selected device.
|
||||
tv().getActiveSource().invalidate();
|
||||
tv().setActivePath(mTarget.getPhysicalAddress());
|
||||
sendCommand(HdmiCecMessageBuilder.buildSetStreamPath(
|
||||
getSourceAddress(), mTarget.getPhysicalAddress()));
|
||||
invokeCallback(HdmiControlManager.RESULT_SUCCESS);
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTimerEvent(int timeoutState) {
|
||||
if (mState != timeoutState) {
|
||||
@@ -187,28 +188,54 @@ final class DeviceSelectAction extends HdmiCecFeatureAction {
|
||||
switch (mState) {
|
||||
case STATE_WAIT_FOR_REPORT_POWER_STATUS:
|
||||
if (tv().isPowerStandbyOrTransient()) {
|
||||
invokeCallback(HdmiControlManager.RESULT_INCORRECT_MODE);
|
||||
finish();
|
||||
invokeCallbackAndFinish(HdmiControlManager.RESULT_INCORRECT_MODE);
|
||||
return;
|
||||
}
|
||||
sendSetStreamPath();
|
||||
selectDevice();
|
||||
break;
|
||||
case STATE_WAIT_FOR_DEVICE_TO_TRANSIT_TO_STANDBY:
|
||||
case STATE_WAIT_FOR_DEVICE_POWER_ON:
|
||||
mPowerStatusCounter++;
|
||||
queryDevicePowerStatus();
|
||||
mState = STATE_WAIT_FOR_REPORT_POWER_STATUS;
|
||||
addTimer(mState, HdmiConfig.TIMEOUT_MS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void invokeCallback(int result) {
|
||||
if (mCallback == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mCallback.onComplete(result);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Callback failed:" + e);
|
||||
private void turnOnDevice() {
|
||||
if (!mIsCec20) {
|
||||
sendUserControlPressedAndReleased(mTarget.getLogicalAddress(),
|
||||
HdmiCecKeycode.CEC_KEYCODE_POWER);
|
||||
sendUserControlPressedAndReleased(mTarget.getLogicalAddress(),
|
||||
HdmiCecKeycode.CEC_KEYCODE_POWER_ON_FUNCTION);
|
||||
}
|
||||
}
|
||||
|
||||
private void selectDevice() {
|
||||
if (!mIsCec20) {
|
||||
sendSetStreamPath();
|
||||
}
|
||||
invokeCallbackAndFinish(HdmiControlManager.RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
private void sendSetStreamPath() {
|
||||
// Turn the active source invalidated, which remains so till <Active Source> comes from
|
||||
// the selected device.
|
||||
tv().getActiveSource().invalidate();
|
||||
tv().setActivePath(mTarget.getPhysicalAddress());
|
||||
sendCommand(HdmiCecMessageBuilder.buildSetStreamPath(
|
||||
getSourceAddress(), mTarget.getPhysicalAddress()));
|
||||
}
|
||||
|
||||
private void invokeCallbackAndFinish(int result) {
|
||||
if (mCallback != null) {
|
||||
try {
|
||||
mCallback.onComplete(result);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Callback failed:" + e);
|
||||
}
|
||||
}
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import android.provider.Settings.Global;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.hdmi.cec.config.CecSettings;
|
||||
import com.android.server.hdmi.cec.config.Setting;
|
||||
@@ -95,6 +96,9 @@ public class HdmiCecConfig {
|
||||
@Nullable private final CecSettings mSystemConfig;
|
||||
@Nullable private final CecSettings mVendorOverride;
|
||||
|
||||
private final Object mLock = new Object();
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private final ArrayMap<Setting, Set<SettingChangeListener>>
|
||||
mSettingChangeListeners = new ArrayMap<>();
|
||||
|
||||
@@ -297,6 +301,8 @@ public class HdmiCecConfig {
|
||||
return STORAGE_SHARED_PREFS;
|
||||
case HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING:
|
||||
return STORAGE_SHARED_PREFS;
|
||||
case HdmiControlManager.CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY:
|
||||
return STORAGE_GLOBAL_SETTINGS;
|
||||
default:
|
||||
throw new RuntimeException("Invalid CEC setting '" + setting.getName()
|
||||
+ "' storage.");
|
||||
@@ -317,6 +323,8 @@ public class HdmiCecConfig {
|
||||
return setting.getName();
|
||||
case HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING:
|
||||
return setting.getName();
|
||||
case HdmiControlManager.CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY:
|
||||
return Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED;
|
||||
default:
|
||||
throw new RuntimeException("Invalid CEC setting '" + setting.getName()
|
||||
+ "' storage key.");
|
||||
@@ -385,12 +393,14 @@ public class HdmiCecConfig {
|
||||
}
|
||||
|
||||
private void notifySettingChanged(@NonNull Setting setting) {
|
||||
Set<SettingChangeListener> listeners = mSettingChangeListeners.get(setting);
|
||||
if (listeners == null) {
|
||||
return; // No listeners registered, do nothing.
|
||||
}
|
||||
for (SettingChangeListener listener: listeners) {
|
||||
listener.onChange(setting.getName());
|
||||
synchronized (mLock) {
|
||||
Set<SettingChangeListener> listeners = mSettingChangeListeners.get(setting);
|
||||
if (listeners == null) {
|
||||
return; // No listeners registered, do nothing.
|
||||
}
|
||||
for (SettingChangeListener listener: listeners) {
|
||||
listener.onChange(setting.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -436,10 +446,12 @@ public class HdmiCecConfig {
|
||||
throw new IllegalArgumentException("Change listeners for setting '" + name
|
||||
+ "' not supported.");
|
||||
}
|
||||
if (!mSettingChangeListeners.containsKey(setting)) {
|
||||
mSettingChangeListeners.put(setting, new HashSet<>());
|
||||
synchronized (mLock) {
|
||||
if (!mSettingChangeListeners.containsKey(setting)) {
|
||||
mSettingChangeListeners.put(setting, new HashSet<>());
|
||||
}
|
||||
mSettingChangeListeners.get(setting).add(listener);
|
||||
}
|
||||
mSettingChangeListeners.get(setting).add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -451,11 +463,13 @@ public class HdmiCecConfig {
|
||||
if (setting == null) {
|
||||
throw new IllegalArgumentException("Setting '" + name + "' does not exist.");
|
||||
}
|
||||
if (mSettingChangeListeners.containsKey(setting)) {
|
||||
Set<SettingChangeListener> listeners = mSettingChangeListeners.get(setting);
|
||||
listeners.remove(listener);
|
||||
if (listeners.isEmpty()) {
|
||||
mSettingChangeListeners.remove(setting);
|
||||
synchronized (mLock) {
|
||||
if (mSettingChangeListeners.containsKey(setting)) {
|
||||
Set<SettingChangeListener> listeners = mSettingChangeListeners.get(setting);
|
||||
listeners.remove(listener);
|
||||
if (listeners.isEmpty()) {
|
||||
mSettingChangeListeners.remove(setting);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,9 +94,6 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
// If true, TV going to standby mode puts other devices also to standby.
|
||||
private boolean mAutoDeviceOff;
|
||||
|
||||
// If true, TV wakes itself up when receiving <Text/Image View On>.
|
||||
private boolean mAutoWakeup;
|
||||
|
||||
private final HdmiCecStandbyModeHandler mStandbyHandler;
|
||||
|
||||
// If true, do not do routing control/send active source for internal source.
|
||||
@@ -163,7 +160,6 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
mPrevPortId = Constants.INVALID_PORT_ID;
|
||||
mAutoDeviceOff = mService.readBooleanSetting(Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED,
|
||||
true);
|
||||
mAutoWakeup = mService.readBooleanSetting(Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED, true);
|
||||
mSystemAudioControlFeatureEnabled =
|
||||
mService.readBooleanSetting(Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED, true);
|
||||
mStandbyHandler = new HdmiCecStandbyModeHandler(service, this);
|
||||
@@ -641,7 +637,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
// implemented in such a way that Android system is not really put to standby mode
|
||||
// but only the display is set to blank. Then the command leads to the effect of
|
||||
// turning on the display by the invocation of PowerManager.wakeUp().
|
||||
if (mService.isPowerStandbyOrTransient() && mAutoWakeup) {
|
||||
if (mService.isPowerStandbyOrTransient() && getAutoWakeup()) {
|
||||
mService.wakeUp();
|
||||
}
|
||||
return true;
|
||||
@@ -1215,16 +1211,12 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
mAutoDeviceOff = enabled;
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
void setAutoWakeup(boolean enabled) {
|
||||
assertRunOnServiceThread();
|
||||
mAutoWakeup = enabled;
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
boolean getAutoWakeup() {
|
||||
assertRunOnServiceThread();
|
||||
return mAutoWakeup;
|
||||
return mService.getHdmiCecConfig().getIntValue(
|
||||
HdmiControlManager.CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY)
|
||||
== HdmiControlManager.TV_WAKE_ON_ONE_TOUCH_PLAY_ENABLED;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1552,7 +1544,6 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
pw.println("mSystemAudioMute: " + mSystemAudioMute);
|
||||
pw.println("mSystemAudioControlFeatureEnabled: " + mSystemAudioControlFeatureEnabled);
|
||||
pw.println("mAutoDeviceOff: " + mAutoDeviceOff);
|
||||
pw.println("mAutoWakeup: " + mAutoWakeup);
|
||||
pw.println("mSkipRoutingControl: " + mSkipRoutingControl);
|
||||
pw.println("mPrevPortId: " + mPrevPortId);
|
||||
}
|
||||
|
||||
@@ -526,6 +526,16 @@ public class HdmiControlService extends SystemService {
|
||||
initializeCec(INITIATED_BY_ENABLE_CEC);
|
||||
}
|
||||
});
|
||||
mHdmiCecConfig.registerChangeListener(
|
||||
HdmiControlManager.CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY,
|
||||
new HdmiCecConfig.SettingChangeListener() {
|
||||
@Override
|
||||
public void onChange(String setting) {
|
||||
if (isTvDeviceEnabled()) {
|
||||
setCecOption(OptionKey.WAKEUP, tv().getAutoWakeup());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void bootCompleted() {
|
||||
@@ -651,7 +661,6 @@ public class HdmiControlService extends SystemService {
|
||||
ContentResolver resolver = getContext().getContentResolver();
|
||||
String[] settings = new String[] {
|
||||
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,
|
||||
Global.MHL_INPUT_SWITCHING_ENABLED,
|
||||
@@ -680,12 +689,6 @@ public class HdmiControlService extends SystemService {
|
||||
setHdmiCecVolumeControlEnabledInternal(getHdmiCecConfig().getIntValue(
|
||||
HdmiControlManager.CEC_SETTING_NAME_VOLUME_CONTROL_MODE));
|
||||
break;
|
||||
case Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED:
|
||||
if (isTvDeviceEnabled()) {
|
||||
tv().setAutoWakeup(enabled);
|
||||
}
|
||||
setCecOption(OptionKey.WAKEUP, enabled);
|
||||
break;
|
||||
case Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED:
|
||||
for (int type : mLocalDevices) {
|
||||
HdmiCecLocalDevice localDevice = mHdmiCecNetwork.getLocalDevice(type);
|
||||
|
||||
@@ -55,4 +55,13 @@
|
||||
</allowed-values>
|
||||
<default-value int-value="1" />
|
||||
</setting>
|
||||
<setting name="tv_wake_on_one_touch_play"
|
||||
value-type="int"
|
||||
user-configurable="true">
|
||||
<allowed-values>
|
||||
<value int-value="0" />
|
||||
<value int-value="1" />
|
||||
</allowed-values>
|
||||
<default-value int-value="1" />
|
||||
</setting>
|
||||
</cec-settings>
|
||||
|
||||
@@ -0,0 +1,362 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.hdmi;
|
||||
|
||||
import static android.hardware.hdmi.HdmiControlManager.POWER_STATUS_ON;
|
||||
import static android.hardware.hdmi.HdmiControlManager.POWER_STATUS_STANDBY;
|
||||
import static android.hardware.hdmi.HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON;
|
||||
|
||||
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_TV;
|
||||
import static com.android.server.hdmi.DeviceSelectAction.STATE_WAIT_FOR_DEVICE_POWER_ON;
|
||||
import static com.android.server.hdmi.DeviceSelectAction.STATE_WAIT_FOR_REPORT_POWER_STATUS;
|
||||
import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.hdmi.HdmiControlManager;
|
||||
import android.hardware.hdmi.HdmiDeviceInfo;
|
||||
import android.hardware.hdmi.HdmiPortInfo;
|
||||
import android.hardware.hdmi.IHdmiControlCallback;
|
||||
import android.os.Handler;
|
||||
import android.os.IPowerManager;
|
||||
import android.os.IThermalService;
|
||||
import android.os.Looper;
|
||||
import android.os.PowerManager;
|
||||
import android.os.test.TestLooper;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.server.hdmi.HdmiCecFeatureAction.ActionTimer;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(JUnit4.class)
|
||||
public class DeviceSelectActionTest {
|
||||
|
||||
private static final int PORT_1 = 1;
|
||||
private static final int PORT_2 = 1;
|
||||
private static final int PHYSICAL_ADDRESS_PLAYBACK_1 = 0x1000;
|
||||
private static final int PHYSICAL_ADDRESS_PLAYBACK_2 = 0x2000;
|
||||
|
||||
private static final byte[] POWER_ON = new byte[] { POWER_STATUS_ON };
|
||||
private static final byte[] POWER_STANDBY = new byte[] { POWER_STATUS_STANDBY };
|
||||
private static final byte[] POWER_TRANSIENT_TO_ON = new byte[] { POWER_STATUS_TRANSIENT_TO_ON };
|
||||
private static final HdmiCecMessage REPORT_POWER_STATUS_ON = new HdmiCecMessage(
|
||||
ADDR_PLAYBACK_1, ADDR_TV, Constants.MESSAGE_REPORT_POWER_STATUS, POWER_ON);
|
||||
private static final HdmiCecMessage REPORT_POWER_STATUS_STANDBY = new HdmiCecMessage(
|
||||
ADDR_PLAYBACK_1, ADDR_TV, Constants.MESSAGE_REPORT_POWER_STATUS, POWER_STANDBY);
|
||||
private static final HdmiCecMessage REPORT_POWER_STATUS_TRANSIENT_TO_ON = new HdmiCecMessage(
|
||||
ADDR_PLAYBACK_1, ADDR_TV, Constants.MESSAGE_REPORT_POWER_STATUS, POWER_TRANSIENT_TO_ON);
|
||||
private static final HdmiCecMessage SET_STREAM_PATH = HdmiCecMessageBuilder.buildSetStreamPath(
|
||||
ADDR_TV, PHYSICAL_ADDRESS_PLAYBACK_1);
|
||||
private static final HdmiDeviceInfo INFO_PLAYBACK_1 = new HdmiDeviceInfo(
|
||||
ADDR_PLAYBACK_1, PHYSICAL_ADDRESS_PLAYBACK_1, PORT_1, HdmiDeviceInfo.DEVICE_PLAYBACK,
|
||||
0x1234, "Playback 1",
|
||||
HdmiControlManager.POWER_STATUS_ON, HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
|
||||
private static final HdmiDeviceInfo INFO_PLAYBACK_2 = new HdmiDeviceInfo(
|
||||
ADDR_PLAYBACK_2, PHYSICAL_ADDRESS_PLAYBACK_2, PORT_2, HdmiDeviceInfo.DEVICE_PLAYBACK,
|
||||
0x1234, "Playback 2",
|
||||
HdmiControlManager.POWER_STATUS_ON, HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
|
||||
|
||||
private HdmiControlService mHdmiControlService;
|
||||
private HdmiCecController mHdmiCecController;
|
||||
private HdmiCecLocalDeviceTv mHdmiCecLocalDeviceTv;
|
||||
private FakeNativeWrapper mNativeWrapper;
|
||||
private Looper mMyLooper;
|
||||
private TestLooper mTestLooper = new TestLooper();
|
||||
private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
|
||||
|
||||
@Mock
|
||||
private IPowerManager mIPowerManagerMock;
|
||||
@Mock
|
||||
private IThermalService mIThermalServiceMock;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
Context context = InstrumentationRegistry.getTargetContext();
|
||||
mMyLooper = mTestLooper.getLooper();
|
||||
PowerManager powerManager = new PowerManager(context, mIPowerManagerMock,
|
||||
mIThermalServiceMock, new Handler(mMyLooper));
|
||||
|
||||
HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(context);
|
||||
|
||||
mHdmiControlService =
|
||||
new HdmiControlService(InstrumentationRegistry.getTargetContext()) {
|
||||
@Override
|
||||
boolean isControlEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
void wakeUp() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeStringSystemProperty(String key, String value) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isPowerStandbyOrTransient() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PowerManager getPowerManager() {
|
||||
return powerManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HdmiCecConfig getHdmiCecConfig() {
|
||||
return hdmiCecConfig;
|
||||
}
|
||||
};
|
||||
|
||||
mHdmiCecLocalDeviceTv = new HdmiCecLocalDeviceTv(mHdmiControlService);
|
||||
mHdmiCecLocalDeviceTv.init();
|
||||
mHdmiControlService.setIoLooper(mMyLooper);
|
||||
mNativeWrapper = new FakeNativeWrapper();
|
||||
mHdmiCecController = HdmiCecController.createWithNativeWrapper(
|
||||
mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
|
||||
mHdmiControlService.setCecController(mHdmiCecController);
|
||||
mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
|
||||
mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
|
||||
mLocalDevices.add(mHdmiCecLocalDeviceTv);
|
||||
HdmiPortInfo[] hdmiPortInfos = new HdmiPortInfo[2];
|
||||
hdmiPortInfos[0] =
|
||||
new HdmiPortInfo(1, HdmiPortInfo.PORT_INPUT, PHYSICAL_ADDRESS_PLAYBACK_1,
|
||||
true, false, false);
|
||||
hdmiPortInfos[1] =
|
||||
new HdmiPortInfo(2, HdmiPortInfo.PORT_INPUT, PHYSICAL_ADDRESS_PLAYBACK_2,
|
||||
true, false, false);
|
||||
mNativeWrapper.setPortInfo(hdmiPortInfos);
|
||||
mHdmiControlService.initService();
|
||||
mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
|
||||
mNativeWrapper.setPhysicalAddress(0x0000);
|
||||
mTestLooper.dispatchAll();
|
||||
mNativeWrapper.clearResultMessages();
|
||||
mHdmiControlService.getHdmiCecNetwork().addCecDevice(INFO_PLAYBACK_1);
|
||||
mHdmiControlService.getHdmiCecNetwork().addCecDevice(INFO_PLAYBACK_2);
|
||||
}
|
||||
|
||||
private static class TestActionTimer implements ActionTimer {
|
||||
private int mState;
|
||||
|
||||
@Override
|
||||
public void sendTimerMessage(int state, long delayMillis) {
|
||||
mState = state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearTimerMessage() {
|
||||
}
|
||||
|
||||
private int getState() {
|
||||
return mState;
|
||||
}
|
||||
}
|
||||
|
||||
private static class TestCallback extends IHdmiControlCallback.Stub {
|
||||
private final ArrayList<Integer> mCallbackResult = new ArrayList<Integer>();
|
||||
|
||||
@Override
|
||||
public void onComplete(int result) {
|
||||
mCallbackResult.add(result);
|
||||
}
|
||||
|
||||
private int getResult() {
|
||||
assertThat(mCallbackResult.size()).isEqualTo(1);
|
||||
return mCallbackResult.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
private DeviceSelectAction createDeviceSelectAction(TestActionTimer actionTimer,
|
||||
TestCallback callback,
|
||||
boolean isCec20) {
|
||||
HdmiDeviceInfo hdmiDeviceInfo =
|
||||
mHdmiControlService.getHdmiCecNetwork().getCecDeviceInfo(ADDR_PLAYBACK_1);
|
||||
DeviceSelectAction action = new DeviceSelectAction(mHdmiCecLocalDeviceTv,
|
||||
hdmiDeviceInfo, callback, isCec20);
|
||||
action.setActionTimer(actionTimer);
|
||||
return action;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeviceSelect_DeviceInPowerOnStatus_Cec14b() {
|
||||
// TV was watching playback2 device connected at port 2, and wants to select
|
||||
// playback1.
|
||||
TestActionTimer actionTimer = new TestActionTimer();
|
||||
TestCallback callback = new TestCallback();
|
||||
DeviceSelectAction action = createDeviceSelectAction(actionTimer, callback,
|
||||
/*isCec20=*/false);
|
||||
mHdmiCecLocalDeviceTv.updateActiveSource(ADDR_PLAYBACK_2, PHYSICAL_ADDRESS_PLAYBACK_2,
|
||||
"testDeviceSelect");
|
||||
action.start();
|
||||
mTestLooper.dispatchAll();
|
||||
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(SET_STREAM_PATH);
|
||||
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
|
||||
action.processCommand(REPORT_POWER_STATUS_ON);
|
||||
mTestLooper.dispatchAll();
|
||||
assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
|
||||
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeviceSelect_DeviceInStandbyStatus_Cec14b() {
|
||||
mHdmiCecLocalDeviceTv.updateActiveSource(ADDR_PLAYBACK_2, PHYSICAL_ADDRESS_PLAYBACK_2,
|
||||
"testDeviceSelect");
|
||||
TestActionTimer actionTimer = new TestActionTimer();
|
||||
TestCallback callback = new TestCallback();
|
||||
DeviceSelectAction action = createDeviceSelectAction(actionTimer, callback,
|
||||
/*isCec20=*/false);
|
||||
action.start();
|
||||
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
|
||||
action.processCommand(REPORT_POWER_STATUS_STANDBY);
|
||||
mTestLooper.dispatchAll();
|
||||
HdmiCecMessage userControlPressed = HdmiCecMessageBuilder.buildUserControlPressed(
|
||||
ADDR_TV, ADDR_PLAYBACK_1, HdmiCecKeycode.CEC_KEYCODE_POWER);
|
||||
assertThat(mNativeWrapper.getResultMessages()).contains(userControlPressed);
|
||||
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_DEVICE_POWER_ON);
|
||||
action.handleTimerEvent(STATE_WAIT_FOR_DEVICE_POWER_ON);
|
||||
action.processCommand(REPORT_POWER_STATUS_ON);
|
||||
mTestLooper.dispatchAll();
|
||||
assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
|
||||
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeviceSelect_DeviceInStandbyStatusWithSomeTimeouts_Cec14b() {
|
||||
mHdmiCecLocalDeviceTv.updateActiveSource(ADDR_PLAYBACK_2, PHYSICAL_ADDRESS_PLAYBACK_2,
|
||||
"testDeviceSelect");
|
||||
TestActionTimer actionTimer = new TestActionTimer();
|
||||
TestCallback callback = new TestCallback();
|
||||
DeviceSelectAction action = createDeviceSelectAction(actionTimer, callback,
|
||||
/*isCec20=*/false);
|
||||
action.start();
|
||||
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
|
||||
action.processCommand(REPORT_POWER_STATUS_STANDBY);
|
||||
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_DEVICE_POWER_ON);
|
||||
action.handleTimerEvent(STATE_WAIT_FOR_DEVICE_POWER_ON);
|
||||
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
|
||||
action.processCommand(REPORT_POWER_STATUS_TRANSIENT_TO_ON);
|
||||
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_DEVICE_POWER_ON);
|
||||
action.handleTimerEvent(STATE_WAIT_FOR_DEVICE_POWER_ON);
|
||||
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
|
||||
action.processCommand(REPORT_POWER_STATUS_ON);
|
||||
mTestLooper.dispatchAll();
|
||||
assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
|
||||
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeviceSelect_DeviceInStandbyAfterTimeoutForReportPowerStatus_Cec14b() {
|
||||
mHdmiCecLocalDeviceTv.updateActiveSource(ADDR_PLAYBACK_2, PHYSICAL_ADDRESS_PLAYBACK_2,
|
||||
"testDeviceSelect");
|
||||
TestActionTimer actionTimer = new TestActionTimer();
|
||||
TestCallback callback = new TestCallback();
|
||||
DeviceSelectAction action = createDeviceSelectAction(actionTimer, callback,
|
||||
/*isCec20=*/false);
|
||||
action.start();
|
||||
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
|
||||
action.processCommand(REPORT_POWER_STATUS_STANDBY);
|
||||
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_DEVICE_POWER_ON);
|
||||
action.handleTimerEvent(STATE_WAIT_FOR_DEVICE_POWER_ON);
|
||||
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
|
||||
action.processCommand(REPORT_POWER_STATUS_TRANSIENT_TO_ON);
|
||||
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_DEVICE_POWER_ON);
|
||||
action.handleTimerEvent(STATE_WAIT_FOR_DEVICE_POWER_ON);
|
||||
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
|
||||
action.handleTimerEvent(STATE_WAIT_FOR_REPORT_POWER_STATUS);
|
||||
// Give up getting power status, and just send <Set Stream Path>
|
||||
mTestLooper.dispatchAll();
|
||||
assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
|
||||
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeviceSelect_DeviceInPowerOnStatus_Cec20() {
|
||||
mHdmiControlService.getHdmiCecNetwork().updateDevicePowerStatus(ADDR_PLAYBACK_1,
|
||||
HdmiControlManager.POWER_STATUS_ON);
|
||||
TestActionTimer actionTimer = new TestActionTimer();
|
||||
TestCallback callback = new TestCallback();
|
||||
DeviceSelectAction action = createDeviceSelectAction(actionTimer, callback,
|
||||
/*isCec20=*/true);
|
||||
mHdmiCecLocalDeviceTv.updateActiveSource(ADDR_PLAYBACK_2, PHYSICAL_ADDRESS_PLAYBACK_2,
|
||||
"testDeviceSelect");
|
||||
action.start();
|
||||
mTestLooper.dispatchAll();
|
||||
assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
|
||||
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeviceSelect_DeviceInPowerUnknownStatus_Cec20() {
|
||||
mHdmiControlService.getHdmiCecNetwork().updateDevicePowerStatus(ADDR_PLAYBACK_1,
|
||||
HdmiControlManager.POWER_STATUS_UNKNOWN);
|
||||
TestActionTimer actionTimer = new TestActionTimer();
|
||||
TestCallback callback = new TestCallback();
|
||||
DeviceSelectAction action = createDeviceSelectAction(actionTimer, callback,
|
||||
/*isCec20=*/true);
|
||||
mHdmiCecLocalDeviceTv.updateActiveSource(ADDR_PLAYBACK_2, PHYSICAL_ADDRESS_PLAYBACK_2,
|
||||
"testDeviceSelect");
|
||||
action.start();
|
||||
mTestLooper.dispatchAll();
|
||||
assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
|
||||
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
|
||||
action.processCommand(REPORT_POWER_STATUS_ON);
|
||||
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeviceSelect_DeviceInStandbyStatus_Cec20() {
|
||||
mHdmiControlService.getHdmiCecNetwork().updateDevicePowerStatus(ADDR_PLAYBACK_1,
|
||||
HdmiControlManager.POWER_STATUS_STANDBY);
|
||||
mHdmiCecLocalDeviceTv.updateActiveSource(ADDR_PLAYBACK_2, PHYSICAL_ADDRESS_PLAYBACK_2,
|
||||
"testDeviceSelect");
|
||||
TestActionTimer actionTimer = new TestActionTimer();
|
||||
TestCallback callback = new TestCallback();
|
||||
DeviceSelectAction action = createDeviceSelectAction(actionTimer, callback,
|
||||
/*isCec20=*/true);
|
||||
action.start();
|
||||
mTestLooper.dispatchAll();
|
||||
assertThat(mNativeWrapper.getResultMessages()).contains(SET_STREAM_PATH);
|
||||
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_REPORT_POWER_STATUS);
|
||||
action.processCommand(REPORT_POWER_STATUS_STANDBY);
|
||||
mTestLooper.dispatchAll();
|
||||
HdmiCecMessage userControlPressed = HdmiCecMessageBuilder.buildUserControlPressed(
|
||||
ADDR_TV, ADDR_PLAYBACK_1, HdmiCecKeycode.CEC_KEYCODE_POWER);
|
||||
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(userControlPressed);
|
||||
assertThat(actionTimer.getState()).isEqualTo(STATE_WAIT_FOR_DEVICE_POWER_ON);
|
||||
action.handleTimerEvent(STATE_WAIT_FOR_DEVICE_POWER_ON);
|
||||
action.processCommand(REPORT_POWER_STATUS_ON);
|
||||
assertThat(callback.getResult()).isEqualTo(HdmiControlManager.RESULT_SUCCESS);
|
||||
}
|
||||
}
|
||||
@@ -104,6 +104,15 @@ final class FakeHdmiCecConfig extends HdmiCecConfig {
|
||||
+ " </allowed-values>"
|
||||
+ " <default-value int-value=\"1\" />"
|
||||
+ " </setting>"
|
||||
+ " <setting name=\"tv_wake_on_one_touch_play\""
|
||||
+ " value-type=\"int\""
|
||||
+ " user-configurable=\"true\">"
|
||||
+ " <allowed-values>"
|
||||
+ " <value int-value=\"0\" />"
|
||||
+ " <value int-value=\"1\" />"
|
||||
+ " </allowed-values>"
|
||||
+ " <default-value int-value=\"1\" />"
|
||||
+ " </setting>"
|
||||
+ "</cec-settings>";
|
||||
|
||||
FakeHdmiCecConfig(@NonNull Context context) {
|
||||
|
||||
@@ -58,6 +58,8 @@ public class HdmiCecLocalDeviceTvTest {
|
||||
private TestLooper mTestLooper = new TestLooper();
|
||||
private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
|
||||
private int mTvPhysicalAddress;
|
||||
private int mTvLogicalAddress;
|
||||
private boolean mWokenUp;
|
||||
|
||||
@Mock
|
||||
private IPowerManager mIPowerManagerMock;
|
||||
@@ -77,6 +79,11 @@ public class HdmiCecLocalDeviceTvTest {
|
||||
|
||||
mHdmiControlService =
|
||||
new HdmiControlService(InstrumentationRegistry.getTargetContext()) {
|
||||
@Override
|
||||
void wakeUp() {
|
||||
mWokenUp = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isControlEnabled() {
|
||||
return true;
|
||||
@@ -122,6 +129,7 @@ public class HdmiCecLocalDeviceTvTest {
|
||||
mTvPhysicalAddress = 0x0000;
|
||||
mNativeWrapper.setPhysicalAddress(mTvPhysicalAddress);
|
||||
mTestLooper.dispatchAll();
|
||||
mTvLogicalAddress = mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress();
|
||||
mNativeWrapper.clearResultMessages();
|
||||
}
|
||||
|
||||
@@ -203,4 +211,60 @@ public class HdmiCecLocalDeviceTvTest {
|
||||
HdmiControlManager.POWER_CONTROL_MODE_TV);
|
||||
assertThat(mHdmiControlService.shouldHandleTvPowerKey()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tvWakeOnOneTouchPlay_TextViewOn_Enabled() {
|
||||
mHdmiCecLocalDeviceTv.mService.getHdmiCecConfig().setIntValue(
|
||||
HdmiControlManager.CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY,
|
||||
HdmiControlManager.TV_WAKE_ON_ONE_TOUCH_PLAY_ENABLED);
|
||||
mTestLooper.dispatchAll();
|
||||
mWokenUp = false;
|
||||
HdmiCecMessage textViewOn = HdmiCecMessageBuilder.buildTextViewOn(ADDR_PLAYBACK_1,
|
||||
mTvLogicalAddress);
|
||||
assertThat(mHdmiCecLocalDeviceTv.dispatchMessage(textViewOn)).isTrue();
|
||||
mTestLooper.dispatchAll();
|
||||
assertThat(mWokenUp).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tvWakeOnOneTouchPlay_ImageViewOn_Enabled() {
|
||||
mHdmiCecLocalDeviceTv.mService.getHdmiCecConfig().setIntValue(
|
||||
HdmiControlManager.CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY,
|
||||
HdmiControlManager.TV_WAKE_ON_ONE_TOUCH_PLAY_ENABLED);
|
||||
mTestLooper.dispatchAll();
|
||||
mWokenUp = false;
|
||||
HdmiCecMessage imageViewOn = new HdmiCecMessage(ADDR_PLAYBACK_1, mTvLogicalAddress,
|
||||
Constants.MESSAGE_IMAGE_VIEW_ON, HdmiCecMessage.EMPTY_PARAM);
|
||||
assertThat(mHdmiCecLocalDeviceTv.dispatchMessage(imageViewOn)).isTrue();
|
||||
mTestLooper.dispatchAll();
|
||||
assertThat(mWokenUp).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tvWakeOnOneTouchPlay_TextViewOn_Disabled() {
|
||||
mHdmiCecLocalDeviceTv.mService.getHdmiCecConfig().setIntValue(
|
||||
HdmiControlManager.CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY,
|
||||
HdmiControlManager.TV_WAKE_ON_ONE_TOUCH_PLAY_DISABLED);
|
||||
mTestLooper.dispatchAll();
|
||||
mWokenUp = false;
|
||||
HdmiCecMessage textViewOn = HdmiCecMessageBuilder.buildTextViewOn(ADDR_PLAYBACK_1,
|
||||
mTvLogicalAddress);
|
||||
assertThat(mHdmiCecLocalDeviceTv.dispatchMessage(textViewOn)).isTrue();
|
||||
mTestLooper.dispatchAll();
|
||||
assertThat(mWokenUp).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tvWakeOnOneTouchPlay_ImageViewOn_Disabled() {
|
||||
mHdmiCecLocalDeviceTv.mService.getHdmiCecConfig().setIntValue(
|
||||
HdmiControlManager.CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY,
|
||||
HdmiControlManager.TV_WAKE_ON_ONE_TOUCH_PLAY_DISABLED);
|
||||
mTestLooper.dispatchAll();
|
||||
mWokenUp = false;
|
||||
HdmiCecMessage imageViewOn = new HdmiCecMessage(ADDR_PLAYBACK_1, mTvLogicalAddress,
|
||||
Constants.MESSAGE_IMAGE_VIEW_ON, HdmiCecMessage.EMPTY_PARAM);
|
||||
assertThat(mHdmiCecLocalDeviceTv.dispatchMessage(imageViewOn)).isTrue();
|
||||
mTestLooper.dispatchAll();
|
||||
assertThat(mWokenUp).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user