Add APIs to expose some cec control to other services.

ag/5398143

We exposed Power on/Power off/Device select/Connected device list
query from HdmiControlManager.

Test: local tested
Bug: 117775357
Change-Id: Iee495e7131f44282a60e83ad827faa1431a30389
This commit is contained in:
Amy
2018-10-30 16:38:33 -07:00
committed by shubang
parent 0063811f18
commit 6f031afecf
4 changed files with 161 additions and 3 deletions

View File

@@ -33,6 +33,8 @@ import android.os.SystemProperties;
import android.util.ArrayMap;
import android.util.Log;
import java.util.List;
/**
* The {@link HdmiControlManager} class is used to send HDMI control messages
* to attached CEC devices.
@@ -403,6 +405,72 @@ public final class HdmiControlManager {
return (HdmiSwitchClient) getClient(HdmiDeviceInfo.DEVICE_PURE_CEC_SWITCH);
}
/**
* Get a snapshot of the real-time status of the remote devices.
*
* @return a list of {@link HdmiDeviceInfo} of the devices connected to the current device.
*
* TODO(b/110094868): unhide for Q
* @hide
*/
public List<HdmiDeviceInfo> getConnectedDevicesList() {
try {
return mService.getDeviceList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Power off the target device.
*
* @param deviceInfo HdmiDeviceInfo of the device to be powered off
*
* TODO(b/110094868): unhide for Q
* @hide
*/
public void powerOffRemoteDevice(HdmiDeviceInfo deviceInfo) {
try {
mService.powerOffRemoteDevice(
deviceInfo.getLogicalAddress(), deviceInfo.getDevicePowerStatus());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Power on the target device.
*
* @param deviceInfo HdmiDeviceInfo of the device to be powered on
*
* TODO(b/110094868): unhide for Q
* @hide
*/
public void powerOnRemoteDevice(HdmiDeviceInfo deviceInfo) {
try {
mService.powerOnRemoteDevice(
deviceInfo.getLogicalAddress(), deviceInfo.getDevicePowerStatus());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Ask the target device to be the new Active Source.
*
* @param deviceInfo HdmiDeviceInfo of the target device
*
* TODO(b/110094868): unhide for Q
* @hide
*/
public void askRemoteDeviceToBecomeActiveSource(HdmiDeviceInfo deviceInfo) {
try {
mService.askRemoteDeviceToBecomeActiveSource(deviceInfo.getPhysicalAddress());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Controls standby mode of the system. It will also try to turn on/off the connected devices if
* necessary.

View File

@@ -61,6 +61,9 @@ interface IHdmiControlService {
void setInputChangeListener(IHdmiInputChangeListener listener);
List<HdmiDeviceInfo> getInputDevices();
List<HdmiDeviceInfo> getDeviceList();
void powerOffRemoteDevice(int logicalAddress, int powerStatus);
void powerOnRemoteDevice(int logicalAddress, int powerStatus);
void askRemoteDeviceToBecomeActiveSource(int physicalAddress);
void sendVendorCommand(int deviceType, int targetAddress, in byte[] params,
boolean hasVendorId);
void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType);

View File

@@ -327,6 +327,18 @@ public class HdmiAudioSystemClientTest {
public int getPhysicalAddress() {
return 0x0000;
}
@Override
public void powerOffRemoteDevice(int logicalAddress, int powerStatus) {
}
@Override
public void powerOnRemoteDevice(int logicalAddress, int powerStatus) {
}
@Override
public void askRemoteDeviceToBecomeActiveSource(int physicalAddress) {
}
}
}

View File

@@ -20,6 +20,7 @@ import static android.hardware.hdmi.HdmiControlManager.DEVICE_EVENT_ADD_DEVICE;
import static android.hardware.hdmi.HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE;
import static com.android.internal.os.RoSystemProperties.PROPERTY_HDMI_IS_DEVICE_HDMI_CEC_SWITCH;
import static com.android.server.hdmi.Constants.ADDR_UNREGISTERED;
import static com.android.server.hdmi.Constants.DISABLED;
import static com.android.server.hdmi.Constants.ENABLED;
import static com.android.server.hdmi.Constants.OPTION_MHL_ENABLE;
@@ -1615,13 +1616,64 @@ public class HdmiControlService extends SystemService {
public List<HdmiDeviceInfo> getDeviceList() {
enforceAccessPermission();
HdmiCecLocalDeviceTv tv = tv();
synchronized (mLock) {
return (tv == null)
if (tv != null) {
synchronized (mLock) {
return tv.getSafeCecDevicesLocked();
}
} else {
HdmiCecLocalDeviceAudioSystem audioSystem = audioSystem();
synchronized (mLock) {
return (audioSystem == null)
? Collections.<HdmiDeviceInfo>emptyList()
: tv.getSafeCecDevicesLocked();
: audioSystem.getSafeCecDevicesLocked();
}
}
}
@Override
public void powerOffRemoteDevice(int logicalAddress, int powerStatus) {
enforceAccessPermission();
runOnServiceThread(new Runnable() {
@Override
public void run() {
if (powerStatus == HdmiControlManager.POWER_STATUS_ON
|| powerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON) {
sendCecCommand(HdmiCecMessageBuilder.buildStandby(
getRemoteControlSourceAddress(), logicalAddress));
} else {
Slog.w(TAG, "Device " + logicalAddress + " is already off " + powerStatus);
}
}
});
}
@Override
public void powerOnRemoteDevice(int logicalAddress, int powerStatus) {
// TODO(amyjojo): implement the method
}
@Override
// TODO(AMYJOJO): add a result callback
public void askRemoteDeviceToBecomeActiveSource(int physicalAddress) {
enforceAccessPermission();
runOnServiceThread(new Runnable() {
@Override
public void run() {
HdmiCecMessage setStreamPath = HdmiCecMessageBuilder.buildSetStreamPath(
getRemoteControlSourceAddress(), physicalAddress);
if (pathToPortId(physicalAddress) != Constants.INVALID_PORT_ID) {
if (getSwitchDevice() != null) {
getSwitchDevice().handleSetStreamPath(setStreamPath);
} else {
Slog.e(TAG, "Can't get the correct local device to handle routing.");
}
} else {
sendCecCommand(setStreamPath);
}
}
});
}
@Override
public void setSystemAudioVolume(final int oldIndex, final int newIndex,
final int maxIndex) {
@@ -1917,6 +1969,29 @@ public class HdmiControlService extends SystemService {
}
}
// Get the source address to send out commands to devices connected to the current device
// when other services interact with HdmiControlService.
private int getRemoteControlSourceAddress() {
if (isAudioSystemDevice()) {
return audioSystem().getDeviceInfo().getLogicalAddress();
} else if (isPlaybackDevice()) {
return playback().getDeviceInfo().getLogicalAddress();
}
return ADDR_UNREGISTERED;
}
// Get the switch device to do CEC routing control
@Nullable
private HdmiCecLocalDeviceSource getSwitchDevice() {
if (isAudioSystemDevice()) {
return audioSystem();
}
if (isPlaybackDevice()) {
return playback();
}
return null;
}
@ServiceThreadOnly
private void oneTouchPlay(final IHdmiControlCallback callback) {
assertRunOnServiceThread();