Merge "CEC Standby messages when going to sleep"

This commit is contained in:
Nathalie Le Clair
2020-07-29 08:07:46 +00:00
committed by Android (Google) Code Review
6 changed files with 180 additions and 8 deletions

View File

@@ -24,6 +24,7 @@ import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.StringDef;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
@@ -39,6 +40,8 @@ import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ConcurrentUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -318,6 +321,37 @@ public final class HdmiControlManager {
/** The HdmiControlService will be disabled to standby. */
public static final int CONTROL_STATE_CHANGED_REASON_STANDBY = 3;
// -- Which devices the playback device can send a <Standby> message to upon going to sleep.
/**
* Send <Standby> to TV only.
*
* @hide
*/
public static final String SEND_STANDBY_ON_SLEEP_TO_TV = "to_tv";
/**
* Broadcast <Standby> to all devices in the network.
*
* @hide
*/
public static final String SEND_STANDBY_ON_SLEEP_BROADCAST = "broadcast";
/**
* Don't send any <Standby> message.
*
* @hide
*/
public static final String SEND_STANDBY_ON_SLEEP_NONE = "none";
/**
* @hide
*/
@StringDef({
SEND_STANDBY_ON_SLEEP_TO_TV,
SEND_STANDBY_ON_SLEEP_BROADCAST,
SEND_STANDBY_ON_SLEEP_NONE
})
@Retention(RetentionPolicy.SOURCE)
public @interface StandbyBehavior {
}
// True if we have a logical device of type playback hosted in the system.
private final boolean mHasPlaybackDevice;
// True if we have a logical device of type TV hosted in the system.

15
core/java/android/provider/Settings.java Executable file → Normal file
View File

@@ -9793,6 +9793,21 @@ public final class Settings {
public static final String HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED =
"hdmi_control_auto_device_off_enabled";
/**
* Property to decide which devices the playback device can send a <Standby> message to upon
* going to sleep. Supported values are:
* <ul>
* <li>{@link HdmiControlManager#SEND_STANDBY_ON_SLEEP_TO_TV} to TV only.</li>
* <li>{@link HdmiControlManager#SEND_STANDBY_ON_SLEEP_BROADCAST} to all devices in the
* network.</li>
* <li>{@link HdmiControlManager#SEND_STANDBY_ON_SLEEP_NONE} no <Standby> message sent.</li>
* </ul>
*
* @hide
*/
public static final String HDMI_CONTROL_SEND_STANDBY_ON_SLEEP =
"hdmi_control_send_standby_on_sleep";
/**
* Whether or not media is shown automatically when bypassing as a heads up.
* @hide

View File

@@ -297,6 +297,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_SEND_STANDBY_ON_SLEEP,
Settings.Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED,
Settings.Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED,
Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED,

View File

@@ -85,6 +85,14 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource {
// The option is false by default. Update settings db as well to have the right
// initial setting on UI.
mService.writeBooleanSetting(Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED, mAutoTvOff);
// Initialize settings database with System Property value. This will be the initial
// setting on the UI. If no System Property is set, the option is set to to_tv by default.
mService.writeStringSetting(Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
mService.readStringSetting(Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
HdmiProperties.send_standby_on_sleep().orElse(
HdmiProperties.send_standby_on_sleep_values.TO_TV).name()
.toLowerCase()));
}
@Override
@@ -188,8 +196,26 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource {
}
switch (standbyAction) {
case HdmiControlService.STANDBY_SCREEN_OFF:
mService.sendCecCommand(
HdmiCecMessageBuilder.buildStandby(mAddress, Constants.ADDR_TV));
// Get latest setting value
@HdmiControlManager.StandbyBehavior
String sendStandbyOnSleep = mService.readStringSetting(
Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
HdmiProperties.send_standby_on_sleep().orElse(
HdmiProperties.send_standby_on_sleep_values.TO_TV).name()
.toLowerCase());
switch (sendStandbyOnSleep) {
case HdmiControlManager.SEND_STANDBY_ON_SLEEP_TO_TV:
mService.sendCecCommand(
HdmiCecMessageBuilder.buildStandby(mAddress, Constants.ADDR_TV));
break;
case HdmiControlManager.SEND_STANDBY_ON_SLEEP_BROADCAST:
mService.sendCecCommand(
HdmiCecMessageBuilder.buildStandby(mAddress,
Constants.ADDR_BROADCAST));
break;
case HdmiControlManager.SEND_STANDBY_ON_SLEEP_NONE:
break;
}
break;
case HdmiControlService.STANDBY_SHUTDOWN:
// ACTION_SHUTDOWN is taken as a signal to power off all the devices.

View File

@@ -772,6 +772,11 @@ public class HdmiControlService extends SystemService {
return content;
}
void writeStringSetting(String key, String value) {
ContentResolver cr = getContext().getContentResolver();
Global.putString(cr, key, value);
}
private void initializeCec(int initiatedBy) {
mAddressAllocated = false;
mCecController.setOption(OptionKey.SYSTEM_CEC_CONTROL, true);

View File

@@ -15,6 +15,7 @@
*/
package com.android.server.hdmi;
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.HdmiControlService.INITIATED_BY_ENABLE_CEC;
@@ -22,6 +23,7 @@ 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.os.Handler;
import android.os.IPowerManager;
import android.os.IThermalService;
@@ -29,6 +31,7 @@ import android.os.Looper;
import android.os.PowerManager;
import android.os.test.TestLooper;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings.Global;
import android.sysprop.HdmiProperties;
import android.view.KeyEvent;
@@ -324,29 +327,117 @@ public class HdmiCecLocalDevicePlaybackTest {
}
@Test
public void handleOnStandby_ScreenOff_NotActiveSource() {
public void handleOnStandby_ScreenOff_NotActiveSource_ToTv() {
mHdmiCecLocalDevicePlayback.mService.writeStringSetting(
Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
HdmiControlManager.SEND_STANDBY_ON_SLEEP_TO_TV);
mHdmiCecLocalDevicePlayback.setIsActiveSource(false);
mHdmiCecLocalDevicePlayback.setAutoDeviceOff(true);
mHdmiCecLocalDevicePlayback.onStandby(false, HdmiControlService.STANDBY_SCREEN_OFF);
mTestLooper.dispatchAll();
HdmiCecMessage standbyMessage = HdmiCecMessageBuilder.buildStandby(
HdmiCecMessage standbyMessageToTv = HdmiCecMessageBuilder.buildStandby(
mHdmiCecLocalDevicePlayback.mAddress, ADDR_TV);
HdmiCecMessage standbyMessageBroadcast = HdmiCecMessageBuilder.buildStandby(
mHdmiCecLocalDevicePlayback.mAddress, ADDR_BROADCAST);
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessage);
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessageToTv);
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessageBroadcast);
}
@Test
public void handleOnStandby_ScreenOff_ActiveSource() {
public void handleOnStandby_ScreenOff_NotActiveSource_Broadcast() {
mHdmiCecLocalDevicePlayback.mService.writeStringSetting(
Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
HdmiControlManager.SEND_STANDBY_ON_SLEEP_BROADCAST);
mHdmiCecLocalDevicePlayback.setIsActiveSource(false);
mHdmiCecLocalDevicePlayback.setAutoDeviceOff(true);
mHdmiCecLocalDevicePlayback.onStandby(false, HdmiControlService.STANDBY_SCREEN_OFF);
mTestLooper.dispatchAll();
HdmiCecMessage standbyMessageToTv = HdmiCecMessageBuilder.buildStandby(
mHdmiCecLocalDevicePlayback.mAddress, ADDR_TV);
HdmiCecMessage standbyMessageBroadcast = HdmiCecMessageBuilder.buildStandby(
mHdmiCecLocalDevicePlayback.mAddress, ADDR_BROADCAST);
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessageToTv);
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessageBroadcast);
}
@Test
public void handleOnStandby_ScreenOff_NotActiveSource_None() {
mHdmiCecLocalDevicePlayback.mService.writeStringSetting(
Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
HdmiControlManager.SEND_STANDBY_ON_SLEEP_NONE);
mHdmiCecLocalDevicePlayback.setIsActiveSource(false);
mHdmiCecLocalDevicePlayback.setAutoDeviceOff(true);
mHdmiCecLocalDevicePlayback.onStandby(false, HdmiControlService.STANDBY_SCREEN_OFF);
mTestLooper.dispatchAll();
HdmiCecMessage standbyMessageToTv = HdmiCecMessageBuilder.buildStandby(
mHdmiCecLocalDevicePlayback.mAddress, ADDR_TV);
HdmiCecMessage standbyMessageBroadcast = HdmiCecMessageBuilder.buildStandby(
mHdmiCecLocalDevicePlayback.mAddress, ADDR_BROADCAST);
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessageToTv);
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessageBroadcast);
}
@Test
public void handleOnStandby_ScreenOff_ActiveSource_ToTv() {
mHdmiCecLocalDevicePlayback.mService.writeStringSetting(
Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
HdmiControlManager.SEND_STANDBY_ON_SLEEP_TO_TV);
mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
mHdmiCecLocalDevicePlayback.setAutoDeviceOff(true);
mHdmiCecLocalDevicePlayback.onStandby(false, HdmiControlService.STANDBY_SCREEN_OFF);
mTestLooper.dispatchAll();
HdmiCecMessage standbyMessage = HdmiCecMessageBuilder.buildStandby(
HdmiCecMessage standbyMessageToTv = HdmiCecMessageBuilder.buildStandby(
mHdmiCecLocalDevicePlayback.mAddress, ADDR_TV);
HdmiCecMessage standbyMessageBroadcast = HdmiCecMessageBuilder.buildStandby(
mHdmiCecLocalDevicePlayback.mAddress, ADDR_BROADCAST);
assertThat(mNativeWrapper.getResultMessages()).contains(standbyMessage);
assertThat(mNativeWrapper.getResultMessages()).contains(standbyMessageToTv);
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessageBroadcast);
}
@Test
public void handleOnStandby_ScreenOff_ActiveSource_Broadcast() {
mHdmiCecLocalDevicePlayback.mService.writeStringSetting(
Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
HdmiControlManager.SEND_STANDBY_ON_SLEEP_BROADCAST);
mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
mHdmiCecLocalDevicePlayback.setAutoDeviceOff(true);
mHdmiCecLocalDevicePlayback.onStandby(false, HdmiControlService.STANDBY_SCREEN_OFF);
mTestLooper.dispatchAll();
HdmiCecMessage standbyMessageToTv = HdmiCecMessageBuilder.buildStandby(
mHdmiCecLocalDevicePlayback.mAddress, ADDR_TV);
HdmiCecMessage standbyMessageBroadcast = HdmiCecMessageBuilder.buildStandby(
mHdmiCecLocalDevicePlayback.mAddress, ADDR_BROADCAST);
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessageToTv);
assertThat(mNativeWrapper.getResultMessages()).contains(standbyMessageBroadcast);
}
@Test
public void handleOnStandby_ScreenOff_ActiveSource_None() {
mHdmiCecLocalDevicePlayback.mService.writeStringSetting(
Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
HdmiControlManager.SEND_STANDBY_ON_SLEEP_NONE);
mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
mHdmiCecLocalDevicePlayback.setAutoDeviceOff(true);
mHdmiCecLocalDevicePlayback.onStandby(false, HdmiControlService.STANDBY_SCREEN_OFF);
mTestLooper.dispatchAll();
HdmiCecMessage standbyMessageToTv = HdmiCecMessageBuilder.buildStandby(
mHdmiCecLocalDevicePlayback.mAddress, ADDR_TV);
HdmiCecMessage standbyMessageBroadcast = HdmiCecMessageBuilder.buildStandby(
mHdmiCecLocalDevicePlayback.mAddress, ADDR_BROADCAST);
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessageToTv);
assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessageBroadcast);
}
@Test