Merge "Refine new device action."
This commit is contained in:
committed by
Android (Google) Code Review
commit
7237cd811c
@@ -67,7 +67,10 @@ final class ActiveSourceHandler {
|
||||
}
|
||||
HdmiCecDeviceInfo device = mService.getDeviceInfo(deviceLogicalAddress);
|
||||
if (device == null) {
|
||||
// TODO: Start new device action (Device Discovery) sequence 5.
|
||||
// "New device action" initiated by <Active Source> does not require
|
||||
// "Routing change action".
|
||||
mService.addAndStartAction(new NewDeviceAction(mService, mSourceAddress,
|
||||
deviceLogicalAddress, routingPath, false));
|
||||
}
|
||||
|
||||
if (!mService.isInPresetInstallationMode()) {
|
||||
|
||||
@@ -55,9 +55,6 @@ final class DeviceDiscoveryAction extends FeatureAction {
|
||||
|
||||
private static final int DEVICE_POLLING_RETRY = 1;
|
||||
|
||||
// TODO: Move this to common place
|
||||
private static final int INVALID_PHYSICAL_ADDRESS = 0xFFFF;
|
||||
|
||||
/**
|
||||
* Interface used to report result of device discovery.
|
||||
*/
|
||||
@@ -75,7 +72,7 @@ final class DeviceDiscoveryAction extends FeatureAction {
|
||||
private static final class DeviceInfo {
|
||||
private final int mLogicalAddress;
|
||||
|
||||
private int mPhysicalAddress = INVALID_PHYSICAL_ADDRESS;
|
||||
private int mPhysicalAddress = HdmiConstants.INVALID_PHYSICAL_ADDRESS;
|
||||
private int mVendorId = HdmiCec.UNKNOWN_VENDOR_ID;
|
||||
private String mDisplayName = "";
|
||||
private int mDeviceType = HdmiCec.DEVICE_INACTIVE;
|
||||
|
||||
@@ -220,4 +220,8 @@ final class DeviceSelectAction extends FeatureAction {
|
||||
Slog.e(TAG, "Callback failed:" + e);
|
||||
}
|
||||
}
|
||||
|
||||
int getTargetAddress() {
|
||||
return mTarget.getLogicalAddress();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ abstract class HdmiCecLocalDevice {
|
||||
return onMessage(message);
|
||||
}
|
||||
|
||||
protected boolean onMessage(HdmiCecMessage message) {
|
||||
protected final boolean onMessage(HdmiCecMessage message) {
|
||||
switch (message.getOpcode()) {
|
||||
case HdmiCec.MESSAGE_GET_MENU_LANGUAGE:
|
||||
return handleGetMenuLanguage(message);
|
||||
@@ -88,6 +88,8 @@ abstract class HdmiCecLocalDevice {
|
||||
return handleGiveDeviceVendorId();
|
||||
case HdmiCec.MESSAGE_GET_CEC_VERSION:
|
||||
return handleGetCecVersion(message);
|
||||
case HdmiCec.MESSAGE_REPORT_PHYSICAL_ADDRESS:
|
||||
return handleReportPhysicalAddress(message);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -143,6 +145,10 @@ abstract class HdmiCecLocalDevice {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean handleReportPhysicalAddress(HdmiCecMessage message) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final void handleAddressAllocated(int logicalAddress) {
|
||||
mAddress = mPreferredAddress = logicalAddress;
|
||||
onAddressAllocated(logicalAddress);
|
||||
|
||||
@@ -16,13 +16,15 @@
|
||||
|
||||
package com.android.server.hdmi;
|
||||
|
||||
import android.hardware.hdmi.IHdmiControlCallback;
|
||||
import android.hardware.hdmi.HdmiCec;
|
||||
import android.hardware.hdmi.HdmiCecDeviceInfo;
|
||||
import android.hardware.hdmi.HdmiCecMessage;
|
||||
import android.hardware.hdmi.IHdmiControlCallback;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.hdmi.DeviceDiscoveryAction.DeviceDiscoveryCallback;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -46,20 +48,10 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
mService.sendCecCommand(HdmiCecMessageBuilder.buildDeviceVendorIdCommand(
|
||||
mAddress, mService.getVendorId()));
|
||||
|
||||
mService.launchDeviceDiscovery(mAddress);
|
||||
launchDeviceDiscovery();
|
||||
// TODO: Start routing control action, device discovery action.
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onMessage(HdmiCecMessage message) {
|
||||
switch (message.getOpcode()) {
|
||||
case HdmiCec.MESSAGE_REPORT_PHYSICAL_ADDRESS:
|
||||
return handleReportPhysicalAddress(message);
|
||||
default:
|
||||
return super.onMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the action 'device select', or 'one touch play' initiated by TV.
|
||||
*
|
||||
@@ -98,7 +90,8 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean handleReportPhysicalAddress(HdmiCecMessage message) {
|
||||
@Override
|
||||
protected boolean handleReportPhysicalAddress(HdmiCecMessage message) {
|
||||
// Ignore if [Device Discovery Action] is going on.
|
||||
if (mService.hasAction(DeviceDiscoveryAction.class)) {
|
||||
Slog.i(TAG, "Ignore unrecognizable <Report Physical Address> "
|
||||
@@ -107,9 +100,15 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
}
|
||||
|
||||
int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams());
|
||||
mService.addAndStartAction(new NewDeviceAction(mService,
|
||||
mAddress, message.getSource(), physicalAddress));
|
||||
int logicalAddress = message.getSource();
|
||||
|
||||
// If it is a new device and connected to the tail of active path,
|
||||
// it's required to change routing path.
|
||||
boolean requireRoutingChange = !mService.isInDeviceList(physicalAddress, logicalAddress)
|
||||
&& mService.isTailOfActivePath(physicalAddress);
|
||||
mService.addAndStartAction(new NewDeviceAction(mService,
|
||||
mAddress, message.getSource(), physicalAddress,
|
||||
requireRoutingChange));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -137,4 +136,29 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
||||
HdmiConstants.ABORT_REFUSED));
|
||||
return true;
|
||||
}
|
||||
|
||||
private void launchDeviceDiscovery() {
|
||||
mService.clearAllDeviceInfo();
|
||||
// TODO: Move the following callback to HdmiLocalDeviceTv.
|
||||
DeviceDiscoveryAction action = new DeviceDiscoveryAction(mService, mAddress,
|
||||
new DeviceDiscoveryCallback() {
|
||||
@Override
|
||||
public void onDeviceDiscoveryDone(List<HdmiCecDeviceInfo> deviceInfos) {
|
||||
for (HdmiCecDeviceInfo info : deviceInfos) {
|
||||
mService.addCecDevice(info);
|
||||
}
|
||||
|
||||
// Since we removed all devices when it's start and
|
||||
// device discovery action does not poll local devices,
|
||||
// we should put device info of local device manually here
|
||||
for (HdmiCecLocalDevice device : mService.getAllLocalDevices()) {
|
||||
mService.addCecDevice(device.getDeviceInfo());
|
||||
}
|
||||
|
||||
mService.addAndStartAction(new HotplugDetectionAction(mService,
|
||||
mAddress));
|
||||
}
|
||||
});
|
||||
mService.addAndStartAction(action);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,5 +77,8 @@ final class HdmiConstants {
|
||||
*/
|
||||
static final int FLAG_HDMI_OPTION_SYSTEM_CEC_CONTROL = 3;
|
||||
|
||||
static final int INVALID_PORT_ID = -1;
|
||||
static final int INVALID_PHYSICAL_ADDRESS = 0xFFFF;
|
||||
|
||||
private HdmiConstants() { /* cannot be instantiated */ }
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.content.Context;
|
||||
import android.hardware.hdmi.HdmiCec;
|
||||
import android.hardware.hdmi.HdmiCecDeviceInfo;
|
||||
import android.hardware.hdmi.HdmiCecMessage;
|
||||
import android.hardware.hdmi.HdmiHotplugEvent;
|
||||
import android.hardware.hdmi.HdmiPortInfo;
|
||||
import android.hardware.hdmi.IHdmiControlCallback;
|
||||
import android.hardware.hdmi.IHdmiControlService;
|
||||
@@ -37,7 +38,6 @@ import android.util.SparseIntArray;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.server.SystemService;
|
||||
import com.android.server.hdmi.DeviceDiscoveryAction.DeviceDiscoveryCallback;
|
||||
import com.android.server.hdmi.HdmiCecController.AllocateAddressCallback;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -296,7 +296,7 @@ public final class HdmiControlService extends SystemService {
|
||||
HdmiPortInfo portInfo = getPortInfo(portId);
|
||||
if (portInfo == null) {
|
||||
Slog.e(TAG, "Cannot find the port info: " + portId);
|
||||
return 0xFFFF; // Use HdmiConstants.INVALID_PHYSICAL_ADDRESS;
|
||||
return HdmiConstants.INVALID_PHYSICAL_ADDRESS;
|
||||
}
|
||||
return portInfo.getAddress();
|
||||
}
|
||||
@@ -314,7 +314,7 @@ public final class HdmiControlService extends SystemService {
|
||||
return info.getId();
|
||||
}
|
||||
}
|
||||
return -1; // Use HdmiConstants.INVALID_PORT_ID;
|
||||
return HdmiConstants.INVALID_PORT_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -446,7 +446,12 @@ public final class HdmiControlService extends SystemService {
|
||||
|
||||
void setSystemAudioMode(boolean on) {
|
||||
synchronized (mLock) {
|
||||
mSystemAudioMode = on;
|
||||
if (on != mSystemAudioMode) {
|
||||
mSystemAudioMode = on;
|
||||
// TODO: Need to set the preference for SystemAudioMode.
|
||||
// TODO: Need to handle the notification of changing the mode and
|
||||
// to identify the notification should be handled in the service or TvSettings.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,6 +461,19 @@ public final class HdmiControlService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a device of the specified physical address is connected to ARC enabled port.
|
||||
*/
|
||||
boolean isConnectedToArcPort(int physicalAddress) {
|
||||
for (HdmiPortInfo portInfo : mPortInfo) {
|
||||
if (hasSameTopPort(portInfo.getAddress(), physicalAddress)
|
||||
&& portInfo.isArcSupported()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// See if we have an action of a given type in progress.
|
||||
<T extends FeatureAction> boolean hasAction(final Class<T> clazz) {
|
||||
for (FeatureAction action : mActions) {
|
||||
@@ -466,6 +484,17 @@ public final class HdmiControlService extends SystemService {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns all actions matched with given class type.
|
||||
<T extends FeatureAction> List<T> getActions(final Class<T> clazz) {
|
||||
ArrayList<T> actions = new ArrayList<>();
|
||||
for (FeatureAction action : mActions) {
|
||||
if (action.getClass().equals(clazz)) {
|
||||
actions.add((T) action);
|
||||
}
|
||||
}
|
||||
return actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the given {@link FeatureAction} object from the action queue.
|
||||
*
|
||||
@@ -529,6 +558,15 @@ public final class HdmiControlService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether ARC is enabled or not.
|
||||
*/
|
||||
boolean getArcStatus() {
|
||||
synchronized (mLock) {
|
||||
return mArcStatusEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transmit a CEC command to CEC bus.
|
||||
*
|
||||
@@ -573,12 +611,23 @@ public final class HdmiControlService extends SystemService {
|
||||
return dispatchMessageToLocalDevice(message);
|
||||
}
|
||||
|
||||
private boolean dispatchMessageToAction(HdmiCecMessage message) {
|
||||
for (FeatureAction action : mActions) {
|
||||
if (action.processCommand(message)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean dispatchMessageToLocalDevice(HdmiCecMessage message) {
|
||||
for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {
|
||||
if (device.dispatchMessage(message)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Slog.w(TAG, "Unhandled cec command:" + message);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -589,7 +638,18 @@ public final class HdmiControlService extends SystemService {
|
||||
* @param connected whether to be plugged in or not
|
||||
*/
|
||||
void onHotplug(int portNo, boolean connected) {
|
||||
// TODO: Start "RequestArcInitiationAction" if ARC port.
|
||||
assertRunOnServiceThread();
|
||||
// TODO: delegate onHotplug event to each local device.
|
||||
|
||||
// Tv device will have permanent HotplugDetectionAction.
|
||||
List<HotplugDetectionAction> hotplugActions = getActions(HotplugDetectionAction.class);
|
||||
if (!hotplugActions.isEmpty()) {
|
||||
// Note that hotplug action is single action running on a machine.
|
||||
// "pollAllDevicesNow" cleans up timer and start poll action immediately.
|
||||
hotplugActions.get(0).pollAllDevicesNow();
|
||||
}
|
||||
|
||||
announceHotplugEvent(portNo, connected);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -617,35 +677,32 @@ public final class HdmiControlService extends SystemService {
|
||||
return strategy | iterationStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch device discovery sequence. It starts with clearing the existing device info list.
|
||||
* Note that it assumes that logical address of all local devices is already allocated.
|
||||
*
|
||||
* @param sourceAddress a logical address of tv
|
||||
*/
|
||||
void launchDeviceDiscovery(final int sourceAddress) {
|
||||
// At first, clear all existing device infos.
|
||||
void clearAllDeviceInfo() {
|
||||
assertRunOnServiceThread();
|
||||
mCecController.clearDeviceInfoList();
|
||||
// TODO: flush cec message cache when CEC is turned off.
|
||||
}
|
||||
|
||||
DeviceDiscoveryAction action = new DeviceDiscoveryAction(this, sourceAddress,
|
||||
new DeviceDiscoveryCallback() {
|
||||
@Override
|
||||
public void onDeviceDiscoveryDone(List<HdmiCecDeviceInfo> deviceInfos) {
|
||||
for (HdmiCecDeviceInfo info : deviceInfos) {
|
||||
addCecDevice(info);
|
||||
}
|
||||
List<HdmiCecLocalDevice> getAllLocalDevices() {
|
||||
assertRunOnServiceThread();
|
||||
return mCecController.getLocalDeviceList();
|
||||
}
|
||||
|
||||
// Add device info of all local devices.
|
||||
for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {
|
||||
addCecDevice(device.getDeviceInfo());
|
||||
}
|
||||
|
||||
addAndStartAction(new HotplugDetectionAction(HdmiControlService.this,
|
||||
sourceAddress));
|
||||
}
|
||||
});
|
||||
addAndStartAction(action);
|
||||
/**
|
||||
* Whether a device of the specified physical address and logical address exists
|
||||
* in a device info list. However, both are minimal condition and it could
|
||||
* be different device from the original one.
|
||||
*
|
||||
* @param physicalAddress physical address of a device to be searched
|
||||
* @param logicalAddress logical address of a device to be searched
|
||||
* @return true if exist; otherwise false
|
||||
*/
|
||||
boolean isInDeviceList(int physicalAddress, int logicalAddress) {
|
||||
assertRunOnServiceThread();
|
||||
HdmiCecDeviceInfo device = mCecController.getDeviceInfo(logicalAddress);
|
||||
if (device == null) {
|
||||
return false;
|
||||
}
|
||||
return device.getPhysicalAddress() == physicalAddress;
|
||||
}
|
||||
|
||||
private HdmiCecDeviceInfo createDeviceInfo(int logicalAddress, int deviceType) {
|
||||
@@ -675,16 +732,6 @@ public final class HdmiControlService extends SystemService {
|
||||
addAndStartAction(action);
|
||||
}
|
||||
|
||||
private boolean dispatchMessageToAction(HdmiCecMessage message) {
|
||||
for (FeatureAction action : mActions) {
|
||||
if (action.processCommand(message)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Slog.w(TAG, "Unsupported cec command:" + message);
|
||||
return false;
|
||||
}
|
||||
|
||||
private void handleSetSystemAudioMode(HdmiCecMessage message) {
|
||||
if (dispatchMessageToAction(message) || !isMessageForSystemAudio(message)) {
|
||||
return;
|
||||
@@ -730,10 +777,6 @@ public final class HdmiControlService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
void addCecDevice(HdmiCecDeviceInfo info) {
|
||||
mCecController.addDeviceInfo(info);
|
||||
}
|
||||
|
||||
private void enforceAccessPermission() {
|
||||
getContext().enforceCallingOrSelfPermission(PERMISSION, TAG);
|
||||
}
|
||||
@@ -768,7 +811,6 @@ public final class HdmiControlService extends SystemService {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void oneTouchPlay(final IHdmiControlCallback callback) {
|
||||
enforceAccessPermission();
|
||||
@@ -910,6 +952,17 @@ public final class HdmiControlService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a device is newly added or a new device is detected.
|
||||
*
|
||||
* @param info device info of a new device.
|
||||
*/
|
||||
void addCecDevice(HdmiCecDeviceInfo info) {
|
||||
mCecController.addDeviceInfo(info);
|
||||
|
||||
// TODO: announce new device detection.
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a device is removed or removal of device is detected.
|
||||
*
|
||||
@@ -918,9 +971,61 @@ public final class HdmiControlService extends SystemService {
|
||||
void removeCecDevice(int address) {
|
||||
mCecController.removeDeviceInfo(address);
|
||||
mCecMessageCache.flushMessagesFrom(address);
|
||||
|
||||
// TODO: announce a device removal.
|
||||
}
|
||||
|
||||
private void announceHotplugEvent(int portNo, boolean connected) {
|
||||
HdmiHotplugEvent event = new HdmiHotplugEvent(portNo, connected);
|
||||
synchronized (mLock) {
|
||||
for (IHdmiHotplugEventListener listener : mHotplugEventListeners) {
|
||||
invokeHotplugEventListener(listener, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void invokeHotplugEventListener(IHdmiHotplugEventListener listener,
|
||||
HdmiHotplugEvent event) {
|
||||
try {
|
||||
listener.onReceived(event);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Failed to report hotplug event:" + event.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
HdmiCecMessageCache getCecMessageCache() {
|
||||
return mCecMessageCache;
|
||||
}
|
||||
|
||||
private static boolean hasSameTopPort(int path1, int path2) {
|
||||
return (path1 & HdmiConstants.ROUTING_PATH_TOP_MASK)
|
||||
== (path2 & HdmiConstants.ROUTING_PATH_TOP_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the given path is located in the tail of current active path.
|
||||
*
|
||||
* @param path to be tested
|
||||
* @return true if the given path is located in the tail of current active path; otherwise,
|
||||
* false
|
||||
*/
|
||||
// TODO: move this to local device tv.
|
||||
boolean isTailOfActivePath(int path) {
|
||||
// If active routing path is internal source, return false.
|
||||
if (mActiveRoutingPath == 0) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 12; i >= 0; i -= 4) {
|
||||
int curActivePath = (mActiveRoutingPath >> i) & 0xF;
|
||||
if (curActivePath == 0) {
|
||||
return true;
|
||||
} else {
|
||||
int curPath = (path >> i) & 0xF;
|
||||
if (curPath != curActivePath) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +90,20 @@ final class HotplugDetectionAction extends FeatureAction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start device polling immediately.
|
||||
*/
|
||||
void pollAllDevicesNow() {
|
||||
// Clear existing timer to avoid overlapped execution
|
||||
mActionTimer.clearTimerMessage();
|
||||
|
||||
mTimeoutCount = 0;
|
||||
mState = STATE_WAIT_FOR_NEXT_POLLING;
|
||||
pollAllDevices();
|
||||
|
||||
addTimer(mState, POLLING_INTERVAL_MS);
|
||||
}
|
||||
|
||||
// This method is called every 5 seconds.
|
||||
private void pollDevices() {
|
||||
// All device check called every 15 seconds.
|
||||
@@ -180,15 +194,56 @@ final class HotplugDetectionAction extends FeatureAction {
|
||||
}
|
||||
|
||||
private void addDevice(int addedAddress) {
|
||||
// TODO: implement this.
|
||||
// Send <Give Physical Address>.
|
||||
sendCommand(HdmiCecMessageBuilder.buildGivePhysicalAddress(mSourceAddress, addedAddress));
|
||||
}
|
||||
|
||||
private void removeDevice(int removedAddress) {
|
||||
// TODO: move the following logic to local device once move many logic to
|
||||
// local device.
|
||||
mayChangeRoutingPath(removedAddress);
|
||||
mayCancelDeviceSelect(removedAddress);
|
||||
mayCancelOneTouchRecord(removedAddress);
|
||||
mayDisableSystemAudioAndARC(removedAddress);
|
||||
|
||||
mService.removeCecDevice(removedAddress);
|
||||
// TODO: implements following steps.
|
||||
// 1. Launch routing control sequence
|
||||
// 2. Stop one touch play sequence if removed device is the device to be selected.
|
||||
// 3. If audio system, start system audio off and arc off
|
||||
// 4. Inform device remove to others
|
||||
}
|
||||
|
||||
private void mayChangeRoutingPath(int address) {
|
||||
// TODO: if removed address is current active source, it should change active source
|
||||
// path new one. we can keep previous selection or can choose default input,
|
||||
// such as internal tuner. Consider send intent to app so that app
|
||||
// can handle it.
|
||||
}
|
||||
|
||||
private void mayCancelDeviceSelect(int address) {
|
||||
List<DeviceSelectAction> actions = mService.getActions(DeviceSelectAction.class);
|
||||
if (actions.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Should ave only one Device Select Action
|
||||
DeviceSelectAction action = actions.get(0);
|
||||
if (action.getTargetAddress() == address) {
|
||||
mService.removeAction(DeviceSelectAction.class);
|
||||
}
|
||||
}
|
||||
|
||||
private void mayCancelOneTouchRecord(int address) {
|
||||
// TODO: implement this.
|
||||
}
|
||||
|
||||
private void mayDisableSystemAudioAndARC(int address) {
|
||||
if (HdmiCec.getTypeFromAddress(address) != HdmiCec.DEVICE_AUDIO_SYSTEM) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Turn off system audio mode.
|
||||
mService.setSystemAudioMode(false);
|
||||
if (mService.getArcStatus()) {
|
||||
mService.addAndStartAction(
|
||||
new RequestArcTerminationAction(mService, mSourceAddress, address));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ final class NewDeviceAction extends FeatureAction {
|
||||
|
||||
private final int mDeviceLogicalAddress;
|
||||
private final int mDevicePhysicalAddress;
|
||||
private final boolean mRequireRoutingChange;
|
||||
|
||||
private int mVendorId;
|
||||
private String mDisplayName;
|
||||
@@ -59,17 +60,36 @@ final class NewDeviceAction extends FeatureAction {
|
||||
* @param sourceAddress logical address to be used as source address
|
||||
* @param deviceLogicalAddress logical address of the device in interest
|
||||
* @param devicePhysicalAddress physical address of the device in interest
|
||||
* @param requireRoutingChange whether to initiate routing change or not
|
||||
*/
|
||||
NewDeviceAction(HdmiControlService service, int sourceAddress, int deviceLogicalAddress,
|
||||
int devicePhysicalAddress) {
|
||||
int devicePhysicalAddress, boolean requireRoutingChange) {
|
||||
super(service, sourceAddress);
|
||||
mDeviceLogicalAddress = deviceLogicalAddress;
|
||||
mDevicePhysicalAddress = devicePhysicalAddress;
|
||||
mVendorId = HdmiCec.UNKNOWN_VENDOR_ID;
|
||||
mRequireRoutingChange = requireRoutingChange;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
if (HdmiCec.getTypeFromAddress(mSourceAddress) == HdmiCec.DEVICE_AUDIO_SYSTEM) {
|
||||
if (mService.getAvrDeviceInfo() == null) {
|
||||
// TODO: Start system audio initiation action
|
||||
}
|
||||
|
||||
// If new device is connected through ARC enabled port,
|
||||
// initiates ARC channel establishment.
|
||||
if (mService.isConnectedToArcPort(mDevicePhysicalAddress)) {
|
||||
mService.addAndStartAction(new RequestArcInitiationAction(mService, mSourceAddress,
|
||||
mDeviceLogicalAddress));
|
||||
}
|
||||
}
|
||||
|
||||
if (mRequireRoutingChange) {
|
||||
startRoutingChange();
|
||||
}
|
||||
|
||||
mState = STATE_WAITING_FOR_SET_OSD_NAME;
|
||||
if (mayProcessCommandIfCached(mDeviceLogicalAddress, HdmiCec.MESSAGE_SET_OSD_NAME)) {
|
||||
return true;
|
||||
@@ -133,6 +153,22 @@ final class NewDeviceAction extends FeatureAction {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void startRoutingChange() {
|
||||
// Stop existing routing control.
|
||||
mService.removeAction(RoutingControlAction.class);
|
||||
|
||||
// Send routing change. The the address is a path of the active port.
|
||||
int newPath = toTopMostPortPath(mDevicePhysicalAddress);
|
||||
sendCommand(HdmiCecMessageBuilder.buildRoutingChange(mSourceAddress,
|
||||
mService.getActivePath(), newPath));
|
||||
mService.addAndStartAction(new RoutingControlAction(mService, mSourceAddress,
|
||||
mService.pathToPortId(newPath), null));
|
||||
}
|
||||
|
||||
private static int toTopMostPortPath(int physicalAddress) {
|
||||
return physicalAddress & HdmiConstants.ROUTING_PATH_TOP_MASK;
|
||||
}
|
||||
|
||||
private boolean mayProcessCommandIfCached(int destAddress, int opcode) {
|
||||
HdmiCecMessage message = mService.getCecMessageCache().getMessage(destAddress, opcode);
|
||||
if (message != null) {
|
||||
|
||||
@@ -16,12 +16,11 @@
|
||||
|
||||
package com.android.server.hdmi;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import android.hardware.hdmi.IHdmiControlCallback;
|
||||
import android.annotation.Nullable;
|
||||
import android.hardware.hdmi.HdmiCec;
|
||||
import android.hardware.hdmi.HdmiCecDeviceInfo;
|
||||
import android.hardware.hdmi.HdmiCecMessage;
|
||||
import android.hardware.hdmi.IHdmiControlCallback;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Slog;
|
||||
|
||||
@@ -59,7 +58,7 @@ public class RoutingControlAction extends FeatureAction {
|
||||
// Time out in milliseconds used for <Report Power Status>
|
||||
private static final int TIMEOUT_REPORT_POWER_STATUS_MS = 1000;
|
||||
|
||||
private final IHdmiControlCallback mCallback;
|
||||
@Nullable private final IHdmiControlCallback mCallback;
|
||||
|
||||
// The latest routing path. Updated by each <Routing Information> from CEC switches.
|
||||
private int mCurrentRoutingPath;
|
||||
@@ -167,7 +166,7 @@ public class RoutingControlAction extends FeatureAction {
|
||||
case STATE_WAIT_FOR_ROUTING_INFORMATION:
|
||||
HdmiCecDeviceInfo device = mService.getDeviceInfoByPath(mCurrentRoutingPath);
|
||||
if (device == null) {
|
||||
maybeChangeActiveInput(mCurrentRoutingPath);
|
||||
maybeChangeActiveInput(mService.pathToPortId(mCurrentRoutingPath));
|
||||
} else {
|
||||
// TODO: Also check followings and then proceed:
|
||||
// if routing change was neither triggered by TV at CEC enable time, nor
|
||||
@@ -185,7 +184,7 @@ public class RoutingControlAction extends FeatureAction {
|
||||
case STATE_WAIT_FOR_REPORT_POWER_STATUS:
|
||||
int tvPowerStatus = getTvPowerStatus();
|
||||
if (isPowerStatusOnOrTransientToOn(tvPowerStatus)) {
|
||||
if (!maybeChangeActiveInput(mCurrentRoutingPath)) {
|
||||
if (!maybeChangeActiveInput(mService.pathToPortId(mCurrentRoutingPath))) {
|
||||
sendSetStreamPath();
|
||||
}
|
||||
}
|
||||
@@ -217,15 +216,10 @@ public class RoutingControlAction extends FeatureAction {
|
||||
mState = STATE_WAIT_FOR_REPORT_POWER_STATUS;
|
||||
addTimer(mState, TIMEOUT_REPORT_POWER_STATUS_MS);
|
||||
} else {
|
||||
maybeChangeActiveInput(mCurrentRoutingPath);
|
||||
maybeChangeActiveInput(mService.pathToPortId(mCurrentRoutingPath));
|
||||
}
|
||||
}
|
||||
|
||||
// Given the HDMI port id, return the port address.
|
||||
private int portToPath(int portId) {
|
||||
return mService.getPortInfo(portId).getAddress();
|
||||
}
|
||||
|
||||
private void invokeCallback(int result) {
|
||||
if (mCallback == null) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user