CEC: Replace the usage of logical address with id for HdmiDeviceInfo

Introduced 'id' of HdmiDeviceInfo to replace the direct use of logical address
as id. This accomodates the identification of MHL device with ease. Also updated
TIF to use id instead of logical address.

Bug: 16986744
Change-Id: Ifa827fb5e5fcf1d2f612f0845accbfe5c03734aa
This commit is contained in:
Jinsuk Kim
2014-08-13 10:48:30 +09:00
parent 0d79310e25
commit 8960d1b155
10 changed files with 128 additions and 76 deletions

View File

@@ -77,11 +77,18 @@ public class HdmiDeviceInfo implements Parcelable {
/** Invalid port ID */
public static final int PORT_INVALID = -1;
private static final int HDMI_DEVICE_TYPE_OTHER = 0;
private static final int HDMI_DEVICE_TYPE_CEC = 1;
private static final int HDMI_DEVICE_TYPE_MHL = 2;
private static final int HDMI_DEVICE_TYPE_CEC = 0;
private static final int HDMI_DEVICE_TYPE_MHL = 1;
private static final int HDMI_DEVICE_TYPE_HARDWARE = 2;
// Offset used for id value. MHL devices, for instance, will be assigned the value from
// ID_OFFSET_MHL.
private static final int ID_OFFSET_CEC = 0x0;
private static final int ID_OFFSET_MHL = 0x80;
private static final int ID_OFFSET_HARDWARE = 0xC0;
// Common parameters for all device.
private final int mId;
private final int mHdmiDeviceType;
private final int mPhysicalAddress;
private final int mPortId;
@@ -121,7 +128,7 @@ public class HdmiDeviceInfo implements Parcelable {
int deviceId = source.readInt();
int adopterId = source.readInt();
return new HdmiDeviceInfo(physicalAddress, portId, adopterId, deviceId);
case HDMI_DEVICE_TYPE_OTHER:
case HDMI_DEVICE_TYPE_HARDWARE:
return new HdmiDeviceInfo(physicalAddress, portId);
default:
return null;
@@ -152,6 +159,7 @@ public class HdmiDeviceInfo implements Parcelable {
mPhysicalAddress = physicalAddress;
mPortId = portId;
mId = idForCecDevice(logicalAddress);
mLogicalAddress = logicalAddress;
mDeviceType = deviceType;
mVendorId = vendorId;
@@ -180,17 +188,18 @@ public class HdmiDeviceInfo implements Parcelable {
}
/**
* Constructor. Used to initialize the instance for other device.
* Constructor. Used to initialize the instance for device representing hardware port.
*
* @param physicalAddress physical address of HDMI device
* @param physicalAddress physical address of the port
* @param portId HDMI port ID (1 for HDMI1)
* @hide
*/
public HdmiDeviceInfo(int physicalAddress, int portId) {
mHdmiDeviceType = HDMI_DEVICE_TYPE_OTHER;
mHdmiDeviceType = HDMI_DEVICE_TYPE_HARDWARE;
mPhysicalAddress = physicalAddress;
mPortId = portId;
mId = idForHardware(portId);
mLogicalAddress = -1;
mDeviceType = DEVICE_RESERVED;
mVendorId = 0;
@@ -216,6 +225,7 @@ public class HdmiDeviceInfo implements Parcelable {
mPhysicalAddress = physicalAddress;
mPortId = portId;
mId = idForMhlDevice(portId);
mLogicalAddress = -1;
mDeviceType = DEVICE_RESERVED;
mVendorId = 0;
@@ -226,6 +236,45 @@ public class HdmiDeviceInfo implements Parcelable {
mAdopterId = deviceId;
}
/**
* Return the id of the device.
*/
public int getId() {
return mId;
}
/**
* Return the id to be used for CEC device.
*
* @param address logical address of CEC device
* @return id for CEC device
*/
public static int idForCecDevice(int address) {
// The id is generated based on the logical address.
return ID_OFFSET_CEC + address;
}
/**
* Return the id to be used for MHL device.
*
* @param portId port which the MHL device is connected to
* @return id for MHL device
*/
public static int idForMhlDevice(int portId) {
// The id is generated based on the port id since there can be only one MHL device per port.
return ID_OFFSET_MHL + portId;
}
/**
* Return the id to be used for hardware port.
*
* @param portId port id
* @return id for hardware port
*/
public static int idForHardware(int portId) {
return ID_OFFSET_HARDWARE + portId;
}
/**
* Return the CEC logical address of the device.
*/
@@ -367,25 +416,25 @@ public class HdmiDeviceInfo implements Parcelable {
switch (mHdmiDeviceType) {
case HDMI_DEVICE_TYPE_CEC:
s.append("CEC: ");
s.append("logical_address: ").append(mLogicalAddress).append(", ");
s.append("device_type: ").append(mDeviceType).append(", ");
s.append("vendor_id: ").append(mVendorId).append(", ");
s.append("display_name: ").append(mDisplayName).append(", ");
s.append("power_status: ").append(mDevicePowerStatus).append(", ");
s.append("logical_address: ").append(mLogicalAddress).append(" ");
s.append("device_type: ").append(mDeviceType).append(" ");
s.append("vendor_id: ").append(mVendorId).append(" ");
s.append("display_name: ").append(mDisplayName).append(" ");
s.append("power_status: ").append(mDevicePowerStatus).append(" ");
break;
case HDMI_DEVICE_TYPE_MHL:
s.append("MHL: ");
s.append("device_id: ").append(mDeviceId).append(" ");
s.append("adopter_id: ").append(mAdopterId).append(" ");
break;
case HDMI_DEVICE_TYPE_OTHER:
s.append("Other: ");
s.append("device_id: ").append(mDeviceId).append(", ");
s.append("adopter_id: ").append(mAdopterId).append(", ");
case HDMI_DEVICE_TYPE_HARDWARE:
s.append("Hardware: ");
break;
default:
return "";
}
s.append("physical_address: ").append(mPhysicalAddress).append(", ");
s.append("physical_address: ").append(String.format("0x04X", mPhysicalAddress)).append(" ");
s.append("port_id: ").append(mPortId);
return s.toString();
}

View File

@@ -43,7 +43,7 @@ interface IHdmiControlService {
void addHotplugEventListener(IHdmiHotplugEventListener listener);
void removeHotplugEventListener(IHdmiHotplugEventListener listener);
void addDeviceEventListener(IHdmiDeviceEventListener listener);
void deviceSelect(int logicalAddress, IHdmiControlCallback callback);
void deviceSelect(int deviceId, IHdmiControlCallback callback);
void portSelect(int portId, IHdmiControlCallback callback);
void sendKeyEvent(int deviceType, int keyCode, boolean isPressed);
List<HdmiPortInfo> getPortInfo();

View File

@@ -25,6 +25,6 @@ import android.media.tv.TvInputInfo;
*/
oneway interface ITvInputServiceCallback {
void addHardwareTvInput(in int deviceId, in TvInputInfo inputInfo);
void addHdmiTvInput(in int logicalAddress, in TvInputInfo inputInfo);
void addHdmiTvInput(in int id, in TvInputInfo inputInfo);
void removeTvInput(in String inputId);
}

View File

@@ -112,7 +112,7 @@ public final class TvInputInfo implements Parcelable {
private static final String PREFIX_HDMI_DEVICE = "HDMI";
private static final String PREFIX_HARDWARE_DEVICE = "HW";
private static final int LENGTH_HDMI_PHYSICAL_ADDRESS = 4;
private static final int LENGTH_HDMI_LOGICAL_ADDRESS = 2;
private static final int LENGTH_HDMI_DEVICE_ID = 2;
private final ResolveInfo mService;
private final String mId;
@@ -536,9 +536,9 @@ public final class TvInputInfo implements Parcelable {
ComponentName name, HdmiDeviceInfo deviceInfo) {
// Example of the format : "/HDMI%04X%02X"
String format = String.format("%s%s%%0%sX%%0%sX", DELIMITER_INFO_IN_ID, PREFIX_HDMI_DEVICE,
LENGTH_HDMI_PHYSICAL_ADDRESS, LENGTH_HDMI_LOGICAL_ADDRESS);
LENGTH_HDMI_PHYSICAL_ADDRESS, LENGTH_HDMI_DEVICE_ID);
return name.flattenToShortString() + String.format(format,
deviceInfo.getPhysicalAddress(), deviceInfo.getLogicalAddress());
deviceInfo.getPhysicalAddress(), deviceInfo.getId());
}
/**

View File

@@ -213,7 +213,7 @@ public abstract class TvInputService extends Service {
}
/**
* Returns the input ID for {@code logicalAddress} if it is handled by this service; otherwise,
* Returns the input ID for {@code deviceInfo} if it is handled by this service; otherwise,
* return {@code null}. Override to modify default behavior of ignoring all HDMI logical input
* device.
*
@@ -1178,11 +1178,11 @@ public abstract class TvInputService extends Service {
mCallbacks.finishBroadcast();
}
private void broadcastAddHdmiTvInput(int logicalAddress, TvInputInfo inputInfo) {
private void broadcastAddHdmiTvInput(int id, TvInputInfo inputInfo) {
int n = mCallbacks.beginBroadcast();
for (int i = 0; i < n; ++i) {
try {
mCallbacks.getBroadcastItem(i).addHdmiTvInput(logicalAddress, inputInfo);
mCallbacks.getBroadcastItem(i).addHdmiTvInput(id, inputInfo);
} catch (RemoteException e) {
Log.e(TAG, "Error while broadcasting.", e);
}
@@ -1289,7 +1289,7 @@ public abstract class TvInputService extends Service {
HdmiDeviceInfo deviceInfo = (HdmiDeviceInfo) msg.obj;
TvInputInfo inputInfo = onHdmiDeviceAdded(deviceInfo);
if (inputInfo != null) {
broadcastAddHdmiTvInput(deviceInfo.getLogicalAddress(), inputInfo);
broadcastAddHdmiTvInput(deviceInfo.getId(), inputInfo);
}
return;
}

View File

@@ -100,7 +100,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
private List<HdmiDeviceInfo> mSafeExternalInputs = Collections.emptyList();
// Map-like container of all cec devices including local ones.
// A logical address of device is used as key of container.
// device id is used as key of container.
// This is not thread-safe. For external purpose use mSafeDeviceInfos.
private final SparseArray<HdmiDeviceInfo> mDeviceInfos = new SparseArray<>();
@@ -167,12 +167,19 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
/**
* Performs the action 'device select', or 'one touch play' initiated by TV.
*
* @param targetAddress logical address of the device to select
* @param id id of HDMI device to select
* @param callback callback object to report the result with
*/
@ServiceThreadOnly
void deviceSelect(int targetAddress, IHdmiControlCallback callback) {
void deviceSelect(int id, IHdmiControlCallback callback) {
assertRunOnServiceThread();
HdmiDeviceInfo targetDevice = mDeviceInfos.get(id);
if (targetDevice == null) {
invokeCallback(callback, HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
return;
}
// TODO: Handle MHL device
int targetAddress = targetDevice.getLogicalAddress();
ActiveSource active = getActiveSource();
if (active.isValid() && targetAddress == active.logicalAddress) {
invokeCallback(callback, HdmiControlManager.RESULT_SUCCESS);
@@ -187,18 +194,10 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
return;
}
if (!mService.isControlEnabled()) {
HdmiDeviceInfo info = getDeviceInfo(targetAddress);
if (info != null) {
setActiveSource(info);
}
setActiveSource(targetDevice);
invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE);
return;
}
HdmiDeviceInfo targetDevice = getDeviceInfo(targetAddress);
if (targetDevice == null) {
invokeCallback(callback, HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE);
return;
}
removeAction(DeviceSelectAction.class);
addAndStartAction(new DeviceSelectAction(this, targetDevice, callback));
}
@@ -231,7 +230,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
}
setActiveSource(newActive);
int logicalAddress = newActive.logicalAddress;
if (getDeviceInfo(logicalAddress) != null && logicalAddress != mAddress) {
if (getCecDeviceInfo(logicalAddress) != null && logicalAddress != mAddress) {
if (mService.pathToPortId(newActive.physicalAddress) == getActivePortId()) {
setPrevPortId(getActivePortId());
}
@@ -279,7 +278,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
// Show OSD port change banner
if (notifyInputChange) {
ActiveSource activeSource = getActiveSource();
HdmiDeviceInfo info = getDeviceInfo(activeSource.logicalAddress);
HdmiDeviceInfo info = getCecDeviceInfo(activeSource.logicalAddress);
if (info == null) {
info = new HdmiDeviceInfo(Constants.ADDR_INVALID, path, portId,
HdmiDeviceInfo.DEVICE_RESERVED, 0, null);
@@ -363,7 +362,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
assertRunOnServiceThread();
int logicalAddress = message.getSource();
int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams());
if (getDeviceInfo(logicalAddress) == null) {
if (getCecDeviceInfo(logicalAddress) == null) {
handleNewDeviceAtTheTailOfActivePath(physicalAddress);
} else {
ActiveSource activeSource = ActiveSource.of(logicalAddress, physicalAddress);
@@ -389,7 +388,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
if (portId != Constants.INVALID_PORT_ID) {
// TODO: Do this only if TV is not showing multiview like PIP/PAP.
HdmiDeviceInfo inactiveSource = getDeviceInfo(message.getSource());
HdmiDeviceInfo inactiveSource = getCecDeviceInfo(message.getSource());
if (inactiveSource == null) {
return true;
}
@@ -577,7 +576,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
@ServiceThreadOnly
protected boolean handleSetOsdName(HdmiCecMessage message) {
int source = message.getSource();
HdmiDeviceInfo deviceInfo = getDeviceInfo(source);
HdmiDeviceInfo deviceInfo = getCecDeviceInfo(source);
// If the device is not in device list, ignore it.
if (deviceInfo == null) {
Slog.e(TAG, "No source device info for <Set Osd Name>." + message);
@@ -952,11 +951,11 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
@ServiceThreadOnly
private HdmiDeviceInfo addDeviceInfo(HdmiDeviceInfo deviceInfo) {
assertRunOnServiceThread();
HdmiDeviceInfo oldDeviceInfo = getDeviceInfo(deviceInfo.getLogicalAddress());
HdmiDeviceInfo oldDeviceInfo = getCecDeviceInfo(deviceInfo.getLogicalAddress());
if (oldDeviceInfo != null) {
removeDeviceInfo(deviceInfo.getLogicalAddress());
removeDeviceInfo(deviceInfo.getId());
}
mDeviceInfos.append(deviceInfo.getLogicalAddress(), deviceInfo);
mDeviceInfos.append(deviceInfo.getId(), deviceInfo);
updateSafeDeviceInfoList();
return oldDeviceInfo;
}
@@ -967,15 +966,15 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
*
* <p>Declared as package-private. accessed by {@link HdmiControlService} only.
*
* @param logicalAddress logical address of device to be removed
* @param id id of device to be removed
* @return removed {@link HdmiDeviceInfo} it exists. Otherwise, returns {@code null}
*/
@ServiceThreadOnly
private HdmiDeviceInfo removeDeviceInfo(int logicalAddress) {
private HdmiDeviceInfo removeDeviceInfo(int id) {
assertRunOnServiceThread();
HdmiDeviceInfo deviceInfo = mDeviceInfos.get(logicalAddress);
HdmiDeviceInfo deviceInfo = mDeviceInfos.get(id);
if (deviceInfo != null) {
mDeviceInfos.remove(logicalAddress);
mDeviceInfos.remove(id);
}
updateSafeDeviceInfoList();
return deviceInfo;
@@ -1035,7 +1034,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
ArrayList<HdmiDeviceInfo> infoList = new ArrayList<>();
for (int i = 0; i < mDeviceInfos.size(); ++i) {
HdmiDeviceInfo info = mDeviceInfos.valueAt(i);
if (isLocalDeviceAddress(i)) {
if (isLocalDeviceAddress(info.getLogicalAddress())) {
continue;
}
if (info.isSourceType() && !hideDevicesBehindLegacySwitch(info)) {
@@ -1095,23 +1094,22 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
@ServiceThreadOnly
HdmiDeviceInfo getAvrDeviceInfo() {
assertRunOnServiceThread();
return getDeviceInfo(Constants.ADDR_AUDIO_SYSTEM);
return getCecDeviceInfo(Constants.ADDR_AUDIO_SYSTEM);
}
/**
* Return a {@link HdmiDeviceInfo} corresponding to the given {@code logicalAddress}.
*
* <p>Declared as package-private. accessed by {@link HdmiControlService} only.
* This is not thread-safe. For thread safety, call {@link #getSafeDeviceInfo(int)}.
* This is not thread-safe. For thread safety, call {@link #getSafeCecDeviceInfo(int)}.
*
* @param logicalAddress logical address to be retrieved
* @param address logical address of the device to be retrieved
* @return {@link HdmiDeviceInfo} matched with the given {@code logicalAddress}.
* Returns null if no logical address matched
*/
@ServiceThreadOnly
HdmiDeviceInfo getDeviceInfo(int logicalAddress) {
HdmiDeviceInfo getCecDeviceInfo(int logicalAddress) {
assertRunOnServiceThread();
return mDeviceInfos.get(logicalAddress);
return mDeviceInfos.get(HdmiDeviceInfo.idForCecDevice(logicalAddress));
}
boolean hasSystemAudioDevice() {
@@ -1119,19 +1117,24 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
}
HdmiDeviceInfo getSafeAvrDeviceInfo() {
return getSafeDeviceInfo(Constants.ADDR_AUDIO_SYSTEM);
return getSafeCecDeviceInfo(Constants.ADDR_AUDIO_SYSTEM);
}
/**
* Thread safe version of {@link #getDeviceInfo(int)}.
* Thread safe version of {@link #getCecDeviceInfo(int)}.
*
* @param logicalAddress logical address to be retrieved
* @return {@link HdmiDeviceInfo} matched with the given {@code logicalAddress}.
* Returns null if no logical address matched
*/
HdmiDeviceInfo getSafeDeviceInfo(int logicalAddress) {
HdmiDeviceInfo getSafeCecDeviceInfo(int logicalAddress) {
synchronized (mLock) {
return mSafeAllDeviceInfos.get(logicalAddress);
for (HdmiDeviceInfo info : mSafeAllDeviceInfos) {
if (info.isCecDevice() && info.getLogicalAddress() == logicalAddress) {
return info;
}
}
return null;
}
}
@@ -1160,7 +1163,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
@ServiceThreadOnly
final void removeCecDevice(int address) {
assertRunOnServiceThread();
HdmiDeviceInfo info = removeDeviceInfo(address);
HdmiDeviceInfo info = removeDeviceInfo(HdmiDeviceInfo.idForCecDevice(address));
mCecMessageCache.flushMessagesFrom(address);
invokeDeviceEventListener(info, HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE);
@@ -1240,7 +1243,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
@ServiceThreadOnly
boolean isInDeviceList(int logicalAddress, int physicalAddress) {
assertRunOnServiceThread();
HdmiDeviceInfo device = getDeviceInfo(logicalAddress);
HdmiDeviceInfo device = getCecDeviceInfo(logicalAddress);
if (device == null) {
return false;
}
@@ -1427,7 +1430,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
}
private boolean checkRecorder(int recorderAddress) {
HdmiDeviceInfo device = getDeviceInfo(recorderAddress);
HdmiDeviceInfo device = getCecDeviceInfo(recorderAddress);
return (device != null)
&& (HdmiUtils.getTypeFromAddress(recorderAddress)
== HdmiDeviceInfo.DEVICE_RECORDER);
@@ -1528,7 +1531,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
}
void updateDevicePowerStatus(int logicalAddress, int newPowerStatus) {
HdmiDeviceInfo info = getDeviceInfo(logicalAddress);
HdmiDeviceInfo info = getCecDeviceInfo(logicalAddress);
if (info == null) {
Slog.w(TAG, "Can not update power status of non-existing device:" + logicalAddress);
return;

View File

@@ -561,7 +561,7 @@ public final class HdmiControlService extends SystemService {
if (tv == null) {
return null;
}
return tv.getDeviceInfo(logicalAddress);
return tv.getCecDeviceInfo(logicalAddress);
}
/**
@@ -942,7 +942,7 @@ public final class HdmiControlService extends SystemService {
}
@Override
public void deviceSelect(final int logicalAddress, final IHdmiControlCallback callback) {
public void deviceSelect(final int deviceId, final IHdmiControlCallback callback) {
enforceAccessPermission();
runOnServiceThread(new Runnable() {
@Override
@@ -957,7 +957,7 @@ public final class HdmiControlService extends SystemService {
invokeCallback(callback, HdmiControlManager.RESULT_SOURCE_NOT_AVAILABLE);
return;
}
tv.deviceSelect(logicalAddress, callback);
tv.deviceSelect(deviceId, callback);
}
});
}

View File

@@ -207,7 +207,7 @@ final class HotplugDetectionAction extends HdmiCecFeatureAction {
}
private void mayChangeRoutingPath(int address) {
HdmiDeviceInfo info = tv().getDeviceInfo(address);
HdmiDeviceInfo info = tv().getCecDeviceInfo(address);
if (info != null) {
tv().handleRemoveActiveRoutingPath(info.getPhysicalAddress());
}

View File

@@ -284,7 +284,7 @@ class TvInputHardwareManager implements TvInputHal.Callback {
return -1;
}
public void addHdmiTvInput(int logicalAddress, TvInputInfo info) {
public void addHdmiTvInput(int id, TvInputInfo info) {
if (info.getType() != TvInputInfo.TYPE_HDMI) {
throw new IllegalArgumentException("info (" + info + ") has non-HDMI type.");
}
@@ -294,13 +294,13 @@ class TvInputHardwareManager implements TvInputHal.Callback {
if (parentIndex < 0) {
throw new IllegalArgumentException("info (" + info + ") has invalid parentId.");
}
String oldInputId = mHdmiInputIdMap.get(logicalAddress);
String oldInputId = mHdmiInputIdMap.get(id);
if (oldInputId != null) {
Slog.w(TAG, "Trying to override previous registration: old = "
+ mInputMap.get(oldInputId) + ":" + logicalAddress + ", new = "
+ info + ":" + logicalAddress);
+ mInputMap.get(oldInputId) + ":" + id + ", new = "
+ info + ":" + id);
}
mHdmiInputIdMap.put(logicalAddress, info.getId());
mHdmiInputIdMap.put(id, info.getId());
mInputMap.put(info.getId(), info);
}
}

View File

@@ -1971,11 +1971,11 @@ public final class TvInputManagerService extends SystemService {
}
@Override
public void addHdmiTvInput(int logicalAddress, TvInputInfo inputInfo) {
public void addHdmiTvInput(int id, TvInputInfo inputInfo) {
ensureHardwarePermission();
ensureValidInput(inputInfo);
synchronized (mLock) {
mTvInputHardwareManager.addHdmiTvInput(logicalAddress, inputInfo);
mTvInputHardwareManager.addHdmiTvInput(id, inputInfo);
addTvInputLocked(inputInfo);
}
}