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:
Amy
2018-09-06 13:21:08 -07:00
committed by shubang
parent 225d55a429
commit 3403742489
5 changed files with 110 additions and 27 deletions

View File

@@ -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";

View File

@@ -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);

View File

@@ -266,7 +266,8 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource {
setIsActiveSource(physicalAddress == mService.getPhysicalAddress());
}
private void wakeUpIfActiveSource() {
@Override
protected void wakeUpIfActiveSource() {
if (!mIsActiveSource) {
return;
}

View File

@@ -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

View File

@@ -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);
}