Add setStreamPath handlers and do input switching according to the new
active path. ag/4959473 SetStreamPath diff is based on Patch 2 Test: local test. Bug: 112477738 Change-Id: I9628330dd2cbb48c1ccba7da40ebc28a05f3a495
This commit is contained in:
@@ -333,6 +333,14 @@ final class Constants {
|
||||
static final String PROPERTY_HDMI_CEC_NEVER_CLAIM_PLAYBACK_LOGICAL_ADDRESS =
|
||||
"ro.hdmi.property_hdmi_cec_never_claim_playback_logical_address";
|
||||
|
||||
/**
|
||||
* Property to indicate if the current device is a cec switch device.
|
||||
*
|
||||
* <p> Default is false.
|
||||
*/
|
||||
static final String PROPERTY_HDMI_IS_DEVICE_HDMI_CEC_SWITCH =
|
||||
"ro.hdmi.property_is_device_hdmi_cec_switch";
|
||||
|
||||
// Set to false to allow playback device to go to suspend mode even
|
||||
// when it's an active source. True by default.
|
||||
static final String PROPERTY_KEEP_AWAKE = "persist.sys.hdmi.keep_awake";
|
||||
|
||||
@@ -34,6 +34,8 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.hdmi.Constants.AudioCodec;
|
||||
import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Represent a logical device of type {@link HdmiDeviceInfo#DEVICE_AUDIO_SYSTEM} residing in Android
|
||||
* system.
|
||||
@@ -62,9 +64,17 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
|
||||
// AVR as audio receiver.
|
||||
@ServiceThreadOnly private boolean mArcEstablished = false;
|
||||
|
||||
// If the current device uses TvInput for ARC. We assume all other inputs also use TvInput
|
||||
// when ARC is using TvInput.
|
||||
private boolean mArcIntentUsed = SystemProperties
|
||||
.get(Constants.PROPERTY_SYSTEM_AUDIO_DEVICE_ARC_PORT, "0").contains("tvinput");
|
||||
|
||||
// Keeps the mapping (HDMI port ID to TV input URI) to keep track of the TV inputs ready to
|
||||
// accept input switching request from HDMI devices. Requests for which the corresponding
|
||||
// input ID is not yet registered by TV input framework need to be buffered for delayed
|
||||
// processing.
|
||||
private final HashMap<Integer, String> mTvInputs = new HashMap<>();
|
||||
|
||||
protected HdmiCecLocalDeviceAudioSystem(HdmiControlService service) {
|
||||
super(service, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
|
||||
mSystemAudioControlFeatureEnabled = true;
|
||||
@@ -75,6 +85,13 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
|
||||
Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED, true);
|
||||
mAutoTvOff = mService.readBooleanSetting(
|
||||
Global.HDMI_CONTROL_AUTO_TV_OFF_ENABLED, true);
|
||||
// TODO(amyjojo): make the map ro property.
|
||||
mTvInputs.put(Constants.CEC_SWITCH_HDMI1,
|
||||
"com.droidlogic.tvinput/.services.Hdmi1InputService/HW5");
|
||||
mTvInputs.put(Constants.CEC_SWITCH_HDMI2,
|
||||
"com.droidlogic.tvinput/.services.Hdmi2InputService/HW6");
|
||||
mTvInputs.put(Constants.CEC_SWITCH_HDMI3,
|
||||
"com.droidlogic.tvinput/.services.Hdmi3InputService/HW7");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -594,20 +611,23 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
|
||||
protected void switchInputOnReceivingNewActivePath(int physicalAddress) {
|
||||
int port = getLocalPortFromPhysicalAddress(physicalAddress);
|
||||
// Wake up if the new Active Source is the current device or under it
|
||||
// or if Arc is enabled.
|
||||
if ((isArcEnabled() || port >= 0) && mService.isPowerStandbyOrTransient()) {
|
||||
// or if System Audio Control is enabled.
|
||||
if ((isSystemAudioActivated() || port >= 0) && mService.isPowerStandbyOrTransient()) {
|
||||
mService.wakeUp();
|
||||
}
|
||||
|
||||
if (isArcEnabled() && port < 0) {
|
||||
// New active source will trigger arc input switching.
|
||||
if (isSystemAudioActivated() && port < 0) {
|
||||
// If system audio mode is on and the new active source is not under the current device,
|
||||
// Will switch to ARC input.
|
||||
// TODO(b/115637145): handle system aduio without ARC
|
||||
routeToInputFromPortId(Constants.CEC_SWITCH_ARC);
|
||||
} else if (port >= 0) {
|
||||
// TODO(amyjojo): Routing Control input swithcing.
|
||||
} else if (mIsSwitchDevice && port >= 0) {
|
||||
// If current device is a switch and the new active source is under it,
|
||||
// will switch to the corresponding active path.
|
||||
routeToInputFromPortId(port);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void routeToInputFromPortId(int portId) {
|
||||
if (mArcIntentUsed) {
|
||||
routeToTvInputFromPortId(portId);
|
||||
@@ -622,14 +642,19 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
|
||||
return;
|
||||
}
|
||||
// TODO(amyjojo): handle if switching to the current input
|
||||
if (portId == Constants.CEC_SWITCH_HOME) {
|
||||
if (portId == Constants.CEC_SWITCH_HOME && mService.isPlaybackDevice()) {
|
||||
switchToHomeTvInput();
|
||||
} else if (portId == Constants.CEC_SWITCH_ARC) {
|
||||
switchToTvInput(SystemProperties.get(Constants.PROPERTY_SYSTEM_AUDIO_DEVICE_ARC_PORT));
|
||||
// TODO(amyjojo): check if setParameters is still needed.
|
||||
return;
|
||||
} else {
|
||||
// TODO(amyjojo): map port number parsed from physical address to LocalActivePort id
|
||||
String uri = mTvInputs.get(portId);
|
||||
if (uri != null) {
|
||||
switchToTvInput(mTvInputs.get(portId));
|
||||
} else {
|
||||
HdmiLogger.debug("Port number does not match any Tv Input.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
setLocalActivePort(portId);
|
||||
|
||||
@@ -266,7 +266,8 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource {
|
||||
setIsActiveSource(physicalAddress == mService.getPhysicalAddress());
|
||||
}
|
||||
|
||||
private void wakeUpIfActiveSource() {
|
||||
@Override
|
||||
protected void wakeUpIfActiveSource() {
|
||||
if (!mIsActiveSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.server.hdmi;
|
||||
import android.hardware.hdmi.HdmiControlManager;
|
||||
import android.hardware.hdmi.IHdmiControlCallback;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
@@ -38,6 +39,11 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
|
||||
// Indicate if current device is Active Source or not
|
||||
private boolean mIsActiveSource = false;
|
||||
|
||||
// Device has cec switch functionality or not.
|
||||
// Default is false.
|
||||
protected boolean mIsSwitchDevice = SystemProperties.getBoolean(
|
||||
Constants.PROPERTY_HDMI_IS_DEVICE_HDMI_CEC_SWITCH, false);
|
||||
|
||||
// Local active port number used for Routing Control.
|
||||
// This records the default active port or the previous valid active port.
|
||||
// Default is HOME input.
|
||||
@@ -123,19 +129,52 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ServiceThreadOnly
|
||||
protected boolean handleSetStreamPath(HdmiCecMessage message) {
|
||||
assertRunOnServiceThread();
|
||||
int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams());
|
||||
// If current device is the target path, set to Active Source.
|
||||
// If the path is under the current device, should switch
|
||||
if (physicalAddress == mService.getPhysicalAddress() && mService.isPlaybackDevice()) {
|
||||
setAndBroadcastActiveSource(message, physicalAddress);
|
||||
}
|
||||
switchInputOnReceivingNewActivePath(physicalAddress);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Method to switch Input with the new Active Path.
|
||||
// All the devices with Switch functionality should implement this.
|
||||
protected void switchInputOnReceivingNewActivePath(int physicalAddress) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
// Active source claiming needs to be handled in the parent class
|
||||
// since we decide who will be the active source when the device supports
|
||||
// multiple device types in this method.
|
||||
// This method should only be called when the device can be the active source.
|
||||
protected void setAndBroadcastActiveSource(HdmiCecMessage message, int physicalAddress) {
|
||||
// If the device has both playback and audio system logical addresses,
|
||||
// playback will claim active source. Otherwise audio system will.
|
||||
HdmiCecLocalDevice deviceToBeActiveSource = mService.playback();
|
||||
if (deviceToBeActiveSource == null) {
|
||||
deviceToBeActiveSource = mService.audioSystem();
|
||||
}
|
||||
if (this == deviceToBeActiveSource) {
|
||||
ActiveSource activeSource = ActiveSource.of(mAddress, physicalAddress);
|
||||
setIsActiveSource(true);
|
||||
setActiveSource(activeSource);
|
||||
wakeUpIfActiveSource();
|
||||
maySendActiveSource(message.getSource());
|
||||
}
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
void setIsActiveSource(boolean on) {
|
||||
assertRunOnServiceThread();
|
||||
mIsActiveSource = on;
|
||||
}
|
||||
|
||||
protected void maySendActiveSource(int dest) {
|
||||
if (mIsActiveSource) {
|
||||
mService.sendCecCommand(HdmiCecMessageBuilder.buildActiveSource(
|
||||
mAddress, mService.getPhysicalAddress()));
|
||||
}
|
||||
}
|
||||
|
||||
@ServiceThreadOnly
|
||||
// Check if current device is the Active Source
|
||||
boolean isActiveSource() {
|
||||
@@ -143,16 +182,22 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
|
||||
return mIsActiveSource;
|
||||
}
|
||||
|
||||
// Method to switch Input with the port id.
|
||||
// All the devices with Switch functionality should implement this.
|
||||
protected void routeToInputFromPortId(int portId) {
|
||||
// do nothing
|
||||
protected void wakeUpIfActiveSource() {
|
||||
if (!mIsActiveSource) {
|
||||
return;
|
||||
}
|
||||
// Wake up the device if the power is in standby mode
|
||||
if (mService.isPowerStandbyOrTransient()) {
|
||||
mService.wakeUp();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Method to switch Input with the new Active Path.
|
||||
// All the devices with Switch functionality should implement this.
|
||||
protected void switchInputOnReceivingNewActivePath(int physicalAddress) {
|
||||
// do nothing
|
||||
protected void maySendActiveSource(int dest) {
|
||||
if (mIsActiveSource) {
|
||||
mService.sendCecCommand(HdmiCecMessageBuilder.buildActiveSource(
|
||||
mAddress, mService.getPhysicalAddress()));
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
||||
@@ -2114,11 +2114,15 @@ public class HdmiControlService extends SystemService {
|
||||
return mLocalDevices.contains(HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
|
||||
}
|
||||
|
||||
boolean isPlaybackDevice() {
|
||||
return mLocalDevices.contains(HdmiDeviceInfo.DEVICE_PLAYBACK);
|
||||
}
|
||||
|
||||
boolean isTvDeviceEnabled() {
|
||||
return isTvDevice() && tv() != null;
|
||||
}
|
||||
|
||||
private HdmiCecLocalDevicePlayback playback() {
|
||||
protected HdmiCecLocalDevicePlayback playback() {
|
||||
return (HdmiCecLocalDevicePlayback)
|
||||
mCecController.getLocalDevice(HdmiDeviceInfo.DEVICE_PLAYBACK);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user